Skip to content

Developer relations

Developer relations fixes what coding agents read, call by call, and ships each fix only when the suite and time to first call agree.

Channel
AI answers
Run oneMode try
You, to your agent

Hand our latest stalled API key to the Content Lead agent and show me what it chose and why. Don’t send.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Action.evaluated%22%2C%20%22APIKey.stalled%22%2C%20%22Question.asked%22%2C%20%22Monitor.matched%22%2C%20%22Version.deployed%22%2C%20%22Version.deprecated%22%2C%20%22Monitor.checked%22%2C%20%22Gathering.scheduled%22%2C%20%22APIKey.activated%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_1405"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Action.evaluated", "APIKey.stalled", "Question.asked", "Monitor.matched", "Version.deployed", "Version.deprecated", "Monitor.checked", "Gathering.scheduled", "APIKey.activated")', 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 (\"Action.evaluated\", \"APIKey.stalled\", \"Question.asked\", \"Monitor.matched\", \"Version.deployed\", \"Version.deprecated\", \"Monitor.checked\", \"Gathering.scheduled\", \"APIKey.activated\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1405"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"key_61\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"key_61\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Action.evaluated\", \"APIKey.stalled\", \"Question.asked\", \"Monitor.matched\", \"Version.deployed\", \"Version.deprecated\", \"Monitor.checked\", \"Gathering.scheduled\", \"APIKey.activated\")', 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_447",
    "$type": "Decision",
    "choice": "fix-what-agents-read",
    "reason": "9 of 14 stalled keys this week failed on POST /notices with a 400 that names no field; the suite fails that call 3 of 5 runs",
    "stakes": "medium",
    "options": [
      "fix-what-agents-read",
      "repair-a-snippet",
      "answer-the-developer",
      "notes-for-agents",
      "host-a-hackathon",
      "to-a-person"
  …
sample · 4 Not live yetPreview

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

action_3 replayed the suite on the new error: POST /notices passes 5 of 5 runs, up from 2 of 5. action_5 is your Approval to merge change_31 behind a 50/50 Flag split by key.

11 min median first call against 47 min before · before-after, not proof · n 34 keys · path → arr

Try another: the stalled keyChoiceReason
key_61, Harbor Row’s developer: 3 failed POST /notices calls in 4 minutesfix-what-agents-readthe same unnamed 400 stalled 9 of 14 keys this week
The renewal reminder docs block fails its sandbox run after Tuesday’s releaserepair-a-snippetits verification line returns 401, not the stated output
Repository issue: “How do I send a notice to every unit in a building?”answer-the-developera verified block answers it
GET /v1/tenants gets a removal date of 2027-01-15notes-for-agentsa removal date is set: notes and the 90-day notice
Repository issue: “Can we get a higher rate Limit on an annual plan?”to-a-personterms are never the agent’s call

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Time to first call → Activation rate → New paying Customers → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +6 activated per 100 new Customers (Other Startups’ results; no lift of your own yet) × 20 new keys a month × 0.8 paid per activated × $347 first order ARR ≈ +$333. Under First signal: At 34 new keys in 56 days, 90 days can tell only a 20-minute drop in time to first call or more, so it reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on APIKey.stalled · first fix drafted 14m · 9 keys Not live yet

Start it this week

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

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

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

# off: no new fix ships; live Pages and errors keep serving
curl -X PATCH https://api.sb/leaseline.app/campaigns/developer-relations \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refuseddeveloper-relations can’t start yet: 1 check fails and 1 warns.
CheckFixThen
use-when pass · Not live yet, gaps #8Under 20 a month it runs, but reads before-after only.POST /{namespace}/metrics/query
baseline pass · Not live yet, gaps #8None needed: 47 minutes is your Before.POST /{namespace}/metrics/query
approved-pages fail · Not live yet, gaps #8Publish the API reference Page; answers quote only verified blocks on it.POST /{namespace}/sites/{site}/publish
role-unstaffed warn · Not live yet, gaps #8Staff the Content Lead, or leave it: every Change comes to you.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "developer-relations can’t start yet: 1 check fails and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "22 new keys in 90 days at a 47-minute median first call; 7 a month, under 20",
      "doc": "/plays/developer-relations#check-use-when",
      "fix": "Under 20 a month it runs, but reads before-after only.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "47 min median first call, n 22 keys in 90 days",
      "doc": "/plays/developer-relations#check-baseline",
      "fix": "None needed: 47 minutes is your Before.",
      "then": "Metric.query"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/developer-relations#check-approved-pages",
      "fix": "Publish the API reference Page; answers quote only verified blocks on it.",
      "then": "Site.publish"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "content-lead"
      ],
      "owned": 0,
      "doc": "/plays/developer-relations#check-role-unstaffed",
      "fix": "Staff the Content Lead, or leave it: every Change comes to you.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · baseline · pass: 22 keys in 90 days, 47 min median first call (gaps #8)POST /{namespace}/metrics/query on time-to-first-call, which fills Before in Your number1 minnone
approved-pages · fail (Not live yet)POST /{namespace}/sites/{site}/publish the API reference Page15 minnone
role-unstaffed · warn (gaps #8): no Content Lead seatPOST /{namespace}/roles/{role}/staff, or leave it: every Change comes to you0 minnone

Your number · Before 47 min · Now 11 min median first call · Target under 10 min by Dec 31 · before-after, not proof · n 34 keys

Each suite run costs about $0.40 in model calls across 5 agent profiles (Worker cost), under a $300-a-month suite Limit; snippet runs in the sandbox cost nothing. That comes to about $40 a month at 100 runs.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A new key fails 3 calls in a row, or has no success in 30 minfirst-call-stallstate on APIKey.stalled where 3 failed calls in a row, or no success 30m after the first call7dyour API reports each call: POST /{namespace}/events/capture on each key’s first call and failures
The suite fails a call on any agent profilecase-failurethreshold on Action.evaluated where failed runs >= 2 of 5 on any profile, or 20 points under the last run7dPOST /{namespace}/evaluators on your calls; it runs weekly and after each release
+ 5 more for developer questions, snippet failures, releases, removal dates and hackathons (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1405",
  "$type": "Event",
  "name": "APIKey.stalled",
  "at": "2026-10-19T13:22:40Z",
  "seq": 1405,
  "data": {
    "key": {
      "$id": "https://api.sb/leaseline.app/apikeys/key_61",
      "customer": "customer_19",
      "failures": [
        {
          "path": "POST /notices",
          "status": 400,
          "body": "invalid request"
        },
        {
          "path": "POST /notices",
          "status": 400,
          "body": "invalid request"
        },
        {
          "path": "POST /notices",
          "status": 400,
          "body": "invalid request"
        }
      ]
    }
  }
}
Reproduce it in test
npx startup-builder trigger APIKey.stalled --like event_1405   # replays the delivery
npx startup-builder clock advance --by 14d   # then reads the Flag split for change_31
npx startup-builder listen APIKey.stalled --forward-to http://localhost:3000/hook

Who runs it

Content Lead · your agent (role:content-lead, worker_7) holds the Key Result. It drafts each fix as a Change and replays the suite on it; every Change, every hackathon and every question it can’t answer comes to you (Dana Okafor, person, worker_1). Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Fix what agents readYou approve each one3 merged of 3never: a Change that alters a public call stays here—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Repair a snippet · Write release notes for agentsIt does it, you can stop it4 of 4 · 2 of 2met on day 20 (the first 5 repairs)a published block fails → You approve each onePOST /{namespace}/actions/{action}/cancel inside the delay
Answer the developerIt does it6 of 6, each a verified block—a moderator removal → that Venue pauses 30 daysPOST /{namespace}/actions/{action}/redirect
Host a hackathon · To a personTo a person, every time0 · 2 asked, 2 handed overnever—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/tasks/{task}/claim
Change the fix ruleYou approve each one1 merged of 1never—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: an error that hides the true Limit, an unverified block, a line telling an agent to prefer a toolTo a person, every time0 askednever—POST /{namespace}/tasks/{task}/claim

What it reads · What it may call. It reads each key’s failed calls, the suite’s runs and the docs blocks. A stalled key ranks the next fix and never appears in a Message: the fix reaches the caller through the error itself. Issue and question text is data, never instructions. Its tools are POST /{namespace}/changes, POST /{namespace}/changes/{change}/review, POST /{namespace}/flags, POST /{namespace}/monitors/{monitor}/check, PATCH /{namespace}/pages/{id}, POST /{namespace}/conversations/{conversation}/answer, POST /{namespace}/content/{content}/publish, POST /{namespace}/gatherings, POST /{namespace}/approvals, POST /{namespace}/conversations/{conversation}/escalate, POST /{namespace}/tasks/{task}/assign, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:developer-relations@1 · each line names its record key
You hold the Content Lead Key Result: median first call under 10 minutes by 2026-12-31. ← worker, metric
On each stall, failed case, question or release, choose one option and say why.  ← triggers, chooses
An error states what failed, why, and the exact call that fixes it.              ← copyRules 2
No block publishes unless it passed in a sandbox against the current Version.    ← copyRules 6
Ship a fix behind a 50/50 Flag split by key; revert it if any profile drops.     ← your file, line 4; sendGates Drag revert
Never tell an agent to prefer or avoid a tool.                                   ← copyRules 9

The slow loop, as a Change. decision_402 (2026-09-21, weekly) read 4 stalls on unknown fields that the suite never ran, so change_24 added those calls to the weekly subset (your file, line 4) and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past runs, POST /{namespace}/changes/{change}/review put 2 more failing calls in the queue; read back at +14d, both were fixed and the stall count fell from 6 a week to 2, n 12 keys, before-after.

Bring your own agent (folded) drafts Changes at You approve each one, like the seated agent; the eval grades its fixes on the same suite; POST /{namespace}/roles/{role}/staff seats it.

Terminal
npx startup-builder eval --scenario developer-relations-34 --agent "claude -p" --seat content-lead   # seated: 11 min replayed first call, 29 of 30 suite runs pass, $0.38 a run · yours: 13 min, 27 of 30, $0.52

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Fix what agents read fix-what-agents-reada call fails 2 of 5 runs, or stalls share one errorAgent’s call, with its reasonPOST /{namespace}/changes → POST /{namespace}/changes/{change}/review on the suite → POST /{namespace}/flags 50/50 by keyPOST /{namespace}/tasks/{task}/assign → you approve the merge, due 1 business day · Take this oneyou
Repair a snippet repair-a-snippeta published block fails its sandbox runYour rule (copy rule 6)POST /{namespace}/monitors/{monitor}/check → PATCH /{namespace}/pages/{id}; the block shows failing within 10 minnobodythe same
Answer the developer answer-the-developerasks how to make a call, and a verified block answers itAgent’s call, with its reasonanswer-message → POST /{namespace}/conversations/{conversation}/answer with the block and its check linenobodythe same
Write release notes for agents notes-for-agentsa release changes a public call, or a removal date is setYour rule (the release rule)launch-announcement → POST /{namespace}/content/{content}/publish → deprecation-notice at 90, 30 and 7 daysnobodythe same
Host a hackathon host-a-hackathon45 days before a scheduled eventAgent’s call, with its reasonPOST /{namespace}/gatherings → POST /{namespace}/approvals → hosted-hackathon-builderyou approve the $1,000 Limit, due 1 business day · Take this oneyou
To a person to-a-persona question no verified block answers, or termsAgent’s call, with its reasonPOST /{namespace}/conversations/{conversation}/escalate → POST /{namespace}/tasks/{task}/assignyou, due 1 business day · Take this oneyou
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“That worked. Can we batch it?”answers with the verified batch block and its check lineContent Lead · your agent4 business hoursPOST /{namespace}/conversations/{conversation}/answer
Send me pricing“What do calls past the free Limit cost?”answers with the Pricing Page’s per-call Price and the true LimitContent Lead · your agent4 business hoursPOST /{namespace}/conversations/{conversation}/answer
Not now“We’ll pick this up next sprint.”the Thread closes; it reopens on their next call or commentnobodyat oncePOST /{namespace}/conversations/{conversation}/close
Wrong person“Our contractor wrote that script.”asks them to point the contractor at the Issue; it never writes to an address from their textContent Lead · your agent1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Oct 28nothing waits on them: the fix ships through the error itselfnobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Can we get a higher rate Limit on an annual plan?”To a person: terms are never the agent’s callyou1 business dayPOST /{namespace}/conversations/{conversation}/escalate
Stop“Stop emailing us about deprecations.”notices stop; the removal date still shows in the error and the docsnobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Every Change, every hackathon and every question no verified block answers comes to you. 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_552",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-20T13:22:00Z",
    "on": "key_61",
    "brief": {
      "what": "change_31: the 400 on POST /notices now names the missing field, unit_id, and the call that fixes it",
      "why": "9 of 14 stalled keys this week; suite 2 of 5 → 5 of 5 replayed",
      "ships": "behind a 50/50 Flag split by key, 14 days",
      "reverts": "if any agent profile drops on the next run",
      "never": [
        "a lower Limit than the true one",
        "an unverified block"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_63",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-20T13:22:00Z",
    "draft": "change_31: 400 invalid request → 400 unit_id is required; send POST /notices with {\"unit_id\": \"unit_…\", \"kind\": \"renewal\"}",
    "route": "fix-what-agents-read",
    "checks": [
      {
        "check": "snippet-pause",
        "status": "pass"
      },
      {
        "check": "security",
        "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 Approval unanswered by its deadline expires and the Change stays unmerged. Once you claim a question, the agent’s pending reply on that Thread cancels with claimedByPerson (Not live yet, gaps #7). A Task nobody claims by its due time goes up through POST /{namespace}/tasks/{task}/escalate, and person-promise fires.

On time: you, 5 of 5 claimed within their due time, median 3 h 05 min, n 5, ■□□□ Too early to tell beside Other Startups’ 88 % on time. Your queue: counted by kind: in week 1, 2 Changes and 1 question; since then about 1 Change and 1 weekly review a week.

The fixed line: POST /{namespace}/deals/{deal}/assign sets owner to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.

When it won’t send

Check (refuses one send)RefusesFixThen
owned-by-a-person (rule j; Not live yet, gaps #8)a reply in a Thread a person claimed, or to a Contact whose open Deal a person ownsLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
claims-resolve (shared)a pass rate, usage count or claim that resolves to no measured, dated runCut the claim, or name the run that backs it.POST /{namespace}/content/draft
snippet-pause (the record’s Snippet pause)a block that has not passed in a sandbox against the current Version, or a Change that breaks oneRun the block in the sandbox; it publishes once its check line matches.POST /{namespace}/monitors/{monitor}/check
credit (the record’s Credit stop)an event credit past its Limit, or a key drawing credits from 2 accountsRaise the event Limit, or block the second account.POST /{namespace}/limits/{limit}/raise
Stop (pauses the Play)Pauses whenThen
drag-reverta merged fix loses its Flag split, or any profile drops on the next runthe Change reverts with POST /{namespace}/changes/{change}/revert
securitya suite run grants more access than its task needsthat call fails and its Pages pin at You approve each one
first-call-regressionmedian first call up 25 % week over week, at 50+ new keysnew fixes freeze; POST /{namespace}/issues
costsuite runs reach their token Limitruns drop to the regression subset; raising it is an Approval
hackathon-flooran event under 5 kept event keys per $1,000 at day 30the series stops until a new Decision
venue-noticea moderator removes an answer, or a Venue sends a noticethat Venue’s answers pause for 30 days
kill-switchyou press itevery Tactic pauses; live Pages and errors keep serving

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

422RefusedThe answer on the repository Issue did not send: its block never passed in the sandbox against the current Version.
CheckFixThen
snippet-pause failRun the block in the sandbox; it publishes once its check line matches.POST /{namespace}/monitors/{monitor}/check
claims-resolve pass—POST /{namespace}/content/draft
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The answer on the repository Issue did not send: its block never passed in the sandbox against the current Version.",
  "checks": [
    {
      "check": "snippet-pause",
      "status": "fail",
      "doc": "/plays/developer-relations#check-snippet-pause",
      "fix": "Run the block in the sandbox; it publishes once its check line matches.",
      "then": "Monitor.check"
    },
    {
      "check": "claims-resolve",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "drag-revert",
      "observed": "4 of 5 → 3 of 5 on one agent profile",
      "bound": "no drop",
      "window": "1 suite run"
    },
    "doc": "/plays/developer-relations#stop-drag-revert",
    "task": "task_538"
  }
]

Did it work

At 34 new keys in 56 days the Flag splits read each fix, but the leaf has too few keys a week for a held-back half, so its basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. Every node above the leaf is Not live yet (gaps #4).

11 min median first call against 47 min before · before-after, not proof · n 34 keys · path → arr

Chose
fix-what-agents-read
Why
9 of 14 stalled keys this week failed on POST /notices with a 400 that names no field; the suite fails that call 3 of 5 runs
From
fix-what-agents-read · repair-a-snippet · answer-the-developer · notes-for-agents · host-a-hackathon · to-a-person
Expects
median time to first call under 15 min for keys on the new error, within 14d
Reopens when
Flag.evaluated split shows no drop for change_31 within 14d
By
worker_7
JSON
{
  "$id": "decisions/decision_447",
  "$type": "Decision",
  "choice": "fix-what-agents-read",
  "reason": "9 of 14 stalled keys this week failed on POST /notices with a 400 that names no field; the suite fails that call 3 of 5 runs",
  "stakes": "medium",
  "options": [
    "fix-what-agents-read",
    "repair-a-snippet",
    "answer-the-developer",
    "notes-for-agents",
    "host-a-hackathon",
    "to-a-person"
  ],
  "by": "worker_7",
  "on": "key_61",
  "expected": "median time to first call under 15 min for keys on the new error, within 14d",
  "reopensWhen": "Flag.evaluated split shows no drop for change_31 within 14d"
}
NodeNow (56 days)Before (the 90 days, per 56)AddedConfidenceBasis
time-to-first-call ↓11 min median, n 34 keys; 29 of 34 succeed within 30 min47 min, n 22 keys; 12 of 22——before-after, not proof · Other Startups’ results −21 min, ■■■□ Likely, n 3,410 keys
activation-rate75 % (9 of 12 new Customers)54 % (7 of 13)——before-after
new-paying-customers · new-arr ↑$1,735, 5 Customers whose first call came through a key · Booked: credited, not all caused by this Play$1,388, 4 Customers— · Worth about +$330 a month—before-after · 6 trials still deciding
net-new-arr · arrcarried from new-arrcarried——carried

Before against after reads 56 days against the 90 days before, scaled to 56; it is not proof, and Other Startups’ results print beside it. Each fix’s own Flag split prints in Example as what happened, never as the Play’s result.

How it moves it: the 3 merged errors now name the missing field and the call that fixes it, and 9 of 11 docs blocks carry a passing check line.

Guardrails: before against after: paid per activated, 0.56 against 0.57, and support Threads per new key, 0.21 against 0.45; 6 trials are still deciding.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/developer-relations",
  "$type": "Campaign",
  "play": "play:developer-relations@1",
  "path": [
    "time-to-first-call",
    "activation-rate",
    "new-paying-customers",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "time-to-first-call",
    "unit": "minutes",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 34,
    "maturing": 6,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 0,
    "workerCost": 74,
    "hours": 3.1,
    "openArr": 2082,
    "wonArr": 1735,
    "projectedArr": 333,
    "paybackDays": 16
  }
}

Outside benchmark: a warning that names the wrong call first raised agent pass rates 20 to 100 points over a tip (a platform vendor’s agent-experience experiments, in Your settings).

Before it · After it. Before it: agent-legibility and agent-registries bring the agents that make first calls. After it: usage-upsell hears the keys whose use climbs past their Limit, and instant-response answers the developers who write in.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 34 new keys, 14 stalls, 3 merged fixes, 4 snippet repairs and 8 developer questions. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsShippedIts own Flag split, 14 days
Fix what agents read43 merged, 1 revertedPOST /notices: new error 9 min median, old 41 min, n 18 keys
Repair a snippet · Write release notes for agents4 · 24 · 2—
Answer the developer · To a person6 · 26 · 2 by you—
All new keys · the 90 days before, per 563411 min median first call47 min, n 22
At 20 a month (the Use it when volume)about 37 in 56 daysbefore-after, not proofOther Startups’ results: −21 min, ■■■□ Likely, n 3,410
DayEventWhat happenedYour time
0event_1371 Campaign.createdthe three steps; the dry run fails approved-pages20 min
0event_1372 Site.publishedthe API reference Page goes live with check lines15 min
9event_1380 Change.mergedthe first fix ships behind its Flag split: GET /leases names its date format10 min
20event_1388 Role.updatedpromoted: snippet repairs and release notes run after a delay—
28event_1394 Change.merged · event_1397 Campaign.pausedthe second fix lost a point on one profile; drag-revert reverted it10 min
56event_1405 APIKey.stalledkey_61 stalls on POST /notices; change_31 goes to you5 min
1–56event_1374 Approval.created, first of 5you approved 4 Changes and refused 1; weekly reviews, from the POST /{namespace}/tasks/next log1 h 40 min · total 3.1 h measured, 3 h asked

Repository issue, Oct 6, 09:14 · “How do I send a notice to every unit in a building?”

Leaseline, 09:31 · Send one POST /notices per unit with "building": "bld_12" and "kind": "renewal", or one POST /notices/batch for up to 500 units.¹ The block below is verified: it prints “42 notices queued” on the sandbox building.² *Signed with the Role’s disclosure line.*³

Developer, 09:52 · “Worked first try.” Their key made its first successful batch call at 09:49.

Repository issue, 2026-09-30 · the draft snippet-pause refused, then the rewrite that sent
- leaseline notices send --all
+ leaseline notices send --building bld_12   # verified 2026-10-02: prints "42 notices queued"

Repository issue, 2026-10-14 15:02 · “Can we get a higher rate Limit on an annual plan?” · Leaseline, 15:04 · *Thanks. Dana, our founder, handles plans and replies here by 15:02 tomorrow.*⁴ The Brief went to Dana (task_549); she replied at 10:30.

¹ It names the right call first. ² The verification line sits under the block. ³ The fixed signature line, compiled from the Role’s disclosure Setting. ⁴ The routed line, compiled from the Role’s Settings.

Your settings

plays/developer-relations.mdx
---
holdout: 0.5   # each fix ships to half the new keys for 14 days, behind its Flag
---
Fix the errors and docs agents read on our API, and test every block in the sandbox. I approve every Change.
Text
$ npx startup-builder show plays/developer-relations
holdout 0.5 per fix · you approve every Change     your file  plays/developer-relations.mdx:2,4 (Ask 2026-08-24; suite subset widened by change_24, 2026-09-21)
family demand · process content-marketing · worker role:content-lead, owns never · chooses 6 (2 rule, 4 read) · sequences deprecation-notice, hosted-hackathon-builder · checks owned-by-a-person, claims-resolve, snippet-pause, credit · stops 7 · placements npm, mcp-registry, github, stack-overflow, youtube, x, linkedin, gmail, outlook, yahoo-mail    catalog  play:developer-relations@1 (Not live yet, gaps #5)

Every key from the catalog

Key Id What it is
Tactic verb-case-intake Verb Case intake: Verb case intake turns stalled first calls, developer questions and agent requests into efficacy cases per Verb, with checklists written from outside. Starts at Sends nothing.
Tactic agent-read-fix Fix what agents read repairs error text, warnings, release notes and starter Pages behind a failing case, gated by the suite and a Flag split. Starts at You approve each one.
Tactic snippet-verification Snippet verification runs every copyable docs block and its verification line on each candidate Version and nightly, and pauses any block that fails. Starts at You approve each one.
Tactic release-notes-for-agents Release notes for agents writes one line per Change, a warning for each changed default, and each deprecation in the response and in notices. Starts at You approve the first wave.
Tactic instruction-file-test Instruction file test gates each challenger description on load rate and task success in the suite, splits it per install, and ships the winner. Starts at It does it, you can stop it.
Tactic hosted-hackathon Hosted hackathon runs one online build event a quarter with prizes for multi-Verb builds, measured by keys issued under the event prefix. Starts at You approve each one.
Tactic first-call-readout First-call Readout reads median time to first call and first-call success weekly, split by caller kind and Interface, beside the suite’s pass rate per Verb. Starts at Sends nothing.
Tactic tool-description-lint Tool description lint blocks any description that holds hidden text, addresses the reading agent, names a rival, or states a fact the claims source lacks. Starts at Sends nothing.
Tactic description-variant-test Description variant test gates each challenger description on the pick-rate suite, then splits it per caller through a Flag and ships the winner everywhere. Starts at Sends nothing.
Tactic placement-code Placement code gives each placement a vanity Page, a Stripe promotion code and, for events, an API Key prefix, each tested before it runs. Starts at Sends nothing.
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.
Trigger case-failure Case failure: threshold on Action.evaluated, window 7d.
Trigger first-call-stall First call stall: state on APIKey.stalled, window 7d.
Trigger developer-question Developer question: event on Question.asked, window 2d.
Trigger snippet-failure Snippet failure: event on Monitor.matched, window 1d.
Trigger release-shipped Version shipped: event on Version.deployed, window 2d.
Trigger deprecation-scheduled Deprecation scheduled: event on Version.deprecated, window 30d.
Trigger model-release Model release: event on Monitor.checked, window 7d.
Trigger hackathon-due Hackathon due: at on Gathering.scheduled, window 14d.
Trigger event-key-activated Event key activated: threshold on APIKey.activated, window 14d.
Sequence deprecation-notice Deprecation notice: 3 steps; it ends on The key makes no call to the old version for 14 days; The old version is removed.
Sequence hosted-hackathon-builder Hosted hackathon builder: 4 steps; it ends on Reply; Booked Meeting; First paid Transaction; Opt-out.
Benchmark devrel-warning-vs-tip Share of agent runs that adopted the documented approach after a docs tip, against a warning naming the failing approach.: 20–100 % (A platform vendor’s agent-experience experiments., 2026-10-06).
Benchmark devrel-json-input-mode Task success of a small model with a JSON input mode, against plain arguments.: 40–100 % (A platform vendor’s agent-experience experiments., 2026-10-06).
Benchmark devrel-named-interface-instruction Setup checks passed when the task told the agent which Interface to use.: 37.5–93.75 % (A platform vendor’s agent-experience experiments., 2026-10-06).

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