Skip to content

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
Run oneMode try
You, to your agent

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"
  }
}
Response200application/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 yetPreview

On 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 windowChoiceReason
Greystone Residential: new VP of Operations, announced Oct 6, 1,200 unitssend-three-touchover the 120-unit line; the ready output is fresh
Harborview Living: leasing coordinator job reposted after 64 days, on your top 25from-your-mailboxa top-25 account goes from Dana’s Mailbox
A rival’s price rise, effective Nov 1, named by 9 companies on your Listpublish-the-pagethe Event touches the whole niche: one dated Page first
Arbor Lane Homes: acquisition announced Oct 2not-nowthe acquisition hold is live until the deal closes

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/leaseline.app · 41 Customers at 2026-10-19 · on Organization.appointed · first draft 4m 12s after the window opened · 10 keys Not live yet

Runs inside: Cold email, as one of its options; this page keeps its own record and URL.

Start it this week

Terminal
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"
422Refusedmoment-outreach can’t start yet: 2 checks fail and 1 warns.
CheckFixThen
use-when pass · Not live yet, gaps #8Keep 3 Triggers on; switch on more only once each has a ready output.POST /{namespace}/metrics/query
baseline pass · Not live yet, gaps #8Nothing to do: Before reads your last 90 days of cold first touches.POST /{namespace}/metrics/query
domain-authenticated failAdd 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 #1Wait 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 #8Nothing to do: their windows draft into your queue instead of sending.POST /{namespace}/tasks/{task}/assign
fact-check pass · Not live yet, gaps #1Nothing to do: every delta line must cite one of the 41 Facts.POST /{namespace}/content/draft
customer-collision pass · Not live yet, gaps #1Nothing to do: Customers leave the List and go to their CSM.POST /{namespace}/leads/{lead}/assign
role-unstaffed warn · Not live yet, gaps #8Staff 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.

