---
title: A new client enquiry
description: Client desk answers Juniper Dental's request for a quote, Proposal writer prices it from the rate card, and Sam approves it before it goes.
agents: [Client desk, Proposal writer]
tools: [triggers, mail.read, contacts.find, companies.create, contacts.create, companies.record, hand_off, start_thread, files.search, files.read, docs.write, message_thread, mail.send]
source: [packages/agents/src/router.ts, packages/agents/src/tools/team.ts, packages/agents/src/tools/threads.ts]
---

> Roadstar docs for agents. Every page, as markdown: https://docs.roadstar.app/llms.txt

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

## What Sam said

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:

```json title="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."
}
```

## 1. The routine fires

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

```json title="use_tool"
{ "name": "mail.read", "input": { "id": "7c41e2d0:19a2c4e07d5b3f18" } }
```

```json title="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:

```json title="use_tool"
{
  "name": "companies.create",
  "input": { "name": "Juniper Dental", "domains": ["juniperdental.test"], "labels": ["Lead"] }
}
```

```json title="use_tool"
{
  "name": "contacts.create",
  "input": {
    "name": "Dana Whitfield",
    "emails": ["dana@juniperdental.test"],
    "jobTitle": "Practice manager",
    "labels": ["Lead"],
    "companyIds": ["3f1c9a52-7b0e-4d61-9a8f-2c5e1b7d4a90"]
  }
}
```

```json title="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

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:

```json title="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.

## 4. Proposal writer writes the quote

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

```json title="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:

```json title="use_tool"
{ "name": "files.search", "input": { "query": "rate card 2026" } }
```

```json title="use_tool"
{ "name": "files.read", "input": { "id": "7c41e2d0:1QmR8vT3kLp0aZ7xYc2NwE5sHd6jUb4oF" } }
```

```json title="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.

## 5. Sam approves, and the thread sends

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:

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

The thread sends:

```json title="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:

```json
{ "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](/how-it-works/the-owners-yes/#reasons).

## What Sam sees

- 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.

## Related

- [The owner's yes](/how-it-works/the-owners-yes/): when the check asks, and what the agent reads back
- [Hand-offs](/how-it-works/hand-offs/): packets, and where answers go
- [Routines and skills](/how-it-works/routines-and-skills/): `when.ask`, schedules and events
- Tools: [mail](/tools/mail/), [contacts](/tools/contacts/), [companies](/tools/companies/), [docs](/tools/docs/), [files](/tools/files/)
