Moment outreach
Writes to a company only in the window a public Event opens, like a new head of operations, then waits for the next.
- Channel
- Email and inboxes
- Kind
- Outreach
Be our SDR: write to a property manager only when they announce something we help with, like a new head of operations or a reposted leasing job. Three touches, then wait. Over 120 units, book our AE; our top 25 go from my mailbox. Show me what’s missing; don’t send.
# Not live yet (gaps #2)
curl -X POST "https://api.sb/leaseline.app/campaigns?mode=try" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"play":"moment-outreach"}'import { $ } from 'startup-builder'
return await $.Campaign.create({ play: 'moment-outreach' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-08-24 · Not live yet, gaps #2
npx startup-builder do Campaign.create --json '{"play":"moment-outreach"}' --try # Not live yet (gaps #2){
"name": "do",
"arguments": {
"code": "return await $.Campaign.create({ play: 'moment-outreach' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-08-24 · Not live yet, gaps #2",
"mode": "try"
}
}application/json{
"type": "https: //startupbuilder.dev/ errors/ refused",
"title": "Refused",
"status": 422,
"detail": "moment-outreach can’t start yet: 2 checks fail and 1 warns.",
"checks": [
{
"check": "use-when",
"status": "pass",
"observed": "46 windows a week on your List across 3 Triggers",
"doc": "/plays/ moment-outreach#check-use-when",
"fix": "Keep 3 Triggers on; switch on more only once each has a ready output.",
"then": "Metric.query"
},
…
Hand the latest window that opened on our List to the SDR agent and show me what it chose and why. Don’t send.
curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Organization.appointed%22%2C%20%22Organization.reposted%22%2C%20%22Organization.announced%22%2C%20%22Organization.published%22%2C%20%22Organization.filed%22%2C%20%22Company.filed%22%2C%20%22Company.funded%22%2C%20%22Opening.published%22%2C%20%22Organization.repriced%22%2C%20%22Organization.degraded%22%2C%20%22Organization.deprecated%22%2C%20%22Visit.recorded%22%2C%20%22Monitor.checked%22%2C%20%22Organization.adopted%22%2C%20%22Organization.downsized%22%2C%20%22Organization.disrupted%22%2C%20%22Organization.acquired%22)&limit=1" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
# Not live yet (gaps #7)
curl -X POST "https://api.sb/leaseline.app/triggers/fire?mode=try" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"like":"event_1312"}'
# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22prospect_31%22" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/actions?where=on%20%3D%20%22prospect_31%22" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"import { $ } from 'startup-builder'
const { events: [last] } = await $.Event.list({ where: 'name in ("Organization.appointed", "Organization.reposted", "Organization.announced", "Organization.published", "Organization.filed", "Company.filed", "Company.funded", "Opening.published", "Organization.repriced", "Organization.degraded", "Organization.deprecated", "Visit.recorded", "Monitor.checked", "Organization.adopted", "Organization.downsized", "Organization.disrupted", "Organization.acquired")', limit: 1 }) // { play } compiled to this Play’s Trigger Events
const { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' }) // the same Event again, in try mode · Not live yet, gaps #7
const { decisions: [decision] } = await $.Decision.list({ where: `on = "${subject}"` }) // what it chose, and why · Not live yet, gaps #7
const { actions } = await $.Action.list({ where: `on = "${subject}"` }) // what it did, with its checks · Not live yet, gaps #7
return { decision, actions }
npx startup-builder do Event.list --json '{"where":"name in (\"Organization.appointed\", \"Organization.reposted\", \"Organization.announced\", \"Organization.published\", \"Organization.filed\", \"Company.filed\", \"Company.funded\", \"Opening.published\", \"Organization.repriced\", \"Organization.degraded\", \"Organization.deprecated\", \"Visit.recorded\", \"Monitor.checked\", \"Organization.adopted\", \"Organization.downsized\", \"Organization.disrupted\", \"Organization.acquired\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1312"}' --try # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"prospect_31\""}' # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"prospect_31\""}' # Not live yet (gaps #7){
"name": "do",
"arguments": {
"code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Organization.appointed\", \"Organization.reposted\", \"Organization.announced\", \"Organization.published\", \"Organization.filed\", \"Company.filed\", \"Company.funded\", \"Opening.published\", \"Organization.repriced\", \"Organization.degraded\", \"Organization.deprecated\", \"Visit.recorded\", \"Monitor.checked\", \"Organization.adopted\", \"Organization.downsized\", \"Organization.disrupted\", \"Organization.acquired\")', limit: 1 }) // { play } compiled to this Play’s Trigger Events\nconst { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' }) // the same Event again, in try mode · Not live yet, gaps #7\nconst { decisions: [decision] } = await $.Decision.list({ where: `on = \"${subject}\"` }) // what it chose, and why · Not live yet, gaps #7\nconst { actions } = await $.Action.list({ where: `on = \"${subject}\"` }) // what it did, with its checks · Not live yet, gaps #7\nreturn { decision, actions }",
"mode": "try"
}
}application/json{
"decision": {
"$id": "https: //api.sb/ leaseline.app/ decisions/ decision_418",
"$type": "Decision",
"choice": "send-three-touch",
"reason": "Greystone Residential named a new VP of Operations on Oct 6 (their own news page); 1, 200 units is over the 120-unit line, and the renewal-notice output was refreshed Oct 13",
"stakes": "low",
"options": [
"send-three-touch",
"from-your-mailbox",
"publish-the-page",
"remedy-note",
"not-now"
],
…
sample · 4 Not live yetPreviewOn POST /{namespace}/processes/{process}/enableOff POST /{namespace}/processes/{process}/pauseTake this one POST /{namespace}/tasks/{task}/claim
action_4 is touch 1, held 15 minutes so you can stop it (Who runs it). action_5 is touch 2 on day 3, re-checked for holds before it sends; any reply ends both.
+6.6 per 100 · ■□□□ Too early to tell · n 169 · path → arr
| Try another: the window | Choice | Reason |
|---|---|---|
| Greystone Residential: new VP of Operations, announced Oct 6, 1,200 units | send-three-touch | over the 120-unit line; the ready output is fresh |
| Harborview Living: leasing coordinator job reposted after 64 days, on your top 25 | from-your-mailbox | a top-25 account goes from Dana’s Mailbox |
| A rival’s price rise, effective Nov 1, named by 9 companies on your List | publish-the-page | the Event touches the whole niche: one dated Page first |
| Arbor Lane Homes: acquisition announced Oct 2 | not-now | the acquisition hold is live until the deal closes |
- 45 min week 1, then 20 a week
- Your time
- Day 17: first qualified reply
- First signal
Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Trigger reply rate → New Leads → New Customers ↑ → ARR added each week → ARR
Worth’s formula: about +4.1 qualified replies per 100 windows (Other Startups’ results; your own read is too early) × 100 windows a month × 0.45 replies to Deals opened × 0.30 Deals to paid × $2,393 first order ARR ≈ +$1,320. Under First signal: With 1 window in 10 held back at 100 a month, about 16 weeks to tell a +4 lift (14 to read, 2 to mature); 90 days can tell only +6.5 or more.
sample · api.sb/
Runs inside: Cold email, as one of its options; this page keeps its own record and URL.
Start it this week
npx startup-builder add play moment-outreach # 1 · writes plays/moment-outreach.mdx (Not live yet, gaps #5)
# 2 · dry run; below, its 422 on the day-0 Startup (--env test, clock at 2026-08-24)
curl -X POST "https://api.sb/leaseline.app/campaigns?mode=try" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"play":"moment-outreach"}'
# 3 · keep it, at You approve each one
curl -X POST https://api.sb/leaseline.app/campaigns \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"play":"moment-outreach"}'
# on
curl -X POST https://api.sb/leaseline.app/processes/outbound/enable \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
# off: every open window parks; nothing queued sends
curl -X POST https://api.sb/leaseline.app/processes/outbound/pause \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"| Check | Fix | Then |
|---|---|---|
use-when pass · Not live yet, gaps #8 | Keep 3 Triggers on; switch on more only once each has a ready output. | POST /{namespace}/metrics/query |
baseline pass · Not live yet, gaps #8 | Nothing to do: Before reads your last 90 days of cold first touches. | POST /{namespace}/metrics/query |
domain-authenticated fail | Add the 3 DNS records shown for go.leaseline.app; it passes once they resolve. | POST /{namespace}/domains/{domain}/authenticate |
mailbox-warm fail · Not live yet, gaps #1 | Wait for the warm-up to finish on Sep 7; drafts queue for you meanwhile. | POST /{namespace}/mailboxes/{mailbox}/warm |
owned-by-a-person pass · Not live yet, gaps #8 | Nothing to do: their windows draft into your queue instead of sending. | POST /{namespace}/tasks/{task}/assign |
fact-check pass · Not live yet, gaps #1 | Nothing to do: every delta line must cite one of the 41 Facts. | POST /{namespace}/content/draft |
customer-collision pass · Not live yet, gaps #1 | Nothing to do: Customers leave the List and go to their CSM. | POST /{namespace}/leads/{lead}/assign |
role-unstaffed warn · Not live yet, gaps #8 | Staff the AE, or leave it: Interested replies come to you. | POST /{namespace}/roles/{role}/staff |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "moment-outreach can’t start yet: 2 checks fail and 1 warns.",
"checks": [
{
"check": "use-when",
"status": "pass",
"observed": "46 windows a week on your List across 3 Triggers",
"doc": "/plays/moment-outreach#check-use-when",
"fix": "Keep 3 Triggers on; switch on more only once each has a ready output.",
"then": "Metric.query"
},
{
"check": "baseline",
"status": "pass",
"observed": "1.9 qualified replies per 100 delivered cold first touches, n 410 in 90 days",
"doc": "/plays/moment-outreach#check-baseline",
"fix": "Nothing to do: Before reads your last 90 days of cold first touches.",
"then": "Metric.query"
},
{
"check": "domain-authenticated",
"status": "fail",
"doc": "/plays/moment-outreach#check-domain-authenticated",
"fix": "Add the 3 DNS records shown for go.leaseline.app; it passes once they resolve.",
"then": "Domain.authenticate"
},
{
"check": "mailbox-warm",
"status": "fail",
"observed": "3 Mailboxes, day 0 of 14",
"doc": "/plays/moment-outreach#check-mailbox-warm",
"fix": "Wait for the warm-up to finish on Sep 7; drafts queue for you meanwhile.",
"then": "Mailbox.warm"
},
{
"check": "owned-by-a-person",
"status": "pass",
"observed": "4 companies on your List have a person owner, you",
"doc": "/plays/moment-outreach#check-owned-by-a-person",
"fix": "Nothing to do: their windows draft into your queue instead of sending.",
"then": "Task.assign"
},
{
"check": "fact-check",
"status": "pass",
"observed": "3 ready outputs, 41 sourced Facts",
"doc": "/plays/moment-outreach#check-fact-check",
"fix": "Nothing to do: every delta line must cite one of the 41 Facts.",
"then": "Content.draft"
},
{
"check": "customer-collision",
"status": "pass",
"observed": "2 Customers on the List, removed",
"doc": "/plays/moment-outreach#check-customer-collision",
"fix": "Nothing to do: Customers leave the List and go to their CSM.",
"then": "Lead.assign"
},
{
"check": "role-unstaffed",
"status": "warn",
"roles": [
"sales-lead"
],
"owned": 4,
"doc": "/plays/moment-outreach#check-role-unstaffed",
"fix": "Staff the AE, or leave it: Interested replies come to you.",
"then": "Role.staff"
}
]
}It says no, says why, and names the fix.
| Check | Fix (one call) | Your time | Wait |
|---|---|---|---|
use-when · baseline · pass: 46 windows a week; 1.9 per 100 cold, n 410 (gaps #8) | POST /{namespace}/metrics/query on trigger-reply-rate, which fills Before in Your number | 1 min | none |
domain-authenticated · fail | POST /{namespace}/domains/{domain}/authenticate on go.leaseline.app, never your main Domain | 10 min | until DNS resolves, often under 1 h |
mailbox-warm · fail: day 0 of 14 (gaps #1) | POST /{namespace}/mailboxes/{mailbox}/warm on the 3 Mailboxes | 2 min | 14 days, to Sep 7 |
owned-by-a-person · fact-check · customer-collision · pass: 4 owned by you; 41 Facts; 2 Customers removed (gaps #1, #8) | nothing; each runs again on every send | 0 min | none |
role-unstaffed · warn (gaps #8): 4 of your List’s companies have a person owner, you | POST /{namespace}/roles/{role}/staff, or leave it: Interested replies come to you within 60 min | 0 min | none |
Your number · Before 1.9 · Now 6.6 per 100 · Target 6 by Dec 31 · ■□□□ Too early to tell · n 169 matured · Other Startups +4.1,
Each window costs $0.06 for contact and company data (POST /{namespace}/contacts/{contact}/enrich) and about $0.04 for the three-line delta (Worker cost). The ready outputs and the moment Pages cost nothing past your time; the 3 Mailboxes are your outbound Domain’s. That comes to about $10 a month at 100 windows and $20 at 200.
When it starts
| When | Trigger id | Starts on | Window | How it gets in |
|---|---|---|---|---|
| A company on your List names a new head of operations in public | new-leader | event on Organization.appointed where function = 'operations' | opens on tenure day 20; closes after 60d | POST /{namespace}/monitors on their news page (web) |
| Their leasing coordinator job stays open 60 days, or is reposted | stale-job-post | threshold on Organization.reposted where openDays >= 60 | 30d | the same Monitor, on their careers page |
| A rival they name in public announces a price rise with a date | alternative-price-rise | event on Organization.repriced where namedByOrganization = true | 60d, to the effective date | POST /{namespace}/monitors on the rival’s pricing page |
+ 14 more: 10 more Events, 3 holds that start as a state and stop every touch, and a renewal window (?lanes=) |
{
"$id": "https://api.sb/leaseline.app/events/event_1312" ,
"$type": "Event",
"name": "Organization.appointed",
"at": "2026-10-19T08:14:40Z" ,
"seq": 1312,
"data": {
"organization": {
"$id": "https://api.sb/leaseline.app/organizations/org_88" ,
"name": "Greystone Residential",
"units": 1200
},
"person": "contact_14",
"title": "VP of Operations",
"announced": "2026-10-06",
"source": "https://greystone-residential.example/news/new-vp-operations"
}
}# each delivery is signed with the Watch’s secret
curl -X POST https://api.sb/leaseline.app/watches \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"selector":"Organization.appointed","url":"https://leaseline.app/hooks/sb"}'
npx startup-builder trigger Organization.appointed --like event_1312 # replays the delivery in test
npx startup-builder clock advance --by 3d # runs touch 2 (action_5), after it re-checks for holds Who runs it
SDR · your agent (role:, worker_2) holds the Key Result. Interested replies go to AE · Priya Shah (person) (role:, worker_3, staffed on day 9); your top 25 and every remedy note come to you (Dana Okafor, person, worker_1), because they send from your Mailbox or carry no ask. Your number links to Did it work. Rungs read each option’s stakes: low holds 15 minutes, medium waits for you.
| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
|---|---|---|---|---|---|
| Send the three touches | It does it, you can stop it | 186 of 191 sent unedited (5 cut by you) | met on day 33 (190 of the first 200 approved unedited); capped here until 1,000 delivered | any Stop fires, or a sent touch fails a Check → You approve each one | POST /{namespace}/actions/{action}/cancel inside the 15-minute hold |
| Publish the moment Page · Not now | It does it, you can stop it | 3 of 3 · 33 of 33 | the same | a Page fails content-evals → You approve each one | the same |
| From your Mailbox · Send a remedy note | You approve each one | 22 of 22 · 2 of 2 | never: your Mailbox and a remedy note stay yours | — | POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse |
| Change the window rule | You approve each one | 1 merged of 1 | never | — | POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert |
| Never: a watched Event in a body, a personal-life fact, a price beyond the list | Refused, every time | 1 drafted, 1 refused | never | — | none: the Check holds it |
What it reads · What it may call. It reads the public Event, its date and its source, and the ready output’s Facts. It never writes a Visit, a detected tool or a renewal date it inferred, and no text in a reply picks a recipient or a link. Its tools are POST /{namespace}/messages/{message}/schedule, POST /{namespace}/approvals, POST /{namespace}/pages, and any other call becomes an Approval under the Role’s Mandate.
You hold the SDR Key Result: 6 qualified replies per 100 windows by 2026-12-31. ← worker, metric
On each window that opens, choose one option and say why. ← triggers, chooses
Send the three touches at 120 units or more; the top 25 go from Dana’s Mailbox. ← your file, lines 5–6
Name one announced Event with its date; link its public source. ← copyRules 2
Never name a watched Event, a personal-life fact or a rival the company has not named. ← copyRules 3–5
Write the three-line delta only; the ready output carries the rest. ← copyRules 7
Never write to a company a person owns: draft it into their queue. ← worker.owns, owned-by-a-person The slow loop, as a Change. decision_301 (2026-09-28, weekly) read new-leader replies by tenure day: 2 of 31 at day 25 or later, 4 of 22 at days 18–24. change_22 moved touch 1 from tenure day 25 to day 20 (your file, line 7), and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past windows, POST /{namespace}/changes/{change}/review put the cell at 8.9 per 100; read back at +21d it is 7.7, n 26, ■□□□ Too early to tell (Example, day 56).
Bring your own agent (folded) starts at It does it, you can stop it when it matches or beats the seated agent on the eval suite, and at You approve each one when it does not; POST /{namespace}/roles/{role}/staff seats it.
npx startup-builder eval --scenario moment-outreach-212 --agent "claude -p" --seat prospector # seated: 6.6 per 100, 0 watched-Event leaks, $0.10 a window · yours: 6.1, 1 leak → You approve each one What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
|---|---|---|---|---|---|
Send the three touches send-three-touch | window open, 120 units or more, ready output fresh | Your rule (line 5) | outbound-sequence → moment-three-touch: value day 0, output day 3, ask day 10 → POST /{namespace}/messages/{message}/schedule | an Interested reply: POST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min (response-60m), Brief attached · Take this one | you, with the Brief, within 60 min |
From your Mailbox from-your-mailbox | on your top-25 List | Your rule (line 6) | moment-three-touch-founder, each touch an POST /{namespace}/approvals for you | you approve each touch · Take this one | you |
Publish the moment Page publish-the-page | the Event touches the whole niche: a rival’s price rise, outage or end-of-life date | Agent’s call, with its reason | publish-content → POST /{namespace}/pages, dated and sourced, naming no company | nobody; windows open on the Page’s day 45 | the same |
Send a remedy note remedy-note | a hold’s window closed, and one output helps with what happened | Agent’s call, with its reason | moment-remedy: one note, no ask, no pricing link, an POST /{namespace}/approvals for you | you approve it · Take this one | you |
Not now not-now | a hold is live, a person owns the company, or no ready output fits | Agent’s call, with its reason | nothing; names what holds it: the hold Check, the owner, or the missing output | the hold, until its window closes; the owner’s queue | the same |
| When they write back | Fixture reply | What happens | Who answers | By when | Call |
|---|---|---|---|---|---|
| Interested | “Yes, Marta would want to see this. Thursday?” | the Sequence stops; it offers the AE’s times and books on reply; the Brief goes to the AE (When it hands to you) | AE · Priya Shah (person) | 60 min | POST /{namespace}/meetings/book |
| Send me pricing | “What does it cost for 1,200 units?” | the Pricing Page’s list Price, and over 120 units the AE’s Quote | SDR · your agent, then AE · Priya Shah | 60 min | POST /{namespace}/conversations/{conversation}/escalate |
| Not now | “We’re mid-migration until January.” | the Sequence stops; the company parks until a new announced Event, and January is noted | nobody | at once | POST /{namespace}/leads/{lead}/nurture |
| Wrong person | “Leasing ops is Sam’s team.” | asks them to bring Sam in; it never writes to an address from their text | SDR · your agent | 1 business day | POST /{namespace}/conversations/{conversation}/answer |
| Out of office | an auto-reply until Oct 27 | the window stays open; touch 2 waits for the return date if the window lasts | nobody | the return date | POST /{namespace}/messages/{message}/schedule |
| Question it can’t answer | “Does it work with our accounting system?” | To a person, the question in the Brief | AE · Priya Shah (person) | 60 min | POST /{namespace}/conversations/{conversation}/escalate |
| Stop | “Take us off your list.” | nothing else sends to anyone at the company, on any lane | nobody | at once | POST /{namespace}/contacts/{contact}/suppress |
When it hands to you
Interested replies go to AE · Priya Shah (person); your top 25 and remedy notes come to you, and before day 9 every Interested reply did. One Brief per Role, as captured, then the Approval (brief, draft, route and checks are Not live yet, gaps #7).
[
{
"$id": "https://api.sb/leaseline.app/tasks/task_244" ,
"$type": "Task",
"assignee": "worker_3",
"due": "2026-10-15T15:12:00Z" ,
"on": "lead_47",
"brief": {
"who": "Owen Hale, Director of Operations, Larkfield Communities (640 units)" ,
"said": "This is timely. Can we look at renewals across our 3 regions?" ,
"chose": "send-three-touch",
"why": "new-leader window, day 22; over the 120-unit line" ,
"event": "Organization.appointed, announced 2026-09-23" ,
"never": [
"a price beyond the list",
"a discount",
"the date we noticed them"
]
}
},
{
"$id": "https://api.sb/leaseline.app/approvals/approval_57" ,
"$type": "Approval",
"verdict": null,
"deadline": "2026-10-20T13:00:00Z" ,
"draft": "Hi Rosa, Harborview reposted its leasing coordinator role on Oct 14…" ,
"route": "from-your-mailbox",
"checks": [
{
"check": "fact-check",
"status": "pass"
},
{
"check": "hold",
"status": "pass"
}
]
}
]Each receiver answers with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, POST /{namespace}/actions/{action}/redirect, POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, each a one-call window. An Approval unanswered by its deadline expires and never sends, because a late touch misses the window (late-send). Once a person claims, the agent’s pending touches to that company cancel with claimedByPerson (Not live yet, gaps #7). A Task nobody claims by its due time goes up a Role through POST /{namespace}/tasks/{task}/escalate (AE to you), and person-promise fires.
On time: AE · Priya Shah, 5 of 5 claimed within 60 min, median 21 min, n 5, ■□□□ Too early to tell beside Other Startups’ 92 % on time; you, 23 of 24 approvals inside their deadline, median 46 min, n 24 (1 expired). Your queue: counted by kind: in week 3, 31 approvals and 1 hand-off; after the promotion, about 6 approvals (your top 25) and 1 hand-off a week.
The fixed line: POST /{namespace}/deals/{deal}/assign sets owner to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.
When it won’t send
| Check (refuses one send) | Refuses | Fix | Then |
|---|---|---|---|
owned-by-a-person (rule j; Not live yet, gaps #8) | a touch to a company whose Lead or open Deal a person owns, or whose Conversation a person claimed | Leave it to the person who owns it: the draft waits in their queue. | POST /{namespace}/tasks/{task}/assign |
hold (the record’s Hold) | any window or queued touch at a company with a live layoff, crisis or acquisition hold | Nothing sends until the hold’s window closes; a remedy note may follow. | POST /{namespace}/approvals |
mailbox-warm (gaps #1) | a first touch from a Mailbox still warming | Wait for the warm-up to finish, 14 days from day 0. | POST /{namespace}/mailboxes/{mailbox}/warm |
fact-check (Not live yet) | a delta line no Fact and no cited public source backs | Cut the claim, or name the Fact that backs it. | POST /{namespace}/content/draft |
customer-collision (gaps #1) | a first touch to a Contact with an active Subscription | Send it to their CSM instead: the Contact leaves the List. | POST /{namespace}/leads/{lead}/assign |
market-hold (the record’s Market hold) | a touch to a Market that is unresolved or failed its row check | Resolve the company’s Market; the touch never retries another way. | PATCH /{namespace}/organizations/{id} |
stale-output (the record’s Stale output stop) | touch 2 when its ready output missed the weekly refresh or cites a changed Fact | Refresh the ready output, then approve it once. | POST /{namespace}/content/draft |
late-send (the record’s Late-send stop) | a draft unapproved past 30 % of its window’s half-life | Approve the next window sooner, or promote the cell; the expired send never goes. | POST /{namespace}/approvals/{approval}/approve |
capacity-drop (the record’s Capacity drop) | a window with no Mailbox slot inside 30 % of its half-life | Add a warmed Mailbox; volume never rises to catch up. | POST /{namespace}/mailboxes |
| Stop (pauses the Play) | Pauses when | Then |
|---|---|---|
watched-event-leak | one delivered touch names a watched Event: a Visit, a detected tool, an inferred renewal | every send pauses until the evals re-run and pass |
personal-life | one draft cites a personal-life event | its Trigger pauses; the case comes to you |
wrong-event | over 5 % of 50 Reasons in the monthly hand check are misdated, misattributed or stale | that Monitor kind halts |
kill-switch | you press it | POST /{namespace}/processes/{process}/pause on outbound; every window parks and moment Pages stop |
unanswered-positive (standard response-60m) | an Interested reply waits 60 min for a person | POST /{namespace}/approvals/{approval}/approve resumes it |
sending-stop-loss | any gate of the sending stop-loss trips: bounce, complaint, provider spam, placement, blocklist, authentication | the Mailbox rests; POST /{namespace}/mailboxes/{mailbox}/rest |
kind-reply-floor | a cell under 1 qualified reply per 100 delivered, after 200 | that Trigger stops firing |
follow-up-complaint | stop and hostile replies to touch 2 or 3 above 2 % of that touch, after 100 | that touch leaves the cell |
The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that sent is the Pinecrest thread in Example.
| Check | Fix | Then |
|---|---|---|
fact-check fail · Not live yet, gaps #1 | Cut the claim, or name the Fact that backs it. | POST /{namespace}/content/draft |
hold pass | — | GET /{namespace}/decisions |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "Touch 1 to Pinecrest Management did not send: one line states a figure no Fact backs.",
"checks": [
{
"check": "fact-check",
"status": "fail",
"doc": "/plays/moment-outreach#check-fact-check",
"fix": "Cut the claim, or name the Fact that backs it.",
"then": "Content.draft"
},
{
"check": "hold",
"status": "pass"
}
]
}It says no, says why, and names the fix.
[
{
"reason": {
"limit": "wrong-event",
"observed": "6 % (3 of 50)",
"bound": "5 %",
"window": "the monthly hand check, Sep 30"
},
"doc": "/plays/moment-outreach#stop-wrong-event" ,
"task": "task_219"
}
]Did it work
One window in 10 is held back at random and gets no touch; both halves are read from that assignment (rules m–o). A held-back window counts a qualified reply when anyone at the company writes in from any source. Each figure’s call is POST /{namespace}/metrics/query by node and by arm; the parent field and every node above the leaf are Not live yet (gaps #4).
+6.6 per 100 · ■□□□ Too early to tell · n 169 · path → arr
- Chose
- send-three-touch
- Why
- Greystone Residential named a new VP of Operations on Oct 6 (their own news page); 1,200 units is over the 120-unit line, and the renewal-notice output was refreshed Oct 13
- From
- send-three-touch · from-your-mailbox · publish-the-page · remedy-note · not-now
- Expects
- a qualified reply from contact_14 within 30d of touch 1
- Reopens when
- no inbound Message.created from contact_14 within 30d of touch 1, and a new announced Event on org_88
- By
- worker_2
JSON
{
"$id": "decisions/decision_418",
"$type": "Decision",
"choice": "send-three-touch",
"reason": "Greystone Residential named a new VP of Operations on Oct 6 (their own news page); 1,200 units is over the 120-unit line, and the renewal-notice output was refreshed Oct 13",
"stakes": "low",
"options": [
"send-three-touch",
"from-your-mailbox",
"publish-the-page",
"remedy-note",
"not-now"
],
"by": "worker_2",
"on": "prospect_31",
"expected": "a qualified reply from contact_14 within 30d of touch 1",
"reopensWhen": "no inbound Message.created from contact_14 within 30d of touch 1, and a new announced Event on org_88"
}| Node | Agent half | Your half (held back) | Added | Confidence | Basis |
|---|---|---|---|---|---|
trigger-reply-rate | 6.6 per 100 (10 of 152) | 0 (0 of 17 wrote in) | +6.6 [−1.9, +11.8] | ■□□□ Too early to tell | held back at random, 1 in 10 · n 169 · 39 still maturing · Other Startups +4.1, ■■■□ Likely, n 3,880 |
new-leads | 9.2 per 100 (14 of 152) | 5.9 (1 of 17) | +3.3 [−8.5, +15.1] | ■□□□ Too early to tell | the same assignment |
new-arr ↑ | $2,740, 2 Customers · Booked: credited, not all caused by this Play | $0, 0 Customers | +$2,740 [−$1,900, +$7,400] · Worth about +$1,300 a month | ■□□□ Too early to tell (2 vs 0 Customers) | the same · 3 Deals still deciding |
net-new-arr · arr | +$2,740 | +$0 | +$2,740, carried: it moves no other bridge term | ■□□□ Too early to tell | carried from new-arr |
The leaf counts qualified replies (Interested, a referral, an objection, or Not now with a date) per 100 windows assigned, once per window, over 30 days from touch 1. The Experiment runs to 200 matured windows a Trigger in the agent half; at 152 it runs on.
How it moves it: touch 1 landed a median 2 days after a dated announcement, against 23 days for your cold first touches before (trigger-reply-rate by age bucket).
Guardrails: treated against held back: positive-reply-rate across all outreach, 3.1 against 2.8 per 100, and shadow complaints on touch 2, 0.3 % against a 2 % Stop.
{
"$id": "https://api.sb/leaseline.app/campaigns/moment-outreach" ,
"$type": "Campaign",
"play": "play:moment-outreach@1" ,
"path": [
"trigger-reply-rate",
"new-leads",
"new-arr",
"net-new-arr",
"arr"
],
"experiment": {
"metric": "trigger-reply-rate",
"unit": "per-100",
"heldBack": 23,
"decision": null
},
"readout": {
"value": 6.6,
"n": 169,
"maturing": 39,
"interval": [
-1.9,
11.8
],
"readability": "inadmissible",
"basis": "held-back",
"pooled": false
},
"ledger": {
"spend": 21,
"workerCost": 8,
"hours": 3.4,
"pipelineArr": 7179,
"wonArr": 2740,
"projectedArr": 1320,
"paybackDays": 6
}
}Outside benchmark: 3.3 % to 6.8 % total reply rate for cold Sequences of 1 to 3 Messages (an email-finder vendor’s annual cold email report, 2025 data, correlational).
Before it · After it. Before it: account-visits and objection-watch add companies to the List the Monitors watch. After it: Interested replies reach instant-response’s hand-off to the AE, lead-nurture hears Lead.nurtured from Not now, and a bounce that reads as a job change goes to champion-follow. It runs inside cold-email, which takes every company with no open window.
Example
Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days); touches started on day 14, once the Mailboxes warmed. 264 windows opened: 33 went to Not now, and 231 were assigned at random, 23 held back and 208 sent. 152 sent windows have matured. Read every captured thread at ?threads=; three follow the tables.
| What happened, by option | Windows | Qualified replies | Meetings held | Won (credited, not all caused by this Play) |
|---|---|---|---|---|
| Send the three touches | 186 | 10 | 4 | 0 won, 3 Deals open |
| From your Mailbox | 22 | 3 | 2 | 1 on the $2,400 plan (+$2,393 ARR) |
| Publish the moment Page · Send a remedy note · Not now | 3 Pages · 2 · 33 | 41 Visits, 2 signups · 0 · 0 | 0 | 1 on Pro at $29 a month (+$347 ARR) · 0 · 0 |
| Agent half · held back | 208 · 23 | 13 (10 of the 152 matured) · 0 of 17 | 6 · 0 | $2,740 · $0 |
| At 20 a week (the Use it when volume) | about 160 in 56 days | held back 1 in 10: Too early to tell at 90 days | — | Other Startups’ results: +4.1 per 100, ■■■□ Likely, n 3,880 |
| Day | Event | What happened | Your time |
|---|---|---|---|
| 0 | event_118 Campaign.created | the three steps; the dry run fails domain-authenticated and mailbox-warm | 25 min |
| 0 | event_121 Domain.authenticated | go.leaseline.app resolves in 40 min; the 3 Mailboxes start warming | 12 min |
| 9 | event_301 Role.staffed | AE · Priya Shah (person) takes role: | — |
| 14–33 | event_402 Approval.created, first of 200 | you approved windows one by one: 190 of the first 200 unedited | 3 h 10 min |
| 17 | event_431 Message.created | the first qualified reply: Larkfield Communities, on touch 1 | — |
| 33 | event_612 Role.updated | promoted: touches send after a 15-minute hold; your top 25 still wait for you | — |
| 35 · 56 | event_655 Change.merged · event_903 Readout.created | touch 1 moved to tenure day 20: replayed at 8.9 per 100, read back at +21d at 7.7, n 26 | 5 min |
| 37 | event_671 Campaign.paused | wrong-event: 3 of 50 site-change Reasons misdated; that Monitor kind halted, fixed and resumed in 2 days | 20 min |
| 14–56 | event_455 Action.refused, first of 2 | fact-check refused 2 drafts, each rewritten once and sent; weekly reviews, from the POST /{namespace}/tasks/next log | 30 min · total 3.4 h measured, 3.5 h asked |
Leaseline → Owen Hale, Larkfield Communities, Oct 15, 09:40 · Larkfield named you Director of Operations on Sep 23 (your news page).¹ Around a new ops lead’s first month, renewal notices across regions tend to land on that desk.² Three things teams your size do first: one owner per region, notices 60 days out, and one report for the owners. Does that match what you’re seeing?³ *Signed with the Role’s disclosure line and the stop line.*⁴
Owen, 14:12 · “This is timely. Can we look at renewals across our 3 regions?” The Brief reached Priya at 14:13; she booked Thursday 15:00 with
POST /{namespace}/meetings/bookat 14:34 (When it hands to you).
- Most firms your size lose 3 renewals a month to late notices.
+ Notices sent 60 days out are the step most often late at 300 to 800 units (Fact f-12, from our renewal-timing output). Willow & Main, 2026-10-02 10:05 · “Does this connect to our accounting system?” · Leaseline, 10:07 · *Thanks for asking. Priya, our account lead, handles integrations and replies by 11:07 today.*⁵ The Brief went to Priya (
task_233); she claimed it at 10:31 and answered at 10:58.
¹ One announced Event, with its date and public source. ² The delta: the agent’s three lines; the ready output carries the rest. ³ One question, no ask yet; the ask is touch 3. ⁴ The fixed signature and stop lines, compiled from the Role’s Settings. ⁵ The routed line, compiled from the Role’s Settings.
Your settings
---
holdout: 0.1 # 1 window in 10 gets no touch
triggers: [new-leader, stale-job-post, alternative-price-rise]
---
Over 120 units, send the three touches and book our AE.
Our top 25 accounts go from Dana’s Mailbox.
New leaders: touch 1 on tenure day 20. $ npx startup-builder show plays/moment-outreach
holdout 0.1 · triggers 3 of 17 · size line 120 units · top 25 from your Mailbox · tenure day 20 your file plays/moment-outreach.mdx:2,3,5,6,7 (Ask 2026-08-24; line 7 by change_22, 2026-09-28)
family outreach · process outbound · worker role:prospector, owns never · chooses 5 (2 rule, 3 read) · sequences moment-three-touch, moment-three-touch-founder, moment-remedy · approval delay-window · checks owned-by-a-person, hold, mailbox-warm, fact-check, customer-collision, market-hold, stale-output, late-send, capacity-drop · stops 8 · runs inside cold-email catalog play:moment-outreach@1 (Not live yet, gaps #5) Every key from the catalog
Compiled, not written: edit the Play record moment-outreach and its Leaseline run, then regenerate. Every step runs from a sentence or a line of code. In your words: the CRM words you know, and where each lives here.