URL: /capabilities/reach-out/account-brief · Id: `page:/capabilities/reach-out/account-brief`

# Account brief

> Two hours before each call: why they are buying now, the objection to expect, the story to tell and the question to ask, all sourced.

Two hours before each call: why they are buying now, the objection to expect, the story to tell and the question to ask, all sourced.

```text title="Run it · Ask"
Brief me on the three companies I am meeting tomorrow, spend up to $1, and show me the plan first.
```

```ts title="Run it · SDK"
import { $ } from 'startup-builder'

const result = await $.try.Deal.brief({ goal: 'Brief me on the three companies I am meeting tomorrow, spend up to $1, and show me the plan first.', budget: { amount: 1, currency: 'USD' } })
```

```json title="Run it · Response"
{
  "mode": "try",
  "stored": false,
  "estimate": "About 9.3¢ a brief",
  "sample": {
    "deal": "Harbor Point Residential",
    "why now": "hiring a second leasing coordinator",
    "objection": "already pays for a property management suite",
    "question": "Who chases a renewal today, and how do they know it is due?"
  }
}
```

- **Kind:** Agent task
- **Price:** 9.3¢ per brief
- **Your time:** 5 minutes
- **Approval:** Runs on its own
- **Deepens:** [`process:inbound-sales`](https://startupbuilder.dev/workflows/processes/inbound-sales)

## What you get
- **1 brief** · Two hours before each call: why they are buying now, the objection to expect, the story to tell and the question to ask, all sourced. · [`noun:deal`](https://startupbuilder.dev/business/nouns/deal)
- `whyNow` · The change that makes this a live buyer, with its source: a hire, a round, growth, a tool dropped.
- `objections[]` · What they will likely push back on, from what they run today and what they said.
- `story` · The customer story closest to their situation, from your records.
- `question` · The one question that surfaces the pain in their own words.
- `sources[]` · Every page and record a line rests on.

**Connect once:** [Google Calendar](/code/integrations/google-calendar). **How long:** About a minute; it lands two hours before the call.

## Trigger
It runs two hours before each booked meeting.

```ts
on.Meeting.booked((meeting, $) => $.Deal.brief({ deal: meeting.deal, before: '2h' }))
```

## Steps
Your agent does these steps, one row per step; each step’s check is part of its row and its price.

| Step | Verb | Returns | Price | Approval |
| --- | --- | --- | --- | --- |
| 1. Read the company’s profile | [`Organization.enrich`](/code/data/organizations/enrich) | Headcount and its trend, location, founding year | About 0.2¢ | Runs on its own |
| 2. Read what just happened there | [`Organization.enrich`](/code/data/organizations/enrich) | Funding, news and launches in the last 90 days | About 1¢ | Runs on its own |
| 3. Read its open roles | [`Organization.enrich`](/code/data/organizations/enrich) | The roles it is hiring for, the clearest sign of where the pain is growing | About 1¢ | Runs on its own |
| 4. Read the products it runs | [`Organization.enrich`](/code/data/organizations/enrich) | The tools on its site, so the brief knows what you replace or sit beside | About 4¢ | Runs on its own |
| 5. Read each attendee | [`Contact.enrich`](/code/data/people/enrich) | Title, tenure and past roles for each person on the call | About 0.6¢ | Runs on its own |
| 6. Read their site | [`Page.audit`](/code/data/pages-and-sites/audit-page) | Home, about, careers and two service pages | About 0.1¢ | Runs on its own |
| 7. Search what they say about rivals | [`Keyword.search`](/code/data/keywords/search) | Posts that name the company beside a rival | About 0.19¢ | Runs on its own |
| 8. Write the brief | `Content.draft` | Why now, the objection, the story and the question, each line with its source | About 2.2¢ | Runs on its own |

Calls: `Organization.enrich`, then `Contact.enrich`, then `Page.audit`, then `Keyword.search`, then `Content.draft`.

About 9.3¢ a brief, each time it runs, capped at 30¢.

## Example: give it a goal
> Brief me on the three companies I am meeting tomorrow, spend up to $1, and show me the plan first.

The plan it shows runs 8 steps, priced before it spends anything; Run it above shows the result it returns.

## When something fails

| When | Then |
| --- | --- |
| Fewer than two facts have a source | The brief says so at the top instead of padding; a thin brief still lands on time. |
| A line fails the grade | It is cut and the brief is rewritten once; the redo is free. |
| The meeting moves | The brief moves with it; reads younger than 7 days are reused at $0. |
| You ask twice for one meeting | The same brief returns: it is idempotent per deal and meeting. |

Each step retries three times, then falls through to the next route; one item's failure lands in `skipped` with its reason, never failing the call. Before a step would cross `maxCost` it stops and returns what it has, with a `resume` link. Each step's idempotency key is the call's key plus the step and the item: `leaseline-deal-brief-1-<step>-<item>`.

## How it is graded
A second model checks each line of the brief against the page or record it cites. It passes when every line has a source that says it, the why-now is under 90 days old, and the question is one sentence. A miss is redone at no charge.

## Change it
| Ask | Compiles to |
| --- | --- |
| Add their likely budget from their headcount. | [`Deal.brief`](/capabilities/reach-out/account-brief) |
| Send it the night before instead. | [`Deal.brief`](/capabilities/reach-out/account-brief) |
| Brief me on everyone who books from my cold email. | [`Deal.brief`](/capabilities/reach-out/account-brief) |

```ts
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'deal-brief',
  verb: 'Deal.brief',
  input: { deal: 'string', attendees: 'string[]?', before: 'string' },
  trigger: { event: 'Meeting.booked' },
  maxCost: 0.3,
  grade: { evaluator: 'each line against its source', passWhen: 'every line sourced; why-now under 90 days; one question', remedy: 'redo' },
  execute: async (ctx, { deal, attendees, before = '2h' }) => {
    const d = await ctx.step('deal', () => $.Collection.query({ from: 'deal', id: deal, with: ['organization', 'meeting'] }))
    const org = await ctx.step('company', () => $.Organization.enrich({ hostname: d.organization.hostname, fields: ['profile', 'events', 'hiring', 'technologies'], maxCost: 0.08 }))
    const people = await ctx.step('people', () => $.Contact.enrich({ contacts: attendees ?? d.meeting.guests, fields: ['title', 'history'], maxCost: 0.03 }))
    const site = await ctx.step('site', () => $.Page.audit({ urls: keyPages(d.organization.hostname, 5), fields: ['content'], maxCost: 0.01 }))
    const rivals = await ctx.step('rivals', () => $.Keyword.search({ keywords: [d.organization.name], venue: 'reddit', maxCost: 0.01 }))
    return ctx.step('brief', () => $.Content.draft({ kind: 'account-brief', from: { org, people, site, rivals }, deliverAt: { before: d.meeting.at, by: before }, maxCost: 0.03 }))
  },
})
```

Extend it with `extends: 'Deal.brief'` and `base()`, or [compose your own](/code/compose) from these steps.

## Works with
**Plays that order it:** [Account visits](/plays/account-visits), [Buying committee](/plays/buying-committee), [Closer handoff](/plays/closer-handoff), [Data residency](/plays/data-residency), [Show up in person](/plays/field-presence), [Hosted gatherings](/plays/gatherings), [Gifting](/plays/gifting), [Outbound calling](/plays/outbound-calling), [Paid pilot](/plays/paid-pilot), [Product signals](/plays/product-signals), [Proof-of-work outreach](/plays/proof-of-work-outreach), [Risk-reversal offers](/plays/risk-reversal-offers), [Waitlist interviews](/plays/signup-interviews), [Trust pack](/plays/trust-pack), [Warm intros](/plays/warm-intros), [Written references](/plays/written-references).

It serves [Reach out](/capabilities/reach-out), and runs in [Hands-on](/strategy/hands-on). It deepens [`process:inbound-sales`](https://startupbuilder.dev/workflows/processes/inbound-sales).

## For agents

| Fact | Value |
| --- | --- |
| Guide | `Deal.brief` |
| Guide approval | `limits` |
| Goal | Brief me on the three companies I am meeting tomorrow, spend up to $1, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval. |
| Trigger | `on.Meeting.booked((meeting, $) => $.Deal.brief({ deal: meeting.deal, before: '2h' }))` |
| Retry | Three times with backoff, then the next route; the same idempotency key never charges, sends or posts twice |
| Idempotency key | `leaseline-deal-brief-1` |
| Lookups | A `find:` input asks unless exactly one record fits |

| Step | Action class | Seat rule that would hold it |
| --- | --- | --- |
| 1. Read the company’s profile | None | None. |
| 2. Read what just happened there | None | None. |
| 3. Read its open roles | None | None. |
| 4. Read the products it runs | None | None. |
| 5. Read each attendee | None | None. |
| 6. Read their site | None | None. |
| 7. Search what they say about rivals | None | None. |
| 8. Write the brief | None | None. |

The amounts live once, on the hub ([approvals](https://startupbuilder.dev/agents/approvals)).

| Step | Function | Doer | Checker | Assurance | Inputs |
| --- | --- | --- | --- | --- | --- |
| 1. Read the company’s profile | `code` | Code | Code checks each result against its declared type | `measured` | `$0.deal.organization` |
| 2. Read what just happened there | `code` | Code | Code checks each result against its declared type | `measured` | `$0.deal.organization` |
| 3. Read its open roles | `code` | Code | Code checks each result against its declared type | `measured` | `$0.deal.organization` |
| 4. Read the products it runs | `code` | Code | Code checks each result against its declared type | `measured` | `$0.deal.organization` |
| 5. Read each attendee | `code` | Code | Code checks each result against its declared type | `measured` | `$0.attendees` |
| 6. Read their site | `code` | Code | Code checks each result against its declared type | `measured` | `$0.deal.organization` |
| 7. Search what they say about rivals | `code` | Code | Code checks each result against its declared type | `measured` | `$0.deal.organization` |
| 8. Write the brief | `agentic` | The [AE](/capabilities/agents/ae) agent | Adversarial review by a second model: Pass, or the unsourced line cut | `graded` | `$1..$7, offer` |

The doer is never the checker, and the weakest assurance on the path is the whole call’s.

## Under the hood

| Kind | What it touches |
| --- | --- |
| Systems | [CRM](/code/apps/crm), [sites and content](/code/apps/sites-and-content) |
| Nouns | [`noun:organization`](https://startupbuilder.dev/business/nouns/organization), [`noun:contact`](https://startupbuilder.dev/business/nouns/contact), [`noun:page`](https://startupbuilder.dev/business/nouns/page), [`noun:keyword`](https://startupbuilder.dev/business/nouns/keyword), [`noun:content`](https://startupbuilder.dev/business/nouns/content), [`noun:action`](https://startupbuilder.dev/business/nouns/action) |
| Events | `Contact.enriched`, `Content.drafted`, `Action.evaluated` |

## Reference

| Name | Type | Default | Meaning |
| --- | --- | --- | --- |
| `deal` | `Deal` | Required | The deal the call is for. |
| `attendees` | `Contact[]` | `the Meeting’s guests` | The people on the call, up to five. |
| `before` | `string` | `'2h'` | How long before the meeting the brief lands. |
| `maxCost` | `number` | `0.30` | The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a `resume` link. |

Emits `Deal.briefed`. Refuses with [`max-cost`](/code/refusals#max-cost) before it spends, and with the Data calls and Accounts groups ([refusals](/code/refusals)).