Skip to content

A new client enquiry

Markdown

Fernhill Studio is Sam Rivera’s design studio. Besides Roadstar, Sam has Client desk, Proposal writer and Bookkeeper.

In Client desk’s chat:

When a new client writes in, answer the same day. Quotes come from the rate card in Drive, and I see every quote before it goes out.

Client desk’s chat set a routine from those words. The routine’s note is Sam’s rule, so every run carries it:

triggers
{
"action": "add",
"name": "New client enquiries",
"when": { "ask": "a new client asking about a project or a quote" },
"note": "Answer the same day. Quotes come from the rate card in Drive, and Sam sees every quote before it goes out."
}

On Tuesday at 10:12, Dana Whitfield of Juniper Dental emails Sam asking for a quote on a new logo and signage before their second clinic opens in March. The email matches the routine’s words, and the run goes to the routine’s own thread, “New client enquiries”. The thread has every tool, and remembers the enquiries before this one.

2. The thread reads the email and records the client

Section titled “2. The thread reads the email and records the client”
use_tool
{ "name": "mail.read", "input": { "id": "7c41e2d0:19a2c4e07d5b3f18" } }
use_tool
{ "name": "contacts.find", "input": { "email": "dana@juniperdental.test" } }

contacts.find returns null: Juniper Dental is new. Adding records needs no yes, so the thread adds the company, then Dana, then the conversation:

use_tool
{
"name": "companies.create",
"input": { "name": "Juniper Dental", "domains": ["juniperdental.test"], "labels": ["Lead"] }
}
use_tool
{
"name": "contacts.create",
"input": {
"name": "Dana Whitfield",
"emails": ["dana@juniperdental.test"],
"jobTitle": "Practice manager",
"labels": ["Lead"],
"companyIds": ["3f1c9a52-7b0e-4d61-9a8f-2c5e1b7d4a90"]
}
}
use_tool
{
"name": "companies.record",
"input": {
"companyId": "3f1c9a52-7b0e-4d61-9a8f-2c5e1b7d4a90",
"kind": "mail",
"title": "Rebrand quote request",
"summary": "Dana asked for a new logo and signage before the second clinic opens in March.",
"at": "2026-11-10T10:12:00Z",
"people": ["dana@juniperdental.test"],
"thread": "7c41e2d0:19a2c4e07d5b3f18",
"state": "waiting_you"
}
}

3. It hands the pricing to Proposal writer

Section titled “3. It hands the pricing to Proposal writer”

Proposal writer owns quotes. It hasn’t seen this thread, so the packet carries the task, the facts no link holds, and links to what to read:

hand_off
{
"agent": "Proposal writer",
"task": "Price a rebrand for Juniper Dental from the rate card: new logo, and signage for two clinics.",
"notes": "Second clinic opens in March. Dana Whitfield, practice manager, signs off.",
"links": ["mail:7c41e2d0:19a2c4e07d5b3f18", "contact:8d2e6b14-3a7c-4f09-b5d1-6e0a9c3f7b22"]
}

hand_off returns { "handed": "Proposal writer", "answer": "comes back to you" }. The thread ends its turn; the answer will wake it.

The packet reaches Proposal writer’s chat. No thread holds Juniper Dental yet, so the chat starts one:

start_thread
{
"title": "Juniper Dental",
"task": "Price a rebrand for Juniper Dental from the rate card: new logo, and signage for two clinics.",
"notes": "Second clinic opens in March. Dana Whitfield, practice manager, signs off.",
"links": ["mail:7c41e2d0:19a2c4e07d5b3f18"]
}

The thread finds the rate card and writes the quote as a doc:

use_tool
{ "name": "files.search", "input": { "query": "rate card 2026" } }
use_tool
{ "name": "files.read", "input": { "id": "7c41e2d0:1QmR8vT3kLp0aZ7xYc2NwE5sHd6jUb4oF" } }
use_tool
{
"name": "docs.write",
"input": {
"projectId": "c7a04e2b-91d5-4b38-8f6e-0d2a5c9b1e47",
"title": "Juniper Dental rebrand quote",
"text": "## Scope\n\n- Logo and a one-page brand guide\n- Signage for two clinics: exterior, reception, rooms\n\n## Price\n\n| Item | Price |\n| --- | ---: |\n| Logo and brand guide | $4,800 |\n| Signage design, two clinics | $3,600 |\n| **Total** | **$8,400** |\n\nReady in five weeks from a signed quote.",
"lines": ["Priced from the 2026 rate card: logo $4,800, signage $3,600."]
}
}

Its answer, the doc and “$8,400, ready in five weeks”, goes back to Client desk’s “New client enquiries” thread.

Sam’s rule says Sam sees every quote first, so the thread asks in its reply instead of sending:

Send Dana the Juniper Dental quote for $8,400? Logo, brand guide and signage for both clinics, ready in five weeks.

Sam answers “Yes, send it” in Client desk’s chat. The chat sends the answer to the thread that holds the work:

message_thread
{ "thread": "New client enquiries", "task": "Sam says yes: send Dana the Juniper Dental quote as written." }

The thread sends:

use_tool
{
"name": "mail.send",
"input": {
"to": ["dana@juniperdental.test"],
"subject": "Re: Rebrand for our second clinic",
"threadId": "7c41e2d0:19a2c4e07d5b3f18",
"text": "Hi Dana,\n\nThanks for thinking of us. For a new logo with a one-page brand guide, and signage for both clinics, the price is $8,400, ready five weeks after you sign. Happy to walk through it on a call.\n\nSam"
}
}

mail.send sends outside the business, so the check reads it first. Sam’s yes answered an ask that named Dana, so it goes. The email leaves after a two-minute Undo on Home.

The thread follows Sam’s rule itself; the check is a backstop. Had the thread sent before asking, the check would read Sam’s rule too, nothing would go out, and use_tool would return the check’s reason instead:

{ "not_done_yet": "Check with Sam first: <reason>. Ask in your reply, saying what you would do. Once they say yes, do it again." }

The reasons it can give are on The owner’s yes.

  • Client desk’s ask with the quote, then the sent email on Home with Undo for two minutes.
  • Juniper Dental under Companies, with Dana and the conversation on its timeline.
  • The quote under Docs.