Skip to content

Product signals

Finds teams getting value on a free account and writes to the right person, citing only their own usage, after you approve the first send.

Channel
Who’s visiting
Run oneMode try
You, to your agent

Hand our latest free account that crossed a usage line 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(%22Event.captured%22%2C%20%22Entitlement.checked%22%2C%20%22Customer.activated%22%2C%20%22Page.viewed%22%2C%20%22Customer.stalled%22%2C%20%22Prospect.engaged%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_2211"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Event.captured", "Entitlement.checked", "Customer.activated", "Page.viewed", "Customer.stalled", "Prospect.engaged")', 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 (\"Event.captured\", \"Entitlement.checked\", \"Customer.activated\", \"Page.viewed\", \"Customer.stalled\", \"Prospect.engaged\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_2211"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"lead_63\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"lead_63\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Event.captured\", \"Entitlement.checked\", \"Customer.activated\", \"Page.viewed\", \"Customer.stalled\", \"Prospect.engaged\")', 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_402",
    "$type": "Decision",
    "choice": "team-plan-note",
    "reason": "4 people at Brightwater Property Group drafted 31 notices this week on a free account; Team covers 5 members, and the count is 3 or more",
    "stakes": "low",
    "options": [
      "team-plan-note",
      "shared-limit-note",
      "senior-welcome",
      "reach-who-pays",
      "rescue",
      "open-a-deal",
  …
sample · 4 Not live yetPreview

On POST /{namespace}/processes/{process}/enableOff POST /{namespace}/processes/{process}/pauseTake this one POST /{namespace}/tasks/{task}/claim

action_2 puts Brightwater in the agent half. action_3 is the team plan note to contact_14, the member who signed up first, waiting for your approval because it is this account’s first send.

+18.5 Deals per 100 · ■■□□ Early sign · n 108 · path → arr

Try another: the free accountChoiceReason
Brightwater Property Group: 4 active people this week on a free accountteam-plan-note3 or more active people
Redfern Homes: 2 people refused at the 5-unit Limit on Tuesdayshared-limit-notetwo people met the same Limit
Marlow Estates: the Director of Operations activated yesterdaysenior-welcomea director, by their own stated role, at a strong fit
Harbor Row: a paying Customer read the cancel page twiceto-the-csma paying Customer never gets a sales touch

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Triggered Organization Deal rate → Deals and trials opened → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +18.5 Deals per 100 fired accounts × 69 a month × 0.35 Deals to paid (your last 90 days) × $547 first order ARR ≈ +$2,444. Under First signal: About 8 weeks to tell a +12 lift at 69 a month (5 to read, 3 to mature); at 30 a month, 90 days can tell only +22 or more, so your half starts at 0.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Event.captured · first card 11 min after the crossing · 9 keys Not live yet

Start it this week

Terminal
npx startup-builder add play product-signals   # 1 · writes plays/product-signals.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":"product-signals"}'

# 3 · keep it, at You approve the first wave
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"product-signals"}'

# on
curl -X POST https://api.sb/leaseline.app/processes/outbound/enable \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# off: no touch sends; churn alerts still reach the CSM
curl -X POST https://api.sb/leaseline.app/processes/outbound/pause \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
422Refusedproduct-signals can’t start yet: 1 check fails and 1 warns.
CheckFixThen
use-when pass · Not live yet, gaps #8Keep 30 or more free accounts a month, or run signup-interviews.POST /{namespace}/metrics/query
baseline pass · Not live yet, gaps #8Read it once; it fills Before in Your number.POST /{namespace}/metrics/query
domain-authenticated passAdd the 3 DNS records shown; it passes once they resolve.POST /{namespace}/domains/{domain}/authenticate
mailbox-warm fail · Not live yet, gaps #1Warm the agent Mailbox; it passes after 14 days at rising volume.POST /{namespace}/mailboxes/{mailbox}/warm
role-unstaffed warn · Not live yet, gaps #8Staff the AE and CSM, or leave them: those routes come to you.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "product-signals can’t start yet: 1 check fails and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "99 free accounts in 30 days; Team at $79 for 5 members",
      "doc": "/plays/product-signals#check-use-when",
      "fix": "Keep 30 or more free accounts a month, or run signup-interviews.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "13.0 Deals per 100 accounts that would have fired, n 140 in 90 days",
      "doc": "/plays/product-signals#check-baseline",
      "fix": "Read it once; it fills Before in Your number.",
      "then": "Metric.query"
    },
    {
      "check": "domain-authenticated",
      "status": "pass",
      "observed": "leaseline.app",
      "doc": "/plays/product-signals#check-domain-authenticated",
      "fix": "Add the 3 DNS records shown; it passes once they resolve.",
      "then": "Domain.authenticate"
    },
    {
      "check": "mailbox-warm",
      "status": "fail",
      "observed": "agent@leaseline.app, 3 days into warm-up",
      "doc": "/plays/product-signals#check-mailbox-warm",
      "fix": "Warm the agent Mailbox; it passes after 14 days at rising volume.",
      "then": "Mailbox.warm"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "sales-lead",
        "success-manager"
      ],
      "owned": 3,
      "doc": "/plays/product-signals#check-role-unstaffed",
      "fix": "Staff the AE and CSM, or leave them: those routes come to you.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · baseline · pass: 99 free accounts a month, a team plan; 13.0 Deals per 100, n 140 (gaps #8)POST /{namespace}/metrics/query on pql-deal-rate, which fills Before in Your number1 minnone
