Waitlist interviews
Interviews each Waitlist signup with your disclosed agent, admits by fit under a published cap, and sends a result built on their company.
- Step
- Make the sale
- Channel
- Signup flows
- Kind
- Conversion
Be our SDR: offer everyone on our Waitlist a short interview with you, say you’re an AI agent, and send each one a renewal calendar built on their own units. I have 10 onboarding slots a week; admit half by your interview rank and half by form rank, as today. Show me what’s missing; don’t send.
# Not live yet (gaps #2)
curl -X POST "https://api.sb/leaseline.app/campaigns?mode=try" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"play":"signup-interviews"}'import { $ } from 'startup-builder'
return await $.Campaign.create({ play: 'signup-interviews' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-08-24 · Not live yet, gaps #2
npx startup-builder do Campaign.create --json '{"play":"signup-interviews"}' --try # Not live yet (gaps #2){
"name": "do",
"arguments": {
"code": "return await $.Campaign.create({ play: 'signup-interviews' }, { mode: 'try' }) // dry run on the day-0 Startup, 2026-08-24 · Not live yet, gaps #2",
"mode": "try"
}
}application/json{
"type": "https: //startupbuilder.dev/ errors/ refused",
"title": "Refused",
"status": 422,
"detail": "signup-interviews can’t start yet: 1 check fails and 2 warn.",
"checks": [
{
"check": "use-when",
"status": "pass",
"observed": "61 Waitlist signups in 30 days; 10 onboarding slots a week",
"doc": "/plays/ signup-interviews#check-use-when",
"fix": "Nothing to fix: 20 or more signups a month, slots for fewer.",
"then": "Metric.query"
},
…
Hand our latest finished interview 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(%22Waitlist.joined%22%2C%20%22Interview.completed%22%2C%20%22Interview.abandoned%22%2C%20%22Call.requested%22%2C%20%22Evidence.created%22%2C%20%22Schedule.fired%22%2C%20%22Waitlist.admitted%22%2C%20%22Meeting.held%22%2C%20%22Customer.activated%22%2C%20%22Message.replied%22%2C%20%22Check.failed%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_1319"}'
# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22lead_71%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_71%22" \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"import { $ } from 'startup-builder'
const { events: [last] } = await $.Event.list({ where: 'name in ("Waitlist.joined", "Interview.completed", "Interview.abandoned", "Call.requested", "Evidence.created", "Schedule.fired", "Waitlist.admitted", "Meeting.held", "Customer.activated", "Message.replied", "Check.failed")', 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 (\"Waitlist.joined\", \"Interview.completed\", \"Interview.abandoned\", \"Call.requested\", \"Evidence.created\", \"Schedule.fired\", \"Waitlist.admitted\", \"Meeting.held\", \"Customer.activated\", \"Message.replied\", \"Check.failed\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1319"}' --try # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"lead_71\""}' # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"lead_71\""}' # Not live yet (gaps #7){
"name": "do",
"arguments": {
"code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Waitlist.joined\", \"Interview.completed\", \"Interview.abandoned\", \"Call.requested\", \"Evidence.created\", \"Schedule.fired\", \"Waitlist.admitted\", \"Meeting.held\", \"Customer.activated\", \"Message.replied\", \"Check.failed\")', limit: 1 }) // { play } compiled to this Play’s Trigger Events\nconst { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' }) // the same Event again, in try mode · Not live yet, gaps #7\nconst { decisions: [decision] } = await $.Decision.list({ where: `on = \"${subject}\"` }) // what it chose, and why · Not live yet, gaps #7\nconst { actions } = await $.Action.list({ where: `on = \"${subject}\"` }) // what it did, with its checks · Not live yet, gaps #7\nreturn { decision, actions }",
"mode": "try"
}
}application/json{
"decision": {
"$id": "https: //api.sb/ leaseline.app/ decisions/ decision_361",
"$type": "Decision",
"choice": "admit-now",
"reason": "Corbin Rentals manages 64 units for 3 owners and named the renewal notices they miss each month; rank 2 of 31 this week, under the cap of 10",
"stakes": "medium",
"options": [
"offer-the-interview",
"admit-now",
"keep-in-queue",
"to-you",
"not-a-fit"
],
…
sample · 4 Not live yetPreviewOn PATCH /{namespace}/campaigns/{id}Off PATCH /{namespace}/campaigns/{id}Take this one POST /{namespace}/tasks/{task}/claim
action_2 is Corbin’s result, a renewal calendar for their 64 units, held 2 minutes. action_3 waits for Monday’s admit list at 09:00, which you approve.
+23.1 per 100 · ■■□□ Early sign · n 52 · path → arr
| Try another: the signup | Choice | Reason |
|---|---|---|
| Corbin Rentals, 64 units: “We miss renewal notices for 3 owners every month.” | admit-now | fit and specific, rank 2 of 31, under the cap |
| Elm Street Homes joined the Waitlist | offer-the-interview | every signup is offered the interview |
| Dover Lane, 22 units: short, general answers | keep-in-queue | rank 19 of 31, below this week’s cap |
| Kingsley Group: “If this handles 400 units we’d pay for the year today.” | to-you | a commitment to pay is yours |
| A class project with no units | not-a-fit | fits no Offer |
- Day 3: first onboarding call booked
- First signal
Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Interview activation rate → Activation rate → New paying Customers → New Customers ↑ → ARR added each week → ARR
Worth’s formula: about +23.1 activated per 100 admits × 43 admits a month × 0.55 paid per activation × $347 first order ARR ≈ +$1,896. Under First signal: About 9 weeks to tell a +15 lift at 43 admits a month with half by form rank (5 to read, 4 to mature).
sample · api.sb/
Start it this week
npx startup-builder add play signup-interviews # 1 · writes plays/signup-interviews.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":"signup-interviews"}'
# 3 · keep it, at You approve each one
curl -X POST https://api.sb/leaseline.app/campaigns \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"play":"signup-interviews"}'
# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/signup-interviews \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"endsAt":null}'
# off: signups wait by form rank; admitted Leads keep access
curl -X PATCH https://api.sb/leaseline.app/campaigns/signup-interviews \
-H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
-H "Content-Type: application/json" \
-d '{"endsAt":"now"}' | Check | Fix | Then |
|---|---|---|
use-when pass · Not live yet, gaps #8 | Nothing to fix: 20 or more signups a month, slots for fewer. | POST /{namespace}/metrics/query |
inbound-source pass · Not live yet, gaps #8 | Nothing to fix: every signup reaches the Waitlist. | POST /{namespace}/integrations/connect |
approved-pages fail · Not live yet, gaps #8 | Publish the Waitlist Page with its weekly cap and what an admit gets. | POST /{namespace}/sites/{site}/publish |
baseline warn · Not live yet, gaps #8 | n 19: your form-rank half becomes the comparison. | POST /{namespace}/metrics/query |
role-unstaffed warn · Not live yet, gaps #8 | Staff onboarding, or leave it: every onboarding call comes to you. | POST /{namespace}/roles/{role}/staff |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "signup-interviews can’t start yet: 1 check fails and 2 warn.",
"checks": [
{
"check": "use-when",
"status": "pass",
"observed": "61 Waitlist signups in 30 days; 10 onboarding slots a week",
"doc": "/plays/signup-interviews#check-use-when",
"fix": "Nothing to fix: 20 or more signups a month, slots for fewer.",
"then": "Metric.query"
},
{
"check": "inbound-source",
"status": "pass",
"observed": "the Waitlist form posts to `Waitlist.join`",
"doc": "/plays/signup-interviews#check-inbound-source",
"fix": "Nothing to fix: every signup reaches the Waitlist.",
"then": "Integration.connect"
},
{
"check": "approved-pages",
"status": "fail",
"observed": "the Waitlist Page shows no cap, and no Page says what an admit gets",
"doc": "/plays/signup-interviews#check-approved-pages",
"fix": "Publish the Waitlist Page with its weekly cap and what an admit gets.",
"then": "Site.publish"
},
{
"check": "baseline",
"status": "warn",
"observed": "form-rank admits: 42 activated per 100, n 19 in 90 days",
"doc": "/plays/signup-interviews#check-baseline",
"fix": "n 19: your form-rank half becomes the comparison.",
"then": "Metric.query"
},
{
"check": "role-unstaffed",
"status": "warn",
"roles": [
"onboarding-specialist",
"sales-lead"
],
"owned": 31,
"doc": "/plays/signup-interviews#check-role-unstaffed",
"fix": "Staff onboarding, or leave it: every onboarding call comes to you.",
"then": "Role.staff"
}
]
}It says no, says why, and names the fix.
| Check | Fix (one call) | Your time | Wait |
|---|---|---|---|
use-when · inbound-source · pass: 61 signups in 30 days, 10 slots a week; the form posts to the Waitlist (gaps #8) | POST /{namespace}/metrics/query on interview-activation-rate; POST /{namespace}/integrations/connect if your form lives elsewhere | 1 min | none |
approved-pages · fail (Not live yet): no cap on the Waitlist Page | POST /{namespace}/sites/{site}/publish the Waitlist Page with its cap of 10 a week | 15 min | none |
baseline · warn: 42 per 100, n 19 | POST /{namespace}/metrics/query; the form-rank half fills Before in Your number | 0 min | none |
role-unstaffed · warn: 31 of your open Leads have a person owner, you | POST /{namespace}/roles/{role}/staff, or leave it: onboarding calls come to you | 0 min | none |
Your number · Before 42.3 per 100 by form rank · Now 65.4 per 100 by interview rank · Target 60 by Dec 31 · ■■□□ Early sign · n 52 matured
Each signup costs about $0.20 for the interview and its result (Worker cost), under a $150 monthly Limit; past it, voice pauses and results use the light template. Your onboarding slots cost nothing. That comes to about $23 a month at 115 signups.
When it starts
| When | Trigger id | Starts on | Window | How it gets in |
|---|---|---|---|---|
| Someone joins your open Waitlist | waitlist-joined | event on Waitlist.joined where waitlist.status = 'open' | the interview offer within 5 min; 7d | your Waitlist form posts to POST /{namespace}/waitlists/{waitlist}/join |
| A signup finishes the interview | interview-completed | event on Interview.completed where kind = 'signup' | the result within the promised hour | none: the interview runs on your Waitlist Page |
| An admit has booked no onboarding call for 2 days | admitted-unbooked | state on Waitlist.admitted where admittedAt < now - 2d and onboardingMeeting is null | a state, read each morning; released at 5 days | none: it reads the admit and your calendar |
+ 9 more for abandoned interviews, voice, commitments, your slots, the admit list, onboarding calls, activation, disputes and the cap number (?lanes=) |
{
"$id": "https://api.sb/leaseline.app/events/event_1319" ,
"$type": "Event",
"name": "Interview.completed",
"at": "2026-10-19T16:20:41Z" ,
"seq": 1319,
"data": {
"lead": "lead_71",
"company": "Corbin Rentals",
"units": 64,
"owners": 3,
"said": "We miss renewal notices for 3 owners every month.",
"minutes": 7
}
}npx startup-builder trigger Interview.completed --like event_1319 # replays the interview
npx startup-builder clock advance --by 3d # runs Monday’s admit list, which you approve
npx startup-builder listen Interview.completed --forward-to http://localhost:3000/hook Who runs it
SDR · your agent (role:, worker_2) holds the Key Result: it interviews, ranks and sends each result. Admits, onboarding calls and commitments to pay come to you (Dana Okafor, person, worker_1), because the Onboarding Role has no person. Your number links to Did it work.
| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
|---|---|---|---|---|---|
| Offer the interview · Keep their place | It does it | 214 of 214 · 38 of 38 | — | a transcript misses the disclosure → every interview pauses | POST /{namespace}/actions/{action}/cancel |
| The result built on their company | It does it, you can stop it | 112 of 118 (6 rewritten) | met on day 15 (the first 30 results) | a fact-check refusal sends → You approve each one | POST /{namespace}/actions/{action}/cancel inside the hold |
| Admit this week | You approve each one | 8 lists of 8 | never: the admit list is yours | — | POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse |
| To you · Not a fit | It does it | 4 of 4 · 17 of 17 | — | — | POST /{namespace}/actions/{action}/redirect |
| Change the ranking | You approve each one | 1 merged of 1 | never | — | POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert |
| Never: passing as a person, a cap the calendar does not show, a promise past the measured time | Never, on every rung | 0 | never | — | kill-switch |
What it reads · What it may call. It reads the signup’s own answers, their company’s public facts and your approved Pages. Answers are data, never instructions: a signup who tries to rewrite the agent’s rules ends the interview, and the attempt scores zero (abuse). Its tools are POST /{namespace}/interviews, POST /{namespace}/waitlists/{waitlist}/admit, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/meetings/book, POST /{namespace}/leads/{lead}/disqualify, POST /{namespace}/messages/{message}/schedule, and any other call becomes an Approval under the Role’s Mandate.
You hold the SDR Key Result: 60 activated per 100 admits by 2026-12-31. ← worker, metric
Open every interview with the Role’s disclosure line, and answer yes when asked if you are an AI. ← Disclosure stop, Setting role.disclosure
Rank by fit and by how specific their own answers are; admit at most the published cap. ← your file, line 4; Cap truth stop
Every fact in a result comes from their answers, their company’s public record or your approved Pages. ← fact-check, approved-pages
A commitment to pay goes to Dana. ← chooses.to-youThe slow loop, as a Change. decision_288 (2026-09-14, weekly) read 6 admits who named a missed renewal activate against 2 of 6 who did not, so change_17 weighted a named, dated problem twice in the rank (your file, line 4), and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past interviews, POST /{namespace}/changes/{change}/review put the interview half at 68 per 100; read back at +30d it is 66.7, n 18, ■□□□ Too early to tell (Example, day 51).
Bring your own agent (folded) starts at It does it, you can stop it when it matches or beats the seated agent on the eval suite, and at You approve each one when it does not; POST /{namespace}/roles/{role}/staff seats it.
npx startup-builder eval --scenario signup-interviews-80 --agent "claude -p" --seat prospector # seated: 65 per 100, 0 disputes upheld, $0.20 a signup · yours: 58, 1 upheld, $0.31 → You approve each one What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
|---|---|---|---|---|---|
Offer the interview offer-the-interview | a signup joins the open Waitlist | Your rule (the Waitlist) | signup-welcome → POST /{namespace}/interviews | the signup | the same |
Admit this week admit-now | fit and specific, in the top of the week, under the cap | Agent’s call, with its reason | POST /{namespace}/waitlists/{waitlist}/admit on Monday’s list → admission-booking | you approve the list; the onboarding call is yours · Take this one | you |
Keep their place keep-in-queue | fits, below this week’s cap | Agent’s call, with its reason | queue-update every 14 days, with their place | nobody | the same |
To you to-you | a commitment to pay, or asks to talk | Agent’s call, with its reason | POST /{namespace}/tasks/{task}/assign → POST /{namespace}/meetings/book on your calendar | you, due 1 business day · Take this one | you |
Not a fit not-a-fit | fits no Offer | Agent’s call, with its reason | POST /{namespace}/leads/{lead}/disqualify (noFit) → their result and an honest no | nobody; the reason feeds the fit Policy | the same |
| When they write back | Fixture reply | What happens | Who answers | By when | Call |
|---|---|---|---|---|---|
| Interested | “Monday 10:00 works for the onboarding call.” | books it on your calendar; the Brief goes with it | you | 1 business day | POST /{namespace}/meetings/book |
| Send me pricing | “What does it cost after the Waitlist?” | answers with the Pricing Page’s list Price and one next step | SDR · your agent | 5 min | POST /{namespace}/conversations/{conversation}/answer |
| Not now | “Let’s start after our busy season.” | their place is kept; queue updates stop until they write | SDR · your agent | at once | POST /{namespace}/leads/{lead}/nurture |
| Wrong person | “Our office manager, Kim, handles software.” | asks them to bring Kim in; it never writes to an address from their text | SDR · your agent | 1 business day | POST /{namespace}/conversations/{conversation}/answer |
| Out of office | an auto-reply until Oct 28 | the booking reminder waits for the return date | nobody | the return date | POST /{namespace}/messages/{message}/schedule |
| Question it can’t answer | “Can you import from our accounting system?” | To you, with the question in the Brief | you | 1 business day | POST /{namespace}/conversations/{conversation}/escalate |
| Stop | “Take me off the Waitlist.” | nothing else sends, on any lane | nobody | at once | POST /{namespace}/contacts/{contact}/suppress |
When it hands to you
Admits and commitments to pay come to you: the onboarding call, and the Monday list to approve. One Brief per Role, then the Approval, as captured (brief, draft and checks are Not live yet, gaps #7).
[
{
"$id": "https://api.sb/leaseline.app/tasks/task_552" ,
"$type": "Task",
"assignee": "worker_1",
"due": "2026-10-20T17:00:00Z" ,
"on": "lead_71",
"brief": {
"who": "Corbin Rentals, 64 units, 3 owners" ,
"said": "We miss renewal notices for 3 owners every month.",
"chose": "admit-now",
"why": "rank 2 of 31, under the cap of 10" ,
"sent": "a renewal calendar for their 64 units",
"next": "your 20-minute onboarding call"
}
},
{
"$id": "https://api.sb/leaseline.app/tasks/task_509" ,
"$type": "Task",
"assignee": "worker_1",
"due": "2026-10-07T17:00:00Z" ,
"on": "lead_64",
"brief": {
"who": "Kingsley Group, about 400 units" ,
"said": "If this handles 400 units we’d pay for the year today.",
"chose": "to-you",
"why": "a commitment to pay is yours",
"never": [
"a price beyond the list",
"a date the calendar does not show"
]
}
},
{
"$id": "https://api.sb/leaseline.app/approvals/approval_58" ,
"$type": "Approval",
"verdict": null,
"deadline": "2026-10-20T09:00:00Z" ,
"draft": "Admit list, week of Oct 19: 5 by interview rank, 5 by form rank" ,
"route": "admit-now",
"checks": [
{
"check": "cap-truth",
"status": "pass"
}
]
}
]You answer with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, each a one-call window; an admit list unanswered by Monday 09:00 waits, and nobody is admitted without it. A Task nobody claims by its due time counts toward person-promise.
On time: you, 8 of 8 admit lists approved by Monday 09:30, and 4 of 4 commitments answered within 1 business day, median 3 h, n 12, ■■□□ Early sign. Your queue: in week 1, 5 test interviews and 30 results to approve; after the promotion, 1 admit list and about 1 commitment a week.
The fixed line: POST /{namespace}/deals/{deal}/assign sets owner to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.
When it won’t send
| Check (refuses one send) | Refuses | Fix | Then |
|---|---|---|---|
owned-by-a-person (rule j, gaps #8) | a send to a signup whose Lead a person owns, or whose Conversation a person claimed | Leave it to the person who owns it: the draft waits in their queue. | POST /{namespace}/tasks/{task}/assign |
fact-check (hub guard on POST /{namespace}/content/{content}/publish) | a result with a claim no answer, public record or approved Page backs | Cut the claim, or name the record that backs it. | POST /{namespace}/content/draft |
approved-pages (Not live yet) | a sentence about Leaseline that no approved Page backs | Cut the sentence, or publish the Page that says it. | POST /{namespace}/sites/{site}/publish |
consent-stop (gaps #3) | an introduction to your other Startup the signup has not said yes to | Ask once for a yes to the other Startup. | POST /{namespace}/messages/{message}/schedule |
The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that sent is the Dover Lane thread in Example.
| Check | Fix | Then |
|---|---|---|
fact-check fail · Not live yet, gaps #1 | Cut the claim, or name the record that backs it. | POST /{namespace}/content/draft |
approved-pages pass · Not live yet, gaps #8 | — | POST /{namespace}/sites/{site}/publish |
JSON
{
"type": "https://startupbuilder.dev/errors/refused",
"title": "Refused",
"status": 422,
"detail": "The result to Dover Lane did not send: it says their 22 units lose $3,800 a year to late renewals, which nothing they said or published backs.",
"checks": [
{
"check": "fact-check",
"status": "fail",
"doc": "/plays/signup-interviews#check-fact-check",
"fix": "Cut the claim, or name the record that backs it.",
"then": "Content.draft"
},
{
"check": "approved-pages",
"status": "pass"
}
]
}It says no, says why, and names the fix.
[
{
"reason": {
"limit": "promise",
"observed": "p90 74 min",
"bound": "60 min",
"window": "7d"
},
"doc": "/plays/signup-interviews#stop-promise" ,
"task": "task_398"
}
]Did it work
Each week’s admits were picked at random by interview rank or by form rank, so both halves come from one random assignment (rules m–o); each figure’s call is POST /{namespace}/metrics/query by node and by arm, and every node above the leaf is Not live yet (gaps #4).
+23.1 per 100 · ■■□□ Early sign · n 52 · path → arr
- Chose
- admit-now
- Why
- Corbin Rentals manages 64 units for 3 owners and named the renewal notices they miss each month; rank 2 of 31 this week, under the cap of 10
- From
- offer-the-interview · admit-now · keep-in-queue · to-you · not-a-fit
- Expects
- activation within 30d of admission
- Reopens when
- no Meeting.booked for lead_71 within 2d of admission
- By
- worker_2
JSON
{
"$id": "decisions/decision_361",
"$type": "Decision",
"choice": "admit-now",
"reason": "Corbin Rentals manages 64 units for 3 owners and named the renewal notices they miss each month; rank 2 of 31 this week, under the cap of 10",
"stakes": "medium",
"options": [
"offer-the-interview",
"admit-now",
"keep-in-queue",
"to-you",
"not-a-fit"
],
"by": "worker_2",
"on": "lead_71",
"expected": "activation within 30d of admission",
"reopensWhen": "no Meeting.booked for lead_71 within 2d of admission"
}| Node | Interview rank | Form rank | Added | Confidence | Basis |
|---|---|---|---|---|---|
interview-activation-rate | 65.4 per 100 (17 of 26) | 42.3 (11 of 26) | +23.1 [0.4, 45.8] | ■■□□ Early sign | admits picked at random by rank · n 52 · 28 still maturing |
activation-rate | 65.4 per 100 (17 of 26) | 42.3 (11 of 26) | +23.1 [0.4, 45.8] | ■■□□ Early sign | the same assignment; every admit starts a trial |
new-paying-customers | 34.6 per 100 (9 of 26) | 23.1 (6 of 26) | +11.5 [−12.9, 35.9] · Not carrying up yet | ■□□□ Too early to tell | the same · 8 trials still deciding |
new-arr ↑ | $3,123, 9 Customers · Booked $5,205 across both halves: credited, not all caused by this Play | $2,082, 6 Customers | +$1,041 [−$1,500, +$3,600] · Worth about +$1,900 a month | ■□□□ Too early to tell (9 vs 6 Customers) | the same |
net-new-arr · arr | +$3,123 | +$2,082 | +$1,041, carried: it moves no other bridge term | ■□□□ Too early to tell | carried from new-arr |
The leaf counts admits with a finished interview who reach activation within 30 days of admission, per 100 admits in each half; only admits 30 days past admission count. It runs to 30 matured in each half, and at 26 and 26 the Experiment runs on.
How it moves it: the onboarding slots went to the signups who named a dated problem in their own words; their results took a median of 38 minutes.
Guardrails: interview half against form half: onboarding calls held per admit, 0.92 against 0.85, and same-month cancels, 1 against 2; 55 % of offers completed the interview against a 15 % floor.
{
"$id": "https://api.sb/leaseline.app/campaigns/signup-interviews" ,
"$type": "Campaign",
"play": "play:signup-interviews@1" ,
"path": [
"interview-activation-rate",
"activation-rate",
"new-paying-customers",
"new-arr",
"net-new-arr",
"arr"
],
"experiment": {
"metric": "interview-activation-rate",
"unit": "per-100",
"heldBack": 40,
"decision": null
},
"readout": {
"value": 23.1,
"n": 52,
"maturing": 28,
"interval": [
0.4,
45.8
],
"readability": "C",
"basis": "held-back",
"pooled": false
},
"ledger": {
"spend": 23,
"workerCost": 19,
"hours": 4.5,
"pipelineArr": 2776,
"wonArr": 5205,
"projectedArr": 1896,
"paybackDays": 5
}
}Outside benchmark: 41 % of free signups to business software reach first value within 30 days (a product-analytics firm’s study of 2,100 companies, 2026-08-31).
Before it · After it. Before it: paid-social, founder-voice and reserve-drop fill the Waitlist. After it: product-led hears the admits who activate, and founder-voice hears the consented quotes from interviews.
Example
Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days). 214 people joined the Waitlist, 118 finished the interview, and 80 were admitted under the cap of 10 a week: 40 by interview rank and 40 by form rank, at random. 52 have matured and 28 are still maturing. Read every captured thread at ?threads=; three follow the tables.
| What happened, by option | Decisions | Activated | Won (credited, not all caused by this Play) |
|---|---|---|---|
| Offer the interview | 214 | 118 finished (55 %) | — |
| Admit this week, interview half · form half | 40 · 40 | 17 of 26 matured · 11 of 26 | 9 on Pro (+$3,123 ARR) · 6 on Pro (+$2,082 ARR) |
| Keep their place · To you · Not a fit | 38 · 4 · 17 | — · 4 calls held by you · — | 1 trial still deciding |
| At 20 signups a month (the Use it when volume) | about 37 in 56 days | held back at random; 90 days tells +30 or more | Other Startups’ results: +14 per 100, ■■■□ Likely, n 4,400 |
| Day | Event | What happened | Your time |
|---|---|---|---|
| 0 | event_119 Campaign.created | the three steps; dry run fails approved-pages | 15 min |
| 0 | event_125 Site.published | the Waitlist Page with its cap of 10 a week; you took 5 test interviews | 45 min |
| 3 | event_190 Meeting.booked | the first onboarding call booked from an admit | — |
| 15 | event_372 Role.updated | promoted: results send after a 2-minute hold | — |
| 21 · 51 | event_511 Change.merged · event_866 Readout.created | a named, dated problem weighted twice: replayed at 68 per 100, read back at +30d at 66.7, n 18 | 5 min |
| 29 | event_590 Campaign.paused | promise: p90 74 min; the Page now says within 75 minutes | 5 min |
| 1–56 | event_131 Approval.created, first of 38 | you approved 30 results and 8 admit lists; weekly reviews, from the POST /{namespace}/tasks/next log | 3.3 h · total 4.5 h measured, 4.5 h asked |
Corbin Rentals, 16:13 · “We miss renewal notices for 3 owners every month.” *The Role’s disclosure line opened the interview.*¹
Leaseline, 16:58 · Here is a renewal calendar for your 64 units, by owner, with each notice 60 days out.² You’re admitted from Monday: pick a 20-minute onboarding call with Dana.³
Corbin, Oct 19, 17:20 · booked Monday 10:00.
Meeting.bookedon Dana’s calendar.
- Your 22 units lose about $3,800 a year to late renewals.
+ You said 4 of your 22 leases renewed late this year; here is when each notice goes out next. Kingsley Group, 2026-10-06 11:40 · “If this handles 400 units we’d pay for the year today.” · Leaseline, 11:41 · *Thanks. Dana, our founder, replies about the annual plan by 17:00 tomorrow.*⁴ The Brief went to Dana (
task_509); she booked a call for 15:00 the same day.
¹ The fixed disclosure line, compiled from the Role’s Settings. ² Every fact comes from their own answers. ³ One next step, inside the published cap. ⁴ The routed line, compiled from the Role’s Settings.
Your settings
---
holdout: 0.5 # half of each week’s admits by form rank, as today, so we can tell
---
Admit 10 a week, from Dana’s onboarding slots. Rank by fit, and weight a named, dated problem twice.
Commitments to pay go to Dana.$ npx startup-builder show plays/signup-interviews
holdout 0.5 · cap 10 a week · named problem ×2 your file plays/signup-interviews.mdx:2,4,5 (Ask 2026-08-24; line 4 by change_17, 2026-09-14)
family demand · worker role:prospector, owns never · chooses 5 (1 rule, 4 read) · sequences signup-welcome, queue-update, admission-booking, post-call-activation · checks owned-by-a-person, fact-check, approved-pages, consent-stop · stops 11 · placements gmail, outlook, yahoo-mail, linkedin, x, google-search, portfolio-network catalog play:signup-interviews (Not live yet, gaps #5) Every key from the catalog
Compiled, not written: edit the Play record signup-interviews 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.