URL: /plays/engagement-bridge · Id: `play:engagement-bridge`

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

Engagement bridge messages a [Person](https://startupbuilder.dev/business/nouns/person) who wrote on your [Post](https://startupbuilder.dev/business/nouns/post), from the account they wrote to, quoting their words; you press every send.

```text title="Set it up · Ask"
Be our SDR for the people who comment on my posts: when someone asks something, draft a short message quoting them, from my own account, and I press send. Interested ones go to Priya. Show me what’s missing; don’t send.
```

```text title="Run one · Ask"
Hand our latest comment to the SDR agent and show me what it chose and why. Don’t send.
```

```ts title="Run one · SDK"
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 }
```

```json title="Run one · Response · sample"
{
  "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"
    ],
    "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"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_2",
      "verb": "Suppression.list",
      "checks": []
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_2",
      "verb": "Contact.enrich",
      "checks": [
        {
          "check": "customer-collision",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_3",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_2",
      "verb": "Task.assign",
      "checks": []
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_4",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingPerson",
      "mode": "try",
      "by": "worker_2",
      "verb": "Message.create",
      "checks": [
        {
          "check": "owned-by-a-person",
          "status": "pass"
        },
        {
          "check": "claims-resolve",
          "status": "pass"
        },
        {
          "check": "customer-collision",
          "status": "pass"
        }
      ]
    }
  ]
}
```

`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 comment | Choice | Reason |
| --- | --- | --- |
| Ines Duarte, 60 units: “Could you share that renewal letter template?” under your LinkedIn post | `message-them` | wrote first, asked for an asset, fits your List |
| A 2nd-degree LinkedIn commenter: “We send notices 45 days out. Too late?” | `connect-on-linkedin` | not a first-degree connection: a connection note quoting them, asking for nothing |
| A commenter wrote TEMPLATE under your own Post | `send-what-they-asked` | the published keyword: the template, once, inside the reply window |
| A Reddit question in a room set to your own answers | `draft-your-reply` | you post it from your own account |
| A reply: “We have 240 units. What would that cost?” | `to-the-ae` | over 100 units: Priya quotes it |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$190 ARR a month at 25 | 20 min week 1, then 15 a business day | $0.02 per draft, ~$1 a month at 25 | Day 1: first reply to a bridge Message | 20+ people a month write on your posts | Under 20 a month: `founder-voice` · no account connected: <Op verb="Handle.connect" /> |

**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](/plays/organic-social), as one of its options; this page keeps its own record and URL.

## Start it this week
```bash
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"}'
```


```json title="The dry run’s 422 · 2026-08-24 · sample"
{
  "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"
    }
  ]
}
```

| Check | Fix (one call) | Your time | Wait |
| --- | --- | --- | --- |
| <a id="check-use-when"></a>`use-when` · <a id="check-baseline"></a>`baseline` · pass: 38 a month write on your posts; 22 replies per 100, n 9 (gaps #8) | <Op verb="Metric.query" /> on `engaged-dm-reply-rate`, which fills Before in Your number | 1 min | none |
| <a id="check-inbound-source"></a>`inbound-source` · fail (gaps #8) | <Op verb="Integration.connect" /> LinkedIn and Reddit | 5 min | none |
| <a id="check-role-unstaffed"></a>`role-unstaffed` · warn (gaps #8): 31 of your open Leads have a person owner, you | <Op verb="Role.staff" />, or leave it: Interested replies come to you | 0 min | none |

`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
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| Someone replies to or quotes your post with words of their own | `reply-to-handle-post` | `event` on `Comment.posted` where post.handle in startup.handles and text != '' | 72 h | <Op verb="Handle.connect" /> the account you post from |
| Someone asks publicly for a link, an asset, a price or a private answer | `public-ask` | `event` on `Question.asked` where asks for a link, an asset, a demo, a price or a private answer | 24 h | the same connected account |
| + 3 more for summons of your agent account, questions in rooms you own and keyword comments (`?lanes=all`) | | | | |

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

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

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Message them · Connect on LinkedIn · Draft your reply | You approve each one | 41 sent of 44 drafted (3 discarded) | never: a person’s own account stays here | — | <Op verb="Approval.approve" /> · <Op verb="Action.cancel" /> |
| Send what they asked for · Answer in public | It does it, you can stop it | 6 of 6 · 2 of 2, from the labeled agent account | met on day 15 (the first 5) | a moderator removal → that room drops to drafts only | <Op verb="Action.cancel" /> inside the delay |
| To the AE | It does it | 4 of 4 | — | a reply waits past 60 min → You approve each one | <Op verb="Action.redirect" /> |
| Change the routing rule | You approve each one | 0 merged | never | — | <Op verb="Change.merge" /> · <Op verb="Change.revert" /> |
| Never: a like or follow to start a thread, a profile visit quoted, a price or terms without your edit | To a person, every time | 1 asked, 1 handed over | never | — | <Op verb="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 <Op verb="Task.assign" />, <Op verb="Comment.create" />, <Op verb="Conversation.escalate" />, and any other call becomes an Approval under the Role’s Mandate.

