Skip to content

Engagement bridge

Engagement bridge messages a Person who wrote on your Post, from the account they wrote to, quoting their words; you press every send.

Channel
Social
Run oneMode try
You, to your agent

Hand our latest comment 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(%22Handle.mentioned%22%2C%20%22Question.asked%22%2C%20%22Comment.posted%22%2C%20%22Post.published%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_1561"}'

# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22contact_14%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%22contact_14%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const { events: [last] } = await $.Event.list({ where: 'name in ("Handle.mentioned", "Question.asked", "Comment.posted", "Post.published")', 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 (\"Handle.mentioned\", \"Question.asked\", \"Comment.posted\", \"Post.published\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1561"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"contact_14\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"contact_14\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Handle.mentioned\", \"Question.asked\", \"Comment.posted\", \"Post.published\")', 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_471",
    "$type": "Decision",
    "choice": "message-them",
    "reason": "they asked for the renewal letter template under your LinkedIn post, manage 60 units, and are a first-degree connection",
    "stakes": "low",
    "options": [
      "message-them",
      "connect-on-linkedin",
      "send-what-they-asked",
      "answer-in-public",
      "draft-your-reply",
      "to-the-ae"
  …
sample · 4 Not live yetPreview

On PATCH /{namespace}/campaigns/{id}Off PATCH /{namespace}/campaigns/{id}Take this one POST /{namespace}/tasks/{task}/claim

action_3 puts the 41-word draft in your send tray; action_4 sends only when you press send from your own LinkedIn account.

46 replies per 100 bridged against 22 before · before-after, not proof · n 41 · path → arr

Try another: the commentChoiceReason
Ines Duarte, 60 units: “Could you share that renewal letter template?” under your LinkedIn postmessage-themwrote first, asked for an asset, fits your List
A 2nd-degree LinkedIn commenter: “We send notices 45 days out. Too late?”connect-on-linkedinnot a first-degree connection: a connection note quoting them, asking for nothing
A commenter wrote TEMPLATE under your own Postsend-what-they-askedthe published keyword: the template, once, inside the reply window
A Reddit question in a room set to your own answersdraft-your-replyyou post it from your own account
A reply: “We have 240 units. What would that cost?”to-the-aeover 100 units: Priya quotes it

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Engaged DM reply rate → New Leads → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +18 replies per 100 bridged (Other Startups’ results; no lift of your own yet) × 25 bridged a month × 12 paid per 100 replies × $347 first order ARR ≈ +$187. Under First signal: At about 25 bridged a month and a 20 % holdout, 90 days can tell only +30 replies per 100 or more, so it reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Comment.posted · first draft 11m · 8 keys Not live yet

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

Start it this week

Terminal
npx startup-builder add play engagement-bridge   # 1 · writes plays/engagement-bridge.mdx (Not live yet, gaps #5)

# 2 · dry run; below, its 422 on 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":"engagement-bridge"}'

# 3 · keep it; you press every send
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"engagement-bridge"}'

# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/engagement-bridge \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":null}'

# off: the tray empties; nothing drafts
curl -X PATCH https://api.sb/leaseline.app/campaigns/engagement-bridge \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedengagement-bridge can’t start yet: 1 check fails and 1 warns.
CheckFixThen
use-when pass · Not live yet, gaps #8None needed: 20 a month is enough.POST /{namespace}/metrics/query
baseline pass · Not live yet, gaps #8None needed: 22 per 100 is your Before.POST /{namespace}/metrics/query
inbound-source fail · Not live yet, gaps #8Connect your LinkedIn and Reddit accounts, so comments reach the tray.POST /{namespace}/integrations/connect
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": "engagement-bridge can’t start yet: 1 check fails and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "38 people wrote words of their own on your posts in 30 days",
      "doc": "/plays/engagement-bridge#check-use-when",
      "fix": "None needed: 20 a month is enough.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "2 replies to 9 messages you sent by hand in 90 days",
      "doc": "/plays/engagement-bridge#check-baseline",
      "fix": "None needed: 22 per 100 is your Before.",
      "then": "Metric.query"
    },
    {
      "check": "inbound-source",
      "status": "fail",
      "doc": "/plays/engagement-bridge#check-inbound-source",
      "fix": "Connect your LinkedIn and Reddit accounts, so comments reach the tray.",
      "then": "Integration.connect"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "sales-lead"
      ],
      "owned": 31,
      "doc": "/plays/engagement-bridge#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: 38 a month write on your posts; 22 replies per 100, n 9 (gaps #8)POST /{namespace}/metrics/query on engaged-dm-reply-rate, which fills Before in Your number1 minnone