CheckFix (one call)Your timeWait
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 number1 minnone
domain-authenticated · failPOST /{namespace}/domains/{domain}/authenticate on go.leaseline.app, never your main Domain10 minuntil DNS resolves, often under 1 h
mailbox-warm · fail: day 0 of 14 (gaps #1)POST /{namespace}/mailboxes/{mailbox}/warm on the 3 Mailboxes2 min14 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 send0 minnone
role-unstaffed · warn (gaps #8): 4 of your List’s companies have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: Interested replies come to you within 60 min0 minnone

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, ■■■□ Likely

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

WhenTrigger idStarts onWindowHow it gets in
A company on your List names a new head of operations in publicnew-leaderevent on Organization.appointed where function = 'operations'opens on tenure day 20; closes after 60dPOST /{namespace}/monitors on their news page (web)
Their leasing coordinator job stays open 60 days, or is repostedstale-job-postthreshold on Organization.reposted where openDays >= 6030dthe same Monitor, on their careers page
A rival they name in public announces a price rise with a datealternative-price-riseevent on Organization.repriced where namedByOrganization = true60d, to the effective datePOST /{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=all)
One signed delivery · StartupBuilder-Signature
{
  "$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"
  }
}
Reproduce it in test
# 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:prospector, worker_2) holds the Key Result. Interested replies go to AE · Priya Shah (person) (role:sales-lead, 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.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Send the three touchesIt does it, you can stop it186 of 191 sent unedited (5 cut by you)met on day 33 (190 of the first 200 approved unedited); capped here until 1,000 deliveredany Stop fires, or a sent touch fails a Check → You approve each onePOST /{namespace}/actions/{action}/cancel inside the 15-minute hold
Publish the moment Page · Not nowIt does it, you can stop it3 of 3 · 33 of 33the samea Page fails content-evals → You approve each onethe same
From your Mailbox · Send a remedy noteYou approve each one22 of 22 · 2 of 2never: your Mailbox and a remedy note stay yours—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Change the window ruleYou approve each one1 merged of 1never—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 listRefused, every time1 drafted, 1 refusednever—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.

The brief (folded): compiled Agent-register Markdown · play:moment-outreach@1 · each line names its record key
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.

Terminal
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

OptionPicked whenDecided byRunsHands toIf it’s just you
Send the three touches send-three-touchwindow open, 120 units or more, ready output freshYour rule (line 5)outbound-sequence → moment-three-touch: value day 0, output day 3, ask day 10 → POST /{namespace}/messages/{message}/schedulean Interested reply: POST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min (response-60m), Brief attached · Take this oneyou, with the Brief, within 60 min
From your Mailbox from-your-mailboxon your top-25 ListYour rule (line 6)moment-three-touch-founder, each touch an POST /{namespace}/approvals for youyou approve each touch · Take this oneyou
Publish the moment Page publish-the-pagethe Event touches the whole niche: a rival’s price rise, outage or end-of-life dateAgent’s call, with its reasonpublish-content → POST /{namespace}/pages, dated and sourced, naming no companynobody; windows open on the Page’s day 45the same
Send a remedy note remedy-notea hold’s window closed, and one output helps with what happenedAgent’s call, with its reasonmoment-remedy: one note, no ask, no pricing link, an POST /{namespace}/approvals for youyou approve it · Take this oneyou
Not now not-nowa hold is live, a person owns the company, or no ready output fitsAgent’s call, with its reasonnothing; names what holds it: the hold Check, the owner, or the missing outputthe hold, until its window closes; the owner’s queuethe same
When they write backFixture replyWhat happensWho answersBy whenCall
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 minPOST /{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 QuoteSDR · your agent, then AE · Priya Shah60 minPOST /{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 notednobodyat oncePOST /{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 textSDR · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 27the window stays open; touch 2 waits for the return date if the window lastsnobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Does it work with our accounting system?”To a person, the question in the BriefAE · Priya Shah (person)60 minPOST /{namespace}/conversations/{conversation}/escalate
Stop“Take us off your list.”nothing else sends to anyone at the company, on any lanenobodyat oncePOST /{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).

What lands in each queue · sample
[
  {
    "$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)RefusesFixThen
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 claimedLeave 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 holdNothing 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 warmingWait 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 backsCut 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 SubscriptionSend 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 checkResolve 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 FactRefresh 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-lifeApprove 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-lifeAdd a warmed Mailbox; volume never rises to catch up.POST /{namespace}/mailboxes
Stop (pauses the Play)Pauses whenThen
watched-event-leakone delivered touch names a watched Event: a Visit, a detected tool, an inferred renewalevery send pauses until the evals re-run and pass
personal-lifeone draft cites a personal-life eventits Trigger pauses; the case comes to you
wrong-eventover 5 % of 50 Reasons in the monthly hand check are misdated, misattributed or stalethat Monitor kind halts
kill-switchyou press itPOST /{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 personPOST /{namespace}/approvals/{approval}/approve resumes it
sending-stop-lossany gate of the sending stop-loss trips: bounce, complaint, provider spam, placement, blocklist, authenticationthe Mailbox rests; POST /{namespace}/mailboxes/{mailbox}/rest
kind-reply-floora cell under 1 qualified reply per 100 delivered, after 200that Trigger stops firing
follow-up-complaintstop and hostile replies to touch 2 or 3 above 2 % of that touch, after 100that 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.

422RefusedTouch 1 to Pinecrest Management did not send: one line states a figure no Fact backs.
CheckFixThen
fact-check fail · Not live yet, gaps #1Cut 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.

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "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"
}
NodeAgent halfYour half (held back)AddedConfidenceBasis
trigger-reply-rate6.6 per 100 (10 of 152)0 (0 of 17 wrote in)+6.6 [−1.9, +11.8]■□□□ Too early to tellheld back at random, 1 in 10 · n 169 · 39 still maturing · Other Startups +4.1, ■■■□ Likely, n 3,880
new-leads9.2 per 100 (14 of 152)5.9 (1 of 17)+3.3 [−8.5, +15.1]■□□□ Too early to tellthe 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 tellcarried 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.

The Campaign card · sample
{
  "$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=all; three follow the tables.

What happened, by optionWindowsQualified repliesMeetings heldWon (credited, not all caused by this Play)
Send the three touches1861040 won, 3 Deals open
From your Mailbox22321 on the $2,400 plan (+$2,393 ARR)
Publish the moment Page · Send a remedy note · Not now3 Pages · 2 · 3341 Visits, 2 signups · 0 · 001 on Pro at $29 a month (+$347 ARR) · 0 · 0
Agent half · held back208 · 2313 (10 of the 152 matured) · 0 of 176 · 0$2,740 · $0
At 20 a week (the Use it when volume)about 160 in 56 daysheld back 1 in 10: Too early to tell at 90 days—Other Startups’ results: +4.1 per 100, ■■■□ Likely, n 3,880
DayEventWhat happenedYour time
0event_118 Campaign.createdthe three steps; the dry run fails domain-authenticated and mailbox-warm25 min
0event_121 Domain.authenticatedgo.leaseline.app resolves in 40 min; the 3 Mailboxes start warming12 min
9event_301 Role.staffedAE · Priya Shah (person) takes role:sales-lead—
14–33event_402 Approval.created, first of 200you approved windows one by one: 190 of the first 200 unedited3 h 10 min
17event_431 Message.createdthe first qualified reply: Larkfield Communities, on touch 1—
33event_612 Role.updatedpromoted: touches send after a 15-minute hold; your top 25 still wait for you—
35 · 56event_655 Change.merged · event_903 Readout.createdtouch 1 moved to tenure day 20: replayed at 8.9 per 100, read back at +21d at 7.7, n 265 min
37event_671 Campaign.pausedwrong-event: 3 of 50 site-change Reasons misdated; that Monitor kind halted, fixed and resumed in 2 days20 min
14–56event_455 Action.refused, first of 2fact-check refused 2 drafts, each rewritten once and sent; weekly reviews, from the POST /{namespace}/tasks/next log30 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/book at 14:34 (When it hands to you).

Pinecrest Management, 2026-09-18 · the draft fact-check refused, then the rewrite that sent
- 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

plays/moment-outreach.mdx
---
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.
Text
$ 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

Key Id What it is
Tactic moment-watch Moment watch: Classifies Monitor Events into catalog Triggers with provenance, date and source, records holds, and opens windows on their open day. Starts at Sends nothing.
Tactic ready-outputs Ready outputs: Builds one approved output per enabled Trigger and ICP slice before any Trigger fires, and keeps each one fresh against its public data. Starts at You approve the first wave.
Tactic moment-window Moment window: Turns an open window into a minted Prospect and a checked three-touch draft whose agent-written part is a three-line delta, or ends with no angle. Starts at You approve each one.
Tactic moment-sequence Moment sequence: Sends a window’s value, output and ask touches on days 0, 3 and 10, re-checking before each, then parks the Organization until a new window. Starts at It does it, you can stop it.
Tactic half-life-calibration Half-life calibration: Replaces borrowed Trigger windows with the Startup’s own reply-by-age buckets every 30 days, one variable per review, using a timing arm and a holdout. Starts at It does it, you can stop it.
Tactic moment-page Moment page: Publishes a dated, sourced reference Page within 60 minutes of a niche Event, naming no target Organization, and keeps it current. Starts at You approve the first wave.
Tactic send-gate-check Send gate check: Checks Suppression, a live reason, the Market, the basis stamp, the Person-month grant, the facts and the labels before any cold Message exists. Starts at Sends nothing.
Tactic cold-email-send Cold email send: Sends a passed draft as plain text from an outbound Mailbox with tracking off, records it with its reason and stamp, and handles bounces. Starts at It does it, you can stop it.
Tactic reply-matrix Reply matrix: Labels every outreach reply with one of 11 labels, maps it to one of seven reply kinds, and runs that kind’s move by its deadline. Starts at You approve each one.
Tactic sending-stop-loss Sending stop loss: Reads the Play’s own bounces, replies and seed tests on every send, and rests, pauses or retires a Mailbox, Domain, cell or the Play. Starts at Sends nothing.
Trigger new-leader New leader: event on Organization.appointed, window 60d.
Trigger stale-job-post Stale job post: threshold on Organization.reposted, window 30d.
Trigger stated-initiative Stated initiative: event on Organization.announced, window 30d.
Trigger site-change Site change: event on Organization.published, window 30d.
Trigger fiscal-year-end Fiscal year end: at on Organization.filed, window 28d.
Trigger public-filing Public filing: event on Company.filed, window 14d.
Trigger funding Funding: at on Company.funded, window 45d.
Trigger hiring Opening published: event on Opening.published, window 30d.
Trigger alternative-price-rise Alternative price rise: event on Organization.repriced, window 60d.
Trigger alternative-outage Alternative outage: event on Organization.degraded, window 90d.
Trigger upstream-deprecation Upstream deprecation: at on Organization.deprecated, window 90d.
Trigger pricing-visit Pricing visit: event on Visit.recorded, window 72h.
Trigger technology-change Technology change: event on Monitor.checked, window 30d.
Trigger renewal-window Renewal window: at on Organization.adopted, window 45d.
Trigger layoff-hold Layoff hold: state on Organization.downsized, window 14d.
Trigger crisis-hold Crisis hold: state on Organization.disrupted, window 30d.
Trigger acquisition-hold Acquisition hold: state on Organization.acquired, window 90d.
Sequence moment-three-touch Moment three touch: 6 steps; it ends on Any reply on any channel; A bounce; Suppression at any scope; A booked Meeting; An open Deal; A hold Event on the Organization; The Reason expires before the next touch.
Sequence moment-three-touch-founder Moment three touch founder: 7 steps; it ends on Any reply on any channel; A bounce; Suppression at any scope; A booked Meeting; An open Deal; A hold Event on the Organization; The Reason expires before the next touch; The Mandate paused or revoked.
Sequence moment-remedy Moment remedy: 1 steps; it ends on Any reply; A bounce; Suppression at any scope; A new hold Event.
Benchmark moment-outreach-three-messages Total reply rate per Sequence, 1 Message against 3 Messages: 3.3–6.8 % (An email-finder vendor’s annual cold email report, 2025 data; correlational, 2025-12-31).
Benchmark moment-outreach-follow-ups Reply rate without follow-ups against with follow-ups: 3–4.9 % (An email-finder vendor’s annual cold email report, 2024 data; correlational, 2024-12-31).
Benchmark moment-outreach-after-step-one Share of a Sequence’s replies that arrive after step 1: 58.6 % (A lead-generation agency’s response-rate study, 2025 data, 2025-12-31).
Benchmark moment-outreach-cell-size Reply rate per Sequence, 500 or more recipients against 21 to 50: 2.4–6.2 % (An email-finder vendor’s annual cold email report, 2025 data; correlational, 2025-12-31).

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.