```md title="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; <Op verb="Role.staff" /> seats it.

```bash
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
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| Message them `message-them` | wrote words of their own on your post, fits your List | Agent’s call, with its reason | `bridge-two-touch`: one Message, one follow-up at 4 days if no reply | <Op verb="Task.assign" /> → you press send, due 1 business day · Take this one | you |
| Connect on LinkedIn `connect-on-linkedin` | commented on LinkedIn, no first-degree connection | Your rule (line 4) | `linkedin-bridge`: a note quoting them, asking for nothing | you press send · Take this one | you |
| Send what they asked for `send-what-they-asked` | commented the keyword on your own Post | Your rule (the keyword) | `keyword-fulfilment` from the labeled agent account | nobody | the same |
| Answer in public `answer-in-public` | summoned your agent account, or asked in a room you own | Agent’s call, with its reason | <Op verb="Comment.create" /> as the labeled agent account | nobody | the same |
| Draft your reply `draft-your-reply` | asked in a room set to your own answers | Your rule (the room’s record) | <Op verb="Task.assign" /> with two drafts | you post it, or not, due 1 business day · Take this one | you |
| To the AE `to-the-ae` | replies Interested, or asks a price for 100+ units | Agent’s call, with its reason | <Op verb="Conversation.escalate" /> → <Op verb="Task.assign" /> | AE · Priya Shah, due 60 min · Take this one | you, within 60 min |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| 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 min | <Op verb="Meeting.book" /> |
| Send me pricing | “What does it cost for 60 units?” | your reply quotes the Pricing Page: Team, $79 a month up to 150 units | you, from the draft | 1 business day | <Op verb="Conversation.answer" /> |
| Not now | “Maybe after renewal season.” | the follow-up stops; nothing more sends on this bridge | nobody | at once | <Op verb="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 text | you, from the draft | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Oct 28 | the follow-up waits for the return date | nobody | the return date | <Op verb="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 it | AE · Priya Shah, or you | 60 min | <Op verb="Conversation.escalate" /> |
| Stop | “stop” | suppressed on every alias, for all your Startups, within the hour | nobody | at once | <Op verb="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).

```json title="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 <Op verb="Task.claim" /> (Take this one), <Op verb="Task.return" /> with a reason, or <Op verb="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 <Op verb="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:** <Op verb="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 |
| --- | --- | --- | --- |
| <a id="check-owned-by-a-person"></a>`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 claimed | Leave it to the person who owns it: the draft waits in their queue. | <Op verb="Task.assign" /> |
| <a id="check-claims-resolve"></a>`claims-resolve` (shared) | a sentence the claims source lacks | Cut the claim, or name the record that backs it. | <Op verb="Content.draft" /> |
| <a id="check-customer-collision"></a>`customer-collision` (Not live yet, gaps #1) | a bridge Message to someone who is already a Customer | Send it to their CSM instead. | <Op verb="Lead.assign" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-account-health"></a>`account-health` | a warning, a rate-limit refusal, a lock or a label removed on an account | every Tactic on that account stops at once |
| <a id="stop-block-report"></a>`block-report` | one block or spam report | that account’s Messages pause 7 days; 2 in 30 days pause the place |
| <a id="stop-removal"></a>`removal` | a moderator removes a public reply | that room drops to drafts only for 30 days |
| <a id="stop-public-callout"></a>`public-callout` | a public post calls a bridge Message spam | the place pauses, and you answer in public within 4 business hours |
| <a id="stop-negative-reply"></a>`negative-reply` | not-interested and hostile replies over 20 %, after 30 replies | that template pauses |
| <a id="stop-reply-floor"></a>`reply-floor` | under 10 replies per 100 after 50 Messages on one place | the run stops there for review |
| <a id="stop-stale-tray"></a>`stale-tray` | tray items expire unread 3 business days running | the Tactic pauses until you clear the tray |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every 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.

```json title="The captured refusal · sample"
{
  "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"
    }
  ]
}
```


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

| Node | Now (56 days) | Before (the 90 days) | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `engaged-dm-reply-rate` | 46 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-leads` | 11 Leads from bridge replies | 2 | — | — | 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` · `arr` | carried from `new-arr` | carried | — | — | 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.

```json title="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 option | Decisions | Sent | Replies |
| --- | --- | --- | --- |
| Message them · Connect on LinkedIn | 33 · 8 | 33 · 5 (3 pending) | 16 · 1 |
| Send what they asked for · Answer in public · Draft your reply | 6 · 2 · 4 | 6 · 2 · 3 you posted | 2 · — · — |
| To the AE | 4 | 4 hand-offs | 3 Meetings booked |
| **Bridged** · held back (public answer only) | **47** · 12 | **41 delivered** · 0 | **19** · 1 wrote again unasked |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| 0 | `event_1520` Campaign.created | the three steps; the dry run fails `inbound-source` | 15 min |
| 0 | `event_1521` Handle.connected | LinkedIn and Reddit connected; the tray opens | 5 min |
| 1 | `event_1524` Message.created | the first bridge reply: “Thanks, this is exactly it.” | — |
| 15 | `event_1538` Role.updated | promoted: keyword fulfilment and public answers from the agent account send after a delay | — |
| 29 | `event_1546` Campaign.paused | `stale-tray`: 3 business days of expired items while you travelled; resumed on your return | 5 min |
| 44 | `event_1553` Meeting.booked | Marcus Lee, 240 units, booked with Priya from a bridge reply | — |
| 1–56 | `event_1523` Task.assigned, first of 44 | you sent 41 of 44 drafts, from the <Op verb="Task.next" /> log | 2 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.

```diff title="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
```mdx title="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
| Key | Id | What it is |
| --- | --- | --- |
| Tactic | <a id="tactic-agent-bridge"></a>`agent-bridge` | Agent 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. |
| Tactic | <a id="tactic-human-post-tray"></a>`human-post-tray` | Human 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. |
| Tactic | <a id="tactic-engagement-bridge"></a>`engagement-bridge` | Engagement 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. |
| Tactic | <a id="tactic-send-gate-check"></a>`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 | <a id="tactic-reply-matrix"></a>`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. |
| Trigger | <a id="trigger-handle-summoned"></a>`handle-summoned` | Handle summoned: `event` on `Handle.mentioned`, window 24h. |
| Trigger | <a id="trigger-owned-room-question"></a>`owned-room-question` | Owned room question: `event` on `Question.asked`, window 24h. |
| Trigger | <a id="trigger-keyword-comment"></a>`keyword-comment` | Keyword comment: `event` on `Comment.posted`, window 24h. |
| Trigger | <a id="trigger-reply-to-handle-post"></a>`reply-to-handle-post` | Reply to a Handle post: `event` on `Comment.posted`, window 72h. |
| Trigger | <a id="trigger-public-ask"></a>`public-ask` | Public ask: `event` on `Question.asked`, window 24h. |
| Trigger | <a id="trigger-brand-mention"></a>`brand-mention` | Brand mention: `event` on `Post.published`, window 24h. |
| Sequence | <a id="sequence-bridge-two-touch"></a>`bridge-two-touch` | Two-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. |
| Sequence | <a id="sequence-linkedin-bridge"></a>`linkedin-bridge` | LinkedIn bridge: 3 steps; it ends on Any reply; A request pending 14 days, which is withdrawn; Suppression on any alias; A booked Meeting. |
| Sequence | <a id="sequence-keyword-fulfilment"></a>`keyword-fulfilment` | Keyword fulfilment: 1 steps; it ends on Delivery; Any reply, which the reply matrix takes; The Venue’s reply window closing. |