Harden it
Add a review step that attacks every translation before the buyer sees it, and watch the redo it sends back.
A review step attacks the work before the buyer sees it: one AI reviewer per lens flags what's wrong, and the work goes back for a redo. It's how a draft is hardened before anyone signs it. This is Grow 1. Each page adds one key to the four-line Translation from your first paid job, shows the whole file, runs check, runs one job on the four buyer surfaces, and ends on what changed across all seven.
Write each step as its own file under grow/, so diff can compare them. check counts 8 lines, the ones inside Service({ … }):
import { Service } from 'services.dev'
// Grow 1, harden it: two AI reviewers attack every translation at once, one for meaning and one for
// terms, and flag it back for a redo until it holds, at most twice, inside the AI budget.
export default Service({
name: 'Translation',
input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA' },
output: { document: 'file' },
deliver: {
translate: 'ai',
harden: { review: 'adversarial', lenses: ['meaning', 'terms'], rounds: 2 },
},
price: 49,
})translate is the AI doing the work. harden is a review step of it.
| Key | What it does | Default |
|---|---|---|
review | 'adversarial' attacks the step it reviews; 'affirmative' extends it, "yes, and", for creative work | required |
of | The step it reviews | the step before |
lenses | One AI reviewer per lens, all at once | one reviewer |
rounds | How many times it may flag the work back and review again, inside the AI budget | 3 |
exhausted | Where work still flagged after the last round goes: a step, such as a person's second look, or an end | the job stops at $0 |
by | A role whose member reviews instead of AI, for work only a credential may pass | AI |
check reads services/, so put the step there:
npx services.dev checkservices/translation.ts · 8 lines · $49 per job, within 48 hours, charged on delivery.
who AI delivers every job.
steps translate · ai → harden · ai · adversarial · 2 lenses
agent order_translation · 24 of 30 words · bought job_7Hq2 · $49.00 · no person
ledger +$49.00 · AI $1.26 (example) · you $47.74
margin at least $39.20 a job (80%) · a job that stops costs you at most $9.80
apps customer portal · owner console
mcp 13 buyer tools · 4,486 of 8,000 tokens · 9 more with ?toolset=sandbox
✓ ready to sell · 1 Service · AI delivers it alone · it keeps at least 80% of every job
next npx services.dev dev
AI and money are simulated until you wire them. $0.42 a call is an example.The steps line reads the graph back. AI still delivers every job alone, and the floor holds at 80%: every round spends from one AI budget, capped at a fifth of the price.
The magic value metadata.sandbox.review = flag_once makes the first round flag the work, so the redo runs without waiting for a real miss:
npx services.dev translation document=https://example.com/lease.pdf to=fr-CA --max 49 --key grow --metadata sandbox.review=flag_oncejob_7Hq2 · working · $49.00 held
job_7Hq2 · delivered · lease.fr-CA.pdf · $49.00 charged
record translate · ai | harden · ai · adversarial · 2 lenses · flagged | translate · ai · redo | harden · ai · adversarial · 2 lenses · pass
ledger +$49.00 · AI $2.52 · you $46.48
next npx services.dev accept job_7Hq2curl -X POST http://localhost:8787/jobs -H 'content-type: application/json' -d '{"service":"translation","document":{"url":"https://example.com/lease.pdf","name":"lease.pdf"},"to":"fr-CA","key":"grow","max_usd":49,"metadata":{"sandbox":{"review":"flag_once"}}}' next get_job {"id":"job_7Hq2"}
$ curl http://localhost:8787/jobs/job_7Hq2?wait=50
← 200 · job_7Hq2 · delivered · lease.fr-CA.pdf · $49.00 charged→ tools/call order_translation {"document":{"url":"https://example.com/lease.pdf","name":"lease.pdf"},"to":"fr-CA","key":"grow","max_usd":49,"metadata":{"sandbox":{"review":"flag_once"}}}← job_7Hq2 · working · $49.00 held
next get_job {"id":"job_7Hq2"}
→ resources/read job://job_7Hq2?wait=50
← job_7Hq2 · delivered · lease.fr-CA.pdf · $49.00 chargedawait lingua.translation.order({"document":{"url":"https://example.com/lease.pdf","name":"lease.pdf"},"to":"fr-CA","key":"grow","max_usd":49,"metadata":{"sandbox":{"review":"flag_once"}}})← job_7Hq2 · working · $49.00 held
next get_job {"id":"job_7Hq2"}
await lingua.jobs.wait("job_7Hq2")
← job_7Hq2 · delivered · lease.fr-CA.pdf · $49.00 chargedThe record keeps both rounds, the flag and the redo:
→ POST /translation {"document":"lease.pdf","to":"fr-CA","key":"grow","max_usd":49,"metadata":{"sandbox":{"review":"flag_once"}}}← job_7Hq2 · delivered · lease.fr-CA.pdf · $49.00 charged
record translate · ai | harden · ai · adversarial · 2 lenses · flagged | translate · ai · redo | harden · ai · adversarial · 2 lenses · pass
ledger +$49.00 · AI $2.52 · you $46.48The redo cost a second pass: $2.52 of AI, where check priced a clean run at $1.26. Both sit under the $9.80 cap, and you kept $46.48.
npx services.dev diff services/translation.ts grow/review.tsservices/translation.ts (4 lines) → grow/review.ts (8 lines)
Translation · changed deliver
API ~ operation service.quote.translation GET /translation.json answers.deliver
~ operation brand.manifest GET /manifest.json answers.services
CLI no change
MCP no change
SDK ~ object job_ (translation) Job<"translation"> + stage: "translate" | "harden"
Site ~ operation service.quote.translation /translation.json deliver
Docs no change
App no changeOnly the steps moved: the quote's deliver, the manifest and the SDK's stage union. No call is new, so the CLI, MCP, Docs and App don't change. The step graph adds branches, loops and joins.
In a brand, the legal example reviews a draft through four lenses, three rounds, and its exhausted sends what's still flagged to a credentialed second look.
Ask the buyer: a question the buyer answers before the AI starts.