inbound-source · fail (gaps #8)POST /{namespace}/integrations/connect LinkedIn and Reddit5 minnone
role-unstaffed · warn (gaps #8): 31 of your open Leads have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: Interested replies come to you0 minnone

Your number · Before 22 per 100 · Now 46 replies per 100 bridged · Target 40 by Dec 31 · before-after, not proof · n 41 delivered

Each draft costs about $0.02 (Worker cost); every send goes from your own account at $0. That comes to about $1 a month at 25 bridged people.

When it starts

WhenTrigger idStarts onWindowHow it gets in
Someone replies to or quotes your post with words of their ownreply-to-handle-postevent on Comment.posted where post.handle in startup.handles and text != ''72 hPOST /{namespace}/handles/{handle}/connect the account you post from
Someone asks publicly for a link, an asset, a price or a private answerpublic-askevent on Question.asked where asks for a link, an asset, a demo, a price or a private answer24 hthe same connected account
+ 3 more for summons of your agent account, questions in rooms you own and keyword comments (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1561",
  "$type": "Event",
  "name": "Comment.posted",
  "at": "2026-10-19T12:48:30Z",
  "seq": 1561,
  "data": {
    "comment": {
      "$id": "https://api.sb/leaseline.app/comments/comment_88",
      "on": "post_31",
      "venue": "linkedin",
      "by": "contact_14",
      "text": "Could you share that renewal letter template? We manage 60 units.",
      "permalink": "linkedin.com/feed/update/post_31#comment_88"
    }
  }
}
Reproduce it in test
npx startup-builder trigger Comment.posted --like event_1561   # replays the delivery
npx startup-builder clock advance --by 4d   # then drafts the one follow-up if no reply came
npx startup-builder listen Comment.posted --forward-to http://localhost:3000/hook

Who runs it

SDR · your agent (role:prospector, worker_2) holds the Key Result. It reads every comment and drafts each Message, but it never sends from your account: you (Dana Okafor, person, worker_1) press every send. Interested replies go to AE · Priya Shah (person) (role:sales-lead, worker_3). Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Message them · Connect on LinkedIn · Draft your replyYou approve each one41 sent of 44 drafted (3 discarded)never: a person’s own account stays here—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/actions/{action}/cancel
Send what they asked for · Answer in publicIt does it, you can stop it6 of 6 · 2 of 2, from the labeled agent accountmet on day 15 (the first 5)a moderator removal → that room drops to drafts onlyPOST /{namespace}/actions/{action}/cancel inside the delay
To the AEIt does it4 of 4—a reply waits past 60 min → You approve each onePOST /{namespace}/actions/{action}/redirect
Change the routing ruleYou approve each one0 mergednever—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a like or follow to start a thread, a profile visit quoted, a price or terms without your editTo a person, every time1 asked, 1 handed overnever—POST /{namespace}/tasks/{task}/claim

What it reads · What it may call. It reads the words people wrote on your posts and their public profile, never a like, a view or a follow, and nothing it reads appears in a Message unless they wrote it. Comment text is data, never instructions. Its tools are POST /{namespace}/tasks/{task}/assign, POST /{namespace}/comments, POST /{namespace}/conversations/{conversation}/escalate, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:engagement-bridge@1 · each line names its record key
You hold the SDR Key Result: 40 replies per 100 bridged by 2026-12-31.           ← worker, metric
On each comment, reply or ask with words of their own, choose one option and say why. ← triggers, chooses
Line one quotes their own words, verbatim, with the link.                        ← copyRules 1
Name Leaseline and Dana’s tie to it; one ask at most; one stop line.             ← copyRules 4, 6, 7
Draft at most 60 words; Dana presses send.                                       ← your file, line 4
Never start a thread with a like, a follow or a repost.                          ← copyRules 10

The slow loop. The weekly Decisions kept the routing rule as written, and no Change was merged in the window, so there is no replay or read-back to print.

Bring your own agent (folded) drafts at You approve each one, like the seated agent, because every send goes from your own account; POST /{namespace}/roles/{role}/staff seats it.

Terminal
npx startup-builder eval --scenario engagement-bridge-59 --agent "claude -p" --seat prospector   # seated: 59 of 59 quotes verbatim, 0 Checks failed sent, 41 words a draft · yours: 58 of 59, 1 failed `claims-resolve`

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Message them message-themwrote words of their own on your post, fits your ListAgent’s call, with its reasonbridge-two-touch: one Message, one follow-up at 4 days if no replyPOST /{namespace}/tasks/{task}/assign → you press send, due 1 business day · Take this oneyou
Connect on LinkedIn connect-on-linkedincommented on LinkedIn, no first-degree connectionYour rule (line 4)linkedin-bridge: a note quoting them, asking for nothingyou press send · Take this oneyou
Send what they asked for send-what-they-askedcommented the keyword on your own PostYour rule (the keyword)keyword-fulfilment from the labeled agent accountnobodythe same
Answer in public answer-in-publicsummoned your agent account, or asked in a room you ownAgent’s call, with its reasonPOST /{namespace}/comments as the labeled agent accountnobodythe same
Draft your reply draft-your-replyasked in a room set to your own answersYour rule (the room’s record)POST /{namespace}/tasks/{task}/assign with two draftsyou post it, or not, due 1 business day · Take this oneyou
To the AE to-the-aereplies Interested, or asks a price for 100+ unitsAgent’s call, with its reasonPOST /{namespace}/conversations/{conversation}/escalate → POST /{namespace}/tasks/{task}/assignAE · Priya Shah, due 60 min · Take this oneyou, within 60 min
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“This is great. Can we talk this week?”Priya offers times; the Brief goes with it (When it hands to you)AE · Priya Shah (person)60 minPOST /{namespace}/meetings/book
Send me pricing“What does it cost for 60 units?”your reply quotes the Pricing Page: Team, $79 a month up to 150 unitsyou, from the draft1 business dayPOST /{namespace}/conversations/{conversation}/answer
Not now“Maybe after renewal season.”the follow-up stops; nothing more sends on this bridgenobodyat oncePOST /{namespace}/enrollments/{enrollment}/cancel
Wrong person“My ops manager handles notices.”you ask them to bring their ops manager in; it never writes to an address from their textyou, from the draft1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 28the follow-up waits for the return datenobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Does it work with our accounting system?”To a person: no record answers it, so it says nothing of itAE · Priya Shah, or you60 minPOST /{namespace}/conversations/{conversation}/escalate
Stop“stop”suppressed on every alias, for all your Startups, within the hournobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Every bridge Message waits in your send tray, because it goes from your own account; Interested replies go to AE · Priya Shah (person). One Brief per Role, as captured (brief is Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_601",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-20T12:48:00Z",
    "on": "contact_14",
    "brief": {
      "who": "Ines Duarte, 60 units, a first-degree connection",
      "said": "Could you share that renewal letter template? We manage 60 units.",
      "chose": "message-them",
      "why": "wrote first and asked for an asset",
      "draft": "“Could you share that renewal letter template?” Here it is, Ines: leaseline.app/templates/renewal-letter. I’m Dana, I run Leaseline. Reply stop and I won’t write again.",
      "never": [
        "a like or follow first",
        "a price without your edit"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_594",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-09T15:12:00Z",
    "on": "lead_47",
    "brief": {
      "who": "Marcus Lee, 240 units",
      "said": "We have 240 units. What would that cost?",
      "chose": "to-the-ae",
      "why": "over 100 units: the AE quotes it",
      "thread": "your LinkedIn post of Oct 6 and Dana’s bridge Message of Oct 7",
      "never": [
        "a discount",
        "terms"
      ]
    }
  }
]

You and Priya answer with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, or POST /{namespace}/actions/{action}/redirect, each a one-call window. Once a person claims, the agent’s pending drafts to that person cancel with claimedByPerson (Not live yet, gaps #7), and every reply goes to the claimer. A tray item unread past its window expires, and 3 business days of expiries fire stale-tray; a Task past its due time goes up through POST /{namespace}/tasks/{task}/escalate.

On time: you, 41 of 44 tray items sent within their window, median 17 min, n 44, ■■□□ Early sign; AE · Priya Shah, 4 of 4 within 60 min, median 21 min. Your queue: counted by kind: about 6 drafts a week in your tray and 1 hand-off a fortnight to Priya.

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 draft to someone 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
claims-resolve (shared)a sentence the claims source lacksCut the claim, or name the record that backs it.POST /{namespace}/content/draft
customer-collision (Not live yet, gaps #1)a bridge Message to someone who is already a CustomerSend it to their CSM instead.POST /{namespace}/leads/{lead}/assign
Stop (pauses the Play)Pauses whenThen
account-healtha warning, a rate-limit refusal, a lock or a label removed on an accountevery Tactic on that account stops at once
block-reportone block or spam reportthat account’s Messages pause 7 days; 2 in 30 days pause the place
removala moderator removes a public replythat room drops to drafts only for 30 days
public-callouta public post calls a bridge Message spamthe place pauses, and you answer in public within 4 business hours
negative-replynot-interested and hostile replies over 20 %, after 30 repliesthat template pauses
reply-floorunder 10 replies per 100 after 50 Messages on one placethe run stops there for review
stale-traytray items expire unread 3 business days runningthe Tactic pauses until you clear the tray
kill-switchyou press itevery bridge Tactic on every account pauses

The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that sent is the second thread in Example.

422RefusedThe draft to a Reddit commenter did not go to the tray: “cuts vacancies 30 %” resolves to no record.
CheckFixThen
claims-resolve failCut the claim, or name the record that backs it.POST /{namespace}/content/draft
owned-by-a-person pass · Not live yet, gaps #8—POST /{namespace}/tasks/{task}/assign
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The draft to a Reddit commenter did not go to the tray: “cuts vacancies 30 %” resolves to no record.",
  "checks": [
    {
      "check": "claims-resolve",
      "status": "fail",
      "doc": "/plays/engagement-bridge#check-claims-resolve",
      "fix": "Cut the claim, or name the record that backs it.",
      "then": "Content.draft"
    },
    {
      "check": "owned-by-a-person",
      "status": "pass"
    }
  ]
}

It says no, says why, and names the fix.

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "stale-tray",
      "observed": "3 business days of expired items",
      "bound": "3",
      "window": "3 business days"
    },
    "doc": "/plays/engagement-bridge#stop-stale-tray",
    "task": "task_582"
  }
]

Did it work

At about 25 bridged a month, the 20 % held back at random are too few for their half to read in 90 days, so the basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. The 12 held back still get only the public answer, and their count prints in Example. Every node above the leaf is Not live yet (gaps #4).

46 replies per 100 bridged against 22 before · before-after, not proof · n 41 · path → arr

Chose
message-them
Why
they asked for the renewal letter template under your LinkedIn post, manage 60 units, and are a first-degree connection
From
message-them · connect-on-linkedin · send-what-they-asked · answer-in-public · draft-your-reply · to-the-ae
Expects
a reply within 4d
Reopens when
no inbound Message.created from contact_14 within 4d: the one follow-up drafts
By
worker_2
JSON
{
  "$id": "decisions/decision_471",
  "$type": "Decision",
  "choice": "message-them",
  "reason": "they asked for the renewal letter template under your LinkedIn post, manage 60 units, and are a first-degree connection",
  "stakes": "low",
  "options": [
    "message-them",
    "connect-on-linkedin",
    "send-what-they-asked",
    "answer-in-public",
    "draft-your-reply",
    "to-the-ae"
  ],
  "by": "worker_2",
  "on": "contact_14",
  "expected": "a reply within 4d",
  "reopensWhen": "no inbound Message.created from contact_14 within 4d: the one follow-up drafts"
}
NodeNow (56 days)Before (the 90 days)AddedConfidenceBasis
engaged-dm-reply-rate46 per 100 (19 of 41 delivered)22 per 100 (2 of 9 sent by hand)——before-after, not proof · Other Startups’ results +18 per 100, ■■□□ Early sign, n 2,960 · 3 LinkedIn notes still pending
new-leads11 Leads from bridge replies2——before-after
new-arr ↑$694, 2 Customers on Pro · Booked: credited, not all caused by this Play$0— · Worth about +$190 a month—before-after · 3 trials and 1 Deal still deciding
net-new-arr · arrcarried from new-arrcarried——carried

Before against after reads 56 days against the 90 days before; it is not proof, and Other Startups’ results print beside it. The leaf counts replies per bridge Message delivered, auto-replies left out, over 30 days.

How it moves it: each person who asked something got a Message quoting their words within a median 17 minutes of the draft, where before most threads ended at the comment.

Guardrails: before against after: Leads per reply, 0.58 against 1.0, and blocks and reports, 0 of 41 delivered; 3 trials and 1 Deal are still deciding.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/engagement-bridge",
  "$type": "Campaign",
  "play": "play:engagement-bridge@1",
  "path": [
    "engaged-dm-reply-rate",
    "new-leads",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "engaged-dm-reply-rate",
    "unit": "per-100",
    "heldBack": 12,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 41,
    "maturing": 3,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 0,
    "workerCost": 1,
    "hours": 3.6,
    "openArr": 2400,
    "wonArr": 694,
    "projectedArr": 187,
    "paybackDays": 1
  }
}

Outside benchmark: no measured range for bridge reply rates survived the research’s check, so Other Startups’ results (n 2,960 bridged) stand in.

Before it · After it. Before it: organic-social and founder-voice publish the posts people write on. After it: instant-response answers the replies that come in by email, and lead-nurture hears the Not now ones.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 74 people wrote on 18 of Dana’s posts; 59 were eligible, 12 held back at random for the public answer only, and 47 bridged. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsSentReplies
Message them · Connect on LinkedIn33 · 833 · 5 (3 pending)16 · 1
Send what they asked for · Answer in public · Draft your reply6 · 2 · 46 · 2 · 3 you posted2 · — · —
To the AE44 hand-offs3 Meetings booked
Bridged · held back (public answer only)47 · 1241 delivered · 019 · 1 wrote again unasked
DayEventWhat happenedYour time
0event_1520 Campaign.createdthe three steps; the dry run fails inbound-source15 min
0event_1521 Handle.connectedLinkedIn and Reddit connected; the tray opens5 min
1event_1524 Message.createdthe first bridge reply: “Thanks, this is exactly it.”—
15event_1538 Role.updatedpromoted: keyword fulfilment and public answers from the agent account send after a delay—
29event_1546 Campaign.pausedstale-tray: 3 business days of expired items while you travelled; resumed on your return5 min
44event_1553 Meeting.bookedMarcus Lee, 240 units, booked with Priya from a bridge reply—
1–56event_1523 Task.assigned, first of 44you sent 41 of 44 drafts, from the POST /{namespace}/tasks/next log2 h 50 min · total 3.6 h measured, 3.5 h asked

Ines Duarte, on your LinkedIn post, Sep 18, 12:40 · “Could you share that renewal letter template? We manage 60 units.”

Dana, 13:02 · “Could you share that renewal letter template?”¹ Here it is, Ines: leaseline.app/templates/renewal-letter. I’m Dana, I run Leaseline.² Reply stop and I won’t write again.³

Ines, 15:20 · “Thank you! How does Leaseline handle 4 owners?” The reply opened a Lead; she started a trial on Sep 20.

A Reddit commenter, 2026-09-09 · the draft claims-resolve refused, then the rewrite that went to the tray
- Leaseline cuts vacancies 30 %.
+ Across 3,520 renewals, leases noticed 60+ days out renewed at 71 % (n 1,940).

Marcus Lee, 2026-10-09 14:12 · “We have 240 units. What would that cost?” · Dana, 14:20 · *Thanks, Marcus. Priya, our account lead, replies with a price by 15:12.*⁴ The Brief went to Priya (task_594); she offered times at 14:51.

¹ Line one quotes their own words. ² It names the Startup and the sender’s tie to it. ³ One stop line. ⁴ The routed line, compiled from the Role’s Settings.

Your settings

plays/engagement-bridge.mdx
---
holdout: 0.2    # 1 eligible person in 5 gets the public answer only
---
Draft a short message quoting them, at most 60 words, from my own account; I press send. Over 100 units, hand it to Priya.
Text
$ npx startup-builder show plays/engagement-bridge
holdout 0.2 · 60 words · you press send · AE over 100 units     your file  plays/engagement-bridge.mdx:2,4 (Ask 2026-08-24)
family demand · process outbound · worker role:prospector, owns never · chooses 6 (3 rule, 3 read) · sequences bridge-two-touch, linkedin-bridge, keyword-fulfilment · approval every-send, delay-window · checks owned-by-a-person, claims-resolve, customer-collision · stops 8 · placements x, reddit, linkedin, instagram, youtube, github · folds into organic-social    catalog  play:engagement-bridge@1 (Not live yet, gaps #5)

Every key from the catalog

KeyIdWhat it is
Tacticagent-bridgeAgent bridge: An agent Handle answers publicly only when summoned or asked in an owned room, and sends one direct Message when the Person asked for something. Starts at It does it, you can stop it.
Tactichuman-post-trayHuman post tray: The agent drafts public replies for rooms closed to agents; a Human rewrites and posts them, and the agent watches each posted reply. Starts at You approve each one.
Tacticengagement-bridgeEngagement bridge message: A Human sends one direct Message, drafted by the agent, to a Person who wrote to the Human’s Handle first, quoting that Person’s words. Starts at You approve each one.
Tacticsend-gate-checkSend 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.
Tacticreply-matrixReply 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.
Triggerhandle-summonedHandle summoned: event on Handle.mentioned, window 24h.
Triggerowned-room-questionOwned room question: event on Question.asked, window 24h.
Triggerkeyword-commentKeyword comment: event on Comment.posted, window 24h.
Triggerreply-to-handle-postReply to a Handle post: event on Comment.posted, window 72h.
Triggerpublic-askPublic ask: event on Question.asked, window 24h.
Triggerbrand-mentionBrand mention: event on Post.published, window 24h.
Sequencebridge-two-touchTwo-touch follow-up: 2 steps; it ends on Any reply; A block or a stop; Suppression on any alias; A public negative post by the Person; A booked Meeting; An accepted Offer.
Sequencelinkedin-bridgeLinkedIn bridge: 3 steps; it ends on Any reply; A request pending 14 days, which is withdrawn; Suppression on any alias; A booked Meeting.
Sequencekeyword-fulfilmentKeyword fulfilment: 1 steps; it ends on Delivery; Any reply, which the reply matrix takes; The Venue’s reply window closing.

Compiled, not written: edit the Play record engagement-bridge 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.