domain-authenticated · passPOST /{namespace}/domains/{domain}/authenticate0 minnone
mailbox-warm · fail (gaps #1): 3 days into warm-upPOST /{namespace}/mailboxes/{mailbox}/warm on agent@leaseline.app2 min14 days; in-product cards show meanwhile
role-unstaffed · warn (gaps #8): 3 free accounts have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: AE and CSM routes come to you, and your 3 get drafts in your queue0 minnone

Your number · Before 13.0 · Now 31.5 Deals per 100 · Target 30 by Dec 31 · ■■□□ Early sign · n 108 matured

Each usage card costs $0.01 to compute and each touch $0.04 from your Domain (Worker cost); first-party matching from your own sign-ins costs nothing. That comes to about $3.50 a month at 69 fired accounts and $1.50 at 30, under the $20 model spend Limit.

When it starts

WhenTrigger idStarts onWindowHow it gets in
3 or more people at one free account are active in 14 daysteam-clusterthreshold on Event.captured where 3 or more active People at one free or trial Organization within 14 dayscard within 1 h; touch within 1dyour app calls POST /{namespace}/events/capture on each notice drafted
2 or more people at one account are refused at the same Limitlimit-pairthreshold on Entitlement.checked where allowed = false for 2 or more People at one Organization on the same Limit7dyour app calls POST /{namespace}/entitlements/check before each unit is added
Someone answers a touch with interestproduct-hand-raiseevent on Prospect.engaged where the answer is to a touch of this Play, read as interesteda Deal within 1 hreplies arrive in the agent Mailbox; POST /{namespace}/conversations/{conversation}/answer reads them
+ 4 more for senior signups, pricing views, stalled signups and paying Customers on pricing (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_2211",
  "$type": "Event",
  "name": "Event.captured",
  "at": "2026-10-19T08:47:31Z",
  "seq": 2211,
  "data": {
    "lead": "lead_63",
    "organization": "organization_29",
    "event": "notice.drafted",
    "people": 4,
    "count": 31,
    "window": "7d",
    "offer": "leaseline-free"
  }
}
Reproduce it in test
npx startup-builder trigger Event.captured --like event_2211   # replays the delivery
npx startup-builder clock advance --by 3d   # runs the team plan note’s day-3 step, which ends on any reply
npx startup-builder listen Event.captured --forward-to http://localhost:3000/hook

Who runs it

SDR · your agent (role:prospector, worker_2) holds the Key Result. It hands hand-raises and director signups to AE · Priya Shah (person) (role:sales-lead, worker_3, staffed on day 9), the who-pays note to you (Dana Okafor, person, worker_1) to send from your own Mailbox, and paying Customers on pricing to the CSM Role, which is unstaffed, so you. Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Team plan note · Shared limit noteIt does it, you can stop it22 of 22 · 9 of 9met on day 16 (the first wave of 20)any touch fails a Check, or count-floor fires → You approve the first wavePOST /{namespace}/actions/{action}/cancel inside the hold
Rescue a stalled signup · Open a Deal · To the CSMIt does it, you can stop it7 of 8 (1 redirected) · 14 of 14 · 5 of 5the samethe samethe same
Founder welcome · Reach who paysYou approve each one4 of 4 · 3 of 3never: they go out under your name—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Change a Trigger’s thresholdYou approve each one1 merged of 1never—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a colleague’s name, a page view, a count under 3Refused, every time2 drafts refusednever—nothing; count-floor holds it

What it reads · What it may call. It reads counts from your own product Events, matched to a company by sign-in domain only. A page view, a session length or a stalled state chooses who and when, and never appears in a Message. Its tools are POST /{namespace}/entitlements/check, POST /{namespace}/meetings/book, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/conversations/{conversation}/answer, POST /{namespace}/leads/{lead}/qualify, POST /{namespace}/deals/{deal}/assign, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:product-signals@1 · each line names its record key
You hold the SDR Key Result: 30 Deals per 100 fired accounts by 2026-12-31.      ← worker, metric
On each Trigger, choose one option and say why; a paying Customer goes To the CSM. ← triggers, chooses
A count shown to anyone covers 3 or more people and names none of them.          ← copyRules 2, 5
State only numbers a live usage card line holds; never a page view.              ← copyRules 1, 3
Team note at 3 active people; founder note for a director (your file, lines 4–5). ← your file
Never write to a Lead or Deal a person owns: draft it into their queue.          ← worker.owns, owned-by-a-person

The slow loop, as a Change. decision_311 (2026-09-21, weekly) read that reviewers rejected 13 of the last 30 team-cluster fires at 2 active people, so change_23 raised the line to 3 (your file, line 4) and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past fires, POST /{namespace}/changes/{change}/review put the agent half at 29.8 per 100; read back at +21d it is 31.5, n 54, ■■□□ Early sign (Example, day 49).

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 the first wave when it does not; POST /{namespace}/roles/{role}/staff seats it.

Terminal
npx startup-builder eval --scenario product-signals-120 --agent "claude -p" --seat prospector   # seated: 31.5 per 100, 0 Checks failed sent, $0.05 a fire · yours: 27.2, 1 count-floor refusal, $0.07 → You approve the first wave

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Team plan note team-plan-note3 or more active people at one free accountYour rule (line 4)team-plan-note, in the product and from the agent Mailboxthe reader’s press, or Open a Deal on a replythe same
Shared limit note shared-limit-note2 or more people refused at one LimitYour rule (line 4)POST /{namespace}/entitlements/check → shared-limit-notethe samethe same
Founder welcome senior-welcomea director or above activates at a strong fitAgent’s call, with its reasonsenior-welcome from your Mailbox → on reply POST /{namespace}/meetings/bookPOST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min · Take this oneyou, within 60 min
Reach who pays reach-who-paysan active team and no known Contact who paysAgent’s call, with its reasonbuyer-note, drafted for you → POST /{namespace}/tasks/{task}/assignyou, to send from your own Mailbox · Take this oneyou
Rescue a stalled signup rescuea fit signup stopped short of first valueAgent’s call, with its reasondormant-rescue: their own last failed step, no plannobodythe same
Open a Deal open-a-dealsomeone answers a touch with interestYour rule (the hand-raise)POST /{namespace}/leads/{lead}/qualify → POST /{namespace}/deals/{deal}/assignPOST /{namespace}/tasks/{task}/assign → AE · Priya Shah, due 60 min (response-60m), Brief attached · Take this oneyou, within 60 min
To the CSM to-the-csma paying Customer reads pricing, billing or cancelYour rule (the Customer guard)POST /{namespace}/tasks/{task}/assign with a health brief; no MessageCSM, so you · Take this oneyou
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Yes, set us up on Team.”opens a Deal and books it; the Brief goes to the AE (When it hands to you)AE · Priya Shah (person)60 minPOST /{namespace}/meetings/book
Send me pricing“What would Team cost for the four of us?”Team’s live Price for the active count, never more seatsSDR · your agent5 minPOST /{namespace}/conversations/{conversation}/answer
Not now“We’re fine on free for now.”the note stops; the account rests 30 days before any new firenobodyat oncePOST /{namespace}/leads/{lead}/nurture
Wrong person“Our owner signs off on software.”asks them to forward the team-totals link; it never writes to an address from their textSDR · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 30the follow-up waits for the return datenobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Can Team sync with our accounting system?”To a person, the question in the BriefAE · Priya Shah60 minPOST /{namespace}/conversations/{conversation}/escalate
Stop“How do you know how many of us use it? Stop.”every touch to that company stops for 90 days, and the reply goes to you (privacy)youat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Hand-raises and director signups go to AE · Priya Shah (person); the who-pays note and paying Customers on pricing come to you, and before day 9 every hand-off did. 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_509",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-19T10:58:00Z",
    "on": "lead_63",
    "brief": {
      "who": "Brightwater Property Group, free account",
      "said": "Yes, set us up on Team. We’re 4 now, maybe 6 by spring.",
      "chose": "open-a-deal",
      "why": "answered the team plan note with interest",
      "counted": "4 active people, 31 notices in 7 days",
      "never": [
        "a colleague’s name",
        "a page view",
        "a discount"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_477",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-06T17:00:00Z",
    "on": "lead_58",
    "brief": {
      "who": "Tidewater Rentals, free account",
      "chose": "reach-who-pays",
      "why": "5 active people, and none of them is the owner who pays",
      "draft": "a 3-line note from you, citing the team’s own totals"
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_61",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-09-03T15:00:00Z",
    "draft": "Hi Sam, your team of 4 drafted 31 renewal notices on Leaseline this week…",
    "route": "team-plan-note",
    "checks": [
      {
        "check": "count-floor",
        "status": "pass"
      },
      {
        "check": "customer-collision",
        "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. Once a person claims, the agent’s pending touches to that company cancel with claimedByPerson (Not live yet, gaps #7), and every reply goes to the claimer. 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, 13 of 14 claimed within 60 min, median 21 min, ■■□□ Early sign, n 14; you, 8 of 8, median 3 h on who-pays notes, n 8. Your queue: in week 1, 20 approvals and 1 weekly review; after the promotion on day 16, 1 weekly review, about 2 hand-offs and 1 who-pays note 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; gaps #8)a touch to a Contact 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
customer-collision (the record’s Paying Customer guard; gaps #1)a sales touch to a paying CustomerSend it to their CSM instead.POST /{namespace}/leads/{lead}/assign
mailbox-warm (gaps #1)a touch from a Mailbox still in warm-upWarm the Mailbox; it passes after 14 days at rising volume.POST /{namespace}/mailboxes/{mailbox}/warm
count-floor (the record’s Count-floor stop, held at the send)a count under 3 people, a colleague’s name, or someone who left the totalsSay “2 people on your team”, never a name.POST /{namespace}/messages/{message}/schedule
Stop (pauses the Play)Pauses whenThen
privacyone reply objects to being watched; 2 in 30 daysthat company rests 90 days; 2 pause the Play
reply-floorinterested replies plus checkouts under 1 % after 300 first touchesthe Play run stops
unanswered-positive (the record’s Owner stop; standard response-60m)a hand-raise waits past 1 business hour, or 30 % of a week’s approvals expirenew fires pause; POST /{namespace}/approvals/{approval}/approve resumes it
false-firereviewers reject over 40 % of a Trigger’s last 30 firesits threshold rises one notch
holdout-integritya touch reaches a held-back account; over 5 % voids the readoutPOST /{namespace}/tasks/{task}/assign names the Play that sent it
spend-limitmonth-to-date model spend reaches its Limitthat part pauses until the month turns (POST /{namespace}/limits/{limit}/raise)
bounce (email)bounces above 2 % of a day’s sendsthat Mailbox pauses
complaint (email)complaints near 0.1 %the Play’s email pauses on every Mailbox
stop-line (email)stop clicks above 2 % of a template’s last 100 deliveredthat template pauses and returns to You approve each one
sync-lag (in-product)Events landing over 60 min late, or a fire over 24 h after its crossingevery route with a window under 7 days pauses
kill-switchyou press itPOST /{namespace}/processes/{process}/pause on outbound; churn alerts still reach the CSM

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

422RefusedThe note to Redfern Homes did not send: it names a colleague.
CheckFixThen
count-floor failSay “2 people on your team”, never a name.POST /{namespace}/messages/{message}/schedule
customer-collision pass · Not live yet, gaps #1—POST /{namespace}/leads/{lead}/assign
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The note to Redfern Homes did not send: it names a colleague.",
  "checks": [
    {
      "check": "count-floor",
      "status": "fail",
      "doc": "/plays/product-signals#check-count-floor",
      "fix": "Say “2 people on your team”, never a name.",
      "then": "Message.schedule"
    },
    {
      "check": "customer-collision",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "unanswered-positive",
      "observed": "1h 22m",
      "bound": "1 business hour",
      "window": "1 hand-raise"
    },
    "doc": "/plays/product-signals#stop-unanswered-positive",
    "task": "task_488"
  }
]

Did it work

Both halves are read from the same random assignment at the fire (rules m–o), and each figure’s call is POST /{namespace}/metrics/query by node and by arm; the leaf and every node above it are Not live yet (gaps #4).

+18.5 Deals per 100 · ■■□□ Early sign · n 108 · path → arr

Chose
team-plan-note
Why
4 people at Brightwater Property Group drafted 31 notices this week on a free account; Team covers 5 members, and the count is 3 or more
From
team-plan-note · shared-limit-note · senior-welcome · reach-who-pays · rescue · open-a-deal · to-the-csm
Expects
a Deal or a Team trial opened by day 21
Reopens when
no Deal opened and no trial started for lead_63 within 21d
By
worker_2
JSON
{
  "$id": "decisions/decision_402",
  "$type": "Decision",
  "choice": "team-plan-note",
  "reason": "4 people at Brightwater Property Group drafted 31 notices this week on a free account; Team covers 5 members, and the count is 3 or more",
  "stakes": "low",
  "options": [
    "team-plan-note",
    "shared-limit-note",
    "senior-welcome",
    "reach-who-pays",
    "rescue",
    "open-a-deal",
    "to-the-csm"
  ],
  "by": "worker_2",
  "on": "lead_63",
  "expected": "a Deal or a Team trial opened by day 21",
  "reopensWhen": "no Deal opened and no trial started for lead_63 within 21d"
}
NodeAgent halfYour halfAddedConfidenceBasis
pql-deal-rate31.5 per 100 (17 of 54)13.0 (7 of 54)+18.5 [3.2, 33.8]■■□□ Early signheld back at random · n 108 · 12 still maturing
opened-deals-and-trials38.9 per 100 (21 of 54)22.2 (12 of 54)+16.7 [−0.4, 33.8] · Not carrying up yet■□□□ Too early to tellthe same assignment; your half’s trials started on their own
new-arr ↑$3,284, 6 Customers · Booked: credited, not all caused by this Play$694, 2 Customers+$2,590 [−$701, +$5,077] · Worth about +$2,400 a month■□□□ Too early to tell (6 vs 2 Customers)the same · 7 Deals still deciding
net-new-arr · arr+$3,284+$694+$2,590, carried: it moves no other bridge term■□□□ Too early to tellcarried from new-arr

The leaf counts Deals or Team trials opened within 21 days per 100 free accounts assigned at their first fire, once paying Customers and held accounts are left out (rule m), to 100 matured in each half; at 54 and 54 so far the Experiment runs on.

How it moves it: a touch on a median of day 1 after the crossing, citing the team’s own counts, where your half heard nothing until they asked.

Guardrails: treated against held back: paid per Deal opened, 0.29 against 0.29 (new-paying-customers per Deal), and stop clicks, 0.9 % against no sends.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/product-signals",
  "$type": "Campaign",
  "play": "play:product-signals@1",
  "path": [
    "pql-deal-rate",
    "opened-deals-and-trials",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "pql-deal-rate",
    "unit": "per-100",
    "heldBack": 60,
    "decision": null
  },
  "readout": {
    "value": 18.5,
    "n": 108,
    "maturing": 12,
    "interval": [
      3.2,
      33.8
    ],
    "readability": "C",
    "basis": "held-back",
    "pooled": false
  },
  "ledger": {
    "spend": 2,
    "workerCost": 4,
    "hours": 2.4,
    "pipelineArr": 5688,
    "wonArr": 3284,
    "projectedArr": 2444,
    "paybackDays": 2
  }
}

Outside benchmark: a median 8 % of free accounts convert to paid within six months, across self-serve B2B products (a growth analyst’s survey with two vendors, 2026-02-04).

Before it · After it. Before it: product-led and programmatic-seo bring the free accounts. After it: closer-handoff hears each Deal it opens, and usage-upsell hears the Team accounts that pace past 150 units; churn alerts it raises feed the CSM’s queue, never a sales touch.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days). 128 free accounts fired a Trigger, 8 were left out as paying Customers or held by a person, and 120 were assigned at random, 60 to each half; 108 have matured and 12 are still maturing. Read every captured thread at ?threads=all; three follow the tables.

What happened, agent half, by optionDecisionsDeals or trials openedWon (credited, not all caused by this Play)
Team plan note · Shared limit note22 · 99 · 43 on Team (+$2,844 ARR)
Founder welcome · Reach who pays4 · 32 · 11 on Pro (+$347 ARR) · 0, 1 open
Rescue a stalled signup · Open a Deal · To the CSM8 · 14 · 51 · 14 (the Deals above) · 01 on Pro · counted above · 0
Agent half · your half60 · 60 assigned21 of 54 matured · 12 of 54$3,284 · $694
At 30 a month (the Use it when volume)about 56 in 56 daysheld back at random, half the firesOther Startups’ results: +12.0 per 100, ■■■□ Likely, n 2,860
DayEventWhat happenedYour time
0event_2003 Campaign.createdthe three steps; the dry run fails mailbox-warm15 min
0–14event_2006 Mailbox.warmedagent@leaseline.app warms; in-product cards show meanwhile2 min
2event_2031 Meeting.bookedthe first Meeting: Marlow Estates’ director, from your welcome note—
9event_2089 Role.staffedAE · Priya Shah (person) takes role:sales-lead—
16event_2120 Role.updatedpromoted: team and limit notes send after a 2-minute hold—
28 · 49event_2144 Change.merged · event_2195 Readout.createdthe team line from 2 to 3 people: replayed at 29.8 per 100, read back at +21d at 31.5, n 545 min
33event_2160 Campaign.pausedunanswered-positive: a hand-raise waited 1 h 22 min; resumed in 9 min6 min
1–56event_2012 Approval.created, first of 27you approved the first wave and 7 founder notes; count-floor refused 2 drafts, each rewritten once and sent; weekly reviews1 h 12 min · total 2.4 h measured, 2.5 h asked

Leaseline → Sam at Brightwater, Oct 19 09:02 · Your team of 4 drafted 31 renewal notices in Leaseline this week.¹ Team is $79 a month for up to 5 members and 150 units, and keeps everyone’s notices in one place.² Want me to set it up for the 4 of you? *Signed with the Role’s disclosure line.*³

Sam, 09:57 · “Yes, set us up on Team. We’re 4 now, maybe 6 by spring.” A Deal opened, and the Brief reached Priya at 09:58 (When it hands to you).

Redfern Homes, 2026-09-11 · the draft count-floor refused, then the rewrite that sent
- Hi Lee, Maria on your team hit the 5-unit limit on Tuesday too.
+ Hi Lee, 2 people on your team hit the 5-unit Limit this week. Pro covers 50 units for $29 a month.

Marlow Estates, 2026-08-26 10:14 · the Director of Operations activated · Dana, from her own Mailbox, 10:40 · a 3-line welcome, approved by Dana · Reply, 13:05 · “Could we talk Thursday?” · *Priya, our account lead, has Thursday at 14:00 or 16:00.*⁴ The Brief went to Priya (task_451).

¹ A count of 3 or more people, from a live usage card line, naming none of them. ² The live Offer’s Price, for the active count only. ³ The fixed signature line, compiled from the Role’s disclosure Setting. ⁴ The routed line, compiled from the Role’s Settings.

Your settings

plays/product-signals.mdx
---
holdout: 0.5      # half the fired accounts get no touch for 60 days, as today
---
Write about Team when 3 or more people at one free account are active.
A director who signs up gets a note from Dana, approved each time.
Hand-raises go to the AE.
Text
$ npx startup-builder show plays/product-signals
holdout 0.5 · team line 3 people · founder note for a director · hand-raises to the AE     your file  plays/product-signals.mdx:2,4,5,6 (Ask 2026-08-24; line 4 by change_23, 2026-09-21)
worker role:prospector, owns never · chooses 7 (4 rule, 3 read) · sequences team-plan-note, shared-limit-note, senior-welcome, dormant-rescue, buyer-note · approval first-send, every-send · checks owned-by-a-person, customer-collision, mailbox-warm · stops 11 + count-floor held at the send · placements gmail, outlook, yahoo-mail, linkedin + in-product card    catalog  play:product-signals@1 (Not live yet, gaps #5)

Every key from the catalog

Key Id What it is
Tactic usage-identity-resolve Usage identity resolve: Resolves each Person in the Product to an Organization from first-party evidence only, with a confidence, and marks each Organization’s lifecycle. Starts at Sends nothing.
Tactic usage-trigger-score Usage trigger score: Grades fit first, fires a Trigger when a usage threshold crosses, stacks live Triggers by half-life, draws the holdout and routes each Organization. Starts at Sends nothing.
Tactic usage-card-build Usage card build computes the only numbers a touch may state about an Organization: its People’s counted use, its Limits reached and its plan math. Starts at Sends nothing.
Tactic usage-touch-compose Usage touch compose: Fills at most three slots of the route’s template from the usage card, checks facts and the count floor, and queues an approval card. Starts at You approve the first wave.
Tactic usage-touch-send Usage touch send: Delivers an approved touch in the Product and from the home-Domain Mailbox, records its trigger, and runs the route’s one follow-up. Starts at You approve the first wave.
Tactic buyer-route Approver route reaches the Person who pays for a triggered team through a known Contact, the champion’s own forward, or an opt-in cold route. Starts at You approve each one.
Tactic churn-alert Churn alert: Turns a paying Customer’s visit to pricing, billing or cancel Pages into a Success Manager Task with a health brief, and sends no Message. Starts at Sends nothing.
Tactic trigger-deal-log Trigger deal log opens a Deal on each hand-raise, counts yield weekly, reads the holdout at day 60 and recalibrates every 30 days. 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 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 team-cluster Team cluster: threshold on Event.captured, window 14d.
Trigger limit-pair Limit pair: threshold on Entitlement.checked, window 7d.
Trigger senior-signup Senior signup: event on Customer.activated, window 7d.
Trigger active-pricing Active pricing: event on Page.viewed, window 3d.
Trigger dormant-signup Dormant signup: state on Customer.stalled, window 14d.
Trigger customer-pricing-visit Customer pricing visit: event on Page.viewed, window 7d.
Trigger product-hand-raise Product hand raise: event on Prospect.engaged, window 1d.
Sequence team-plan-note Team plan note: 4 steps; it ends on A reply; A checkout started; A Deal opened; The card dismissed; An Organization-scope stop; The Organization becomes a paying Customer; 14 days.
Sequence shared-limit-note Shared limit note: 4 steps; it ends on A reply; A checkout started; A Deal opened; An Organization-scope stop; The Organization becomes a paying Customer; 14 days.
Sequence senior-welcome Senior welcome: 2 steps; it ends on A reply; A booked Meeting; A checkout started; A stop; 14 days.
Sequence dormant-rescue Dormant rescue: 4 steps; it ends on Any activation Event; A reply; A stop; A send gate refusal for the colleague; 21 days.
Sequence buyer-note Approver note: 2 steps; it ends on A reply; A Quote request; A checkout started; A stop; 14 days.
Benchmark product-signals-plan-upgrade-timing Monthly plan upgrade rate after a purchase, from month 4 (low) to month 1 (high).: 0.16–0.75 % (A subscription-analytics vendor’s upgrade-timing study, published 2026-09-30., 2026-10-24).
Benchmark product-signals-seat-upgrade-timing Monthly seat upgrade rate after a purchase, from month 4 (low) to month 1 (high).: 0.19–0.83 % (A subscription-analytics vendor’s upgrade-timing study, published 2026-09-30., 2026-10-24).
Benchmark product-signals-free-to-paid-median Median free-to-paid conversion within six months of signup, across self-serve B2B products.: 8 % (A self-serve benchmark survey by a growth analyst and two vendors, published 2026-02-04., 2026-10-24).

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