Skip to content

Weekly readout

Each week, each running Play’s numbers beside its benchmark, then keep, fix or switch, naming the row that fired.

Kind
Workflow
Price
Free
Your time
7 minutes
Approval
Runs on its own
Play.review
You, to your agent

Read this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing.

curl -X POST "https://api.sb/leaseline.app/plays/review?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"goal":"Read this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing.","budget":{"amount":0,"currency":"USD"}}'
npx startup-builder do Play.review --try --data '{"goal":"Read this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing.","budget":{"amount":0,"currency":"USD"}}'
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Play.review({ goal: 'Read this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing.', budget: { amount: 0, currency: 'USD' } })"
  }
}
import { $ } from 'startup-builder'

const result = await $.try.Play.review({ goal: 'Read this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing.', budget: { amount: 0, currency: 'USD' } })
Response
{
  "mode": "try",
  "stored": false,
  "estimate": "Free",
  "sample": {
    "play": "Cold email",
    "metric": "reply rate",
    "week": "1.6% of 250 (0.7% to 3.5%)",
    "benchmark": "3% to 6%",
    "verdict": "fix",
    "fired": "replies < 2% at 200 sends: angle, not volume"
  }
}
Try mode reads, stores nothing and spends nothingAPI referenceIts Nouns

What you get

  • 1 week · Each week, each running Play’s numbers beside its benchmark, then keep, fix or switch, naming the row that fired. · Play
  • plays[].numbers · The week’s numbers for the Play’s Metric and its funnel rows, each beside its benchmark and its source label.
  • plays[].interval · The 90% interval on every rate: 2 replies from 60 sends reads “3.3%, 1.1% to 9.6%”, so one reply never decides a switch.
  • plays[].verdict · keep (every good row for this week holds), fix (a breaks row fired and its fix is a change inside the Play) or switch (two breaks rows fired two weeks running).
  • plays[].fired · The typed row that fired: its metric, the threshold, this week’s reading, the cause and the call that fixes it.

How long: Seconds.

Trigger

It runs weekly at 08:00 on the first weekday, after the week’s Search readout lands.

TypeScript
every('mon 08:00', ($) => $.Play.review({ plays: 'running' }))

Steps

Your agent does these steps, one row per step; each step’s check is part of its row and its price.

StepVerbReturnsPriceApproval
1. Read each running Play’s numbers for the weekMetric.queryThe Metric and the funnel rows for each Play, with nFreeRuns on its own
2. Read the benchmarks and the typed rowsCollection.queryEach Play’s good row for this week and its breaks rows, with their thresholds and source labelsFreeRuns on its own
3. Hold each reading against its rowsMetric.watchWhich breaks rows fired, which good rows held, and the 90% interval on every rateFreeRuns on its own
4. Write the verdict by the declared ruleCollection.queryKeep, fix or switch per Play, with the row that fired and the call that fixes itFreeRuns on its own

Calls: Metric.query, then Collection.query, then Metric.watch, then Collection.query.

Free, each time it runs, capped at 0¢.

Example: give it a goal

Read this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing.

The plan it shows runs 4 steps, priced before it spends anything; Run it above shows the result it returns.

When something fails

Each failure, and what happens next
WhenThen
A Play’s Metric has no reading this weekThe Play reads no-data with the Event it waits on, never a zero; a missing feed is a fix, not a switch.
n is under minNThe verdict can be keep or fix, never switch: at 60 sends a 3.3% reply rate could be anywhere from 1.1% to 9.6%.
Two breaks rows fire for one PlayThe verdict names both, the first by the order its page lists them, and the switch waits one more week unless both fired last week too.

Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-play-review-1-<step>-<item>.

Change it

AskCompiles to
Wait two weeks before any switch.Play.review
Apply the fix the readout names for Cold email.Play.apply
Rebuild next week’s mix from this readout.PlayMix.compile
TypeScript
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'weekly-review',
  verb: 'Play.review',
  input: { plays: "'running' | string[]", minN: 'integer' },
  trigger: { schedule: 'mon 08:00' },
  maxCost: 0,
  execute: async (ctx, { plays = 'running', minN = 100 }) => {
    const numbers = await ctx.step('numbers', () => $.Metric.query({ plays, period: 'week', withN: true }))
    const rows = await ctx.step('rows', () => $.Collection.query({ from: 'play', where: plays === 'running' ? "state = 'running'" : `$id in ${plays}`, fields: ['breaks', 'good'] }))
    const held = await ctx.step('watch', () => $.Metric.watch({ readings: numbers, against: rows, interval: 0.9, minN }))
    return verdicts(held)        // keep: every good row holds · fix: a breaks row fired · switch: two rows, two weeks running
  },
})

Extend it with extends: 'Play.review' and base(), or compose your own from these steps.

Works with

Plays that order it: Build in public, Commission partners, Creator partnership, Creator retainers, Made-with line, Sponsorships.

It serves Measure, and runs in Hands-on, Paid, Borrowed, Keep and grow. It deepens Weekly review.

For agents

For agents: the guide, its approvals, retries and lookups
FactValue
GuidePlay.review
Guide approvalnone
GoalRead this week’s numbers for every running Play and tell me what to keep, fix or switch. Spend nothing. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval.
Triggerevery('mon 08:00', ($) => $.Play.review({ plays: 'running' }))
RetryThree times with backoff, then the next route; the same idempotency key never charges, sends or posts twice
Idempotency keyleaseline-play-review-1
LookupsA find: input asks unless exactly one record fits
Step
1. Read each running Play’s numbers for the week
2. Read the benchmarks and the typed rows
3. Hold each reading against its rows
4. Write the verdict by the declared rule

The amounts live once, on the hub (approvals).

Who does each step, and how it is checked
StepFunctionDoerCheckerAssuranceInputs
1. Read each running Play’s numbers for the weekcodeCodeCode checks each result against its declared typemeasured$0.plays, $0.week
2. Read the benchmarks and the typed rowscodeCodeCode checks each result against its declared typemeasured$0.plays
3. Hold each reading against its rowscodeCodeCode checks each result against its declared typemeasured$1, $2, $0.minN
4. Write the verdict by the declared rulecodeCodeCode checks each result against its declared typemeasured$3

The doer is never the checker, and the weakest assurance on the path is the whole call’s.

Under the hood

Under the hood: the Systems, Nouns and Events it touches
KindWhat it touches
SystemsAnalytics and experiments
NounsMetric, Collection
EventsMetric.queried, Collection.queried, Metric.watched

Reference

Inputs, outputs, its Event and its errors
NameTypeDefaultMeaning
plays'running' | PlayId[]'running'The Plays to read: every Play running this week, or the ones you name.
weekstringthe last full ISO weekThe week read.
minNinteger100Below this many sends, visits or clicks, the verdict can fix but never switch: the interval is too wide to call.
maxCostnumber0.00The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link.

Emits Play.reviewed. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).

Contents