Guards
A guard checks a step's output before it commits, such as a floor, a cap or a required field. The AI redoes a refused proposal, and a person's step stays theirs until it holds.
A guard answers one question: is this output acceptable, whoever proposed it?
translate: { by: 'ai', guard: { match: (v, job) => v >= job.policy.match || `below the match the client set (${v} < ${job.policy.match})` } },On a step
| Key | Written | Left out | Does |
|---|---|---|---|
guard | Guard | none | Checks on the output before it commits; a failure is guard_refused, for AI and people alike. |
checklist | string[] | none | What a person checks, item by item. |
A guard is a function per output field. It reads the proposed value and the job, and returns true or the reason it can't stand. The reason is what everyone sees: the record, the person, the agent.
Refused, the AI redoes it inside its budget, and the record keeps both:
→ POST /checked-translation {"document":"manual.pdf","to":"de","policy":{"match":0.9},"max_usd":79,"key":"guarded","metadata":{"sandbox":{"propose":{"match":[0.7,0.95]}}}}← job_7Hq2 · waiting · on person · $79.00 held
record translate · ai · refused · guard_refused · match: below the match the client set (0.7 < 0.9) | translate · ai · redoA person gets the same refusal as a 422, inline, and the step stays theirs:
→ POST /proofreaders/jobs/job_7Hq2/approve {"output":{"match":0.8}} "code": "guard_refused",
"reason": "match: below the match the client set (0.8 < 0.9)",
"do": "approve",
"tool": null,
"http": "POST http://localhost:8787/jobs/job_7Hq2/approve"next is approve with no MCP tool: the step is still the proofreader's, in their app, and no key can take it.
→ POST /proofreaders/jobs/job_7Hq2/approve {"output":{"match":0.96}}← job_7Hq2 · delivered · manual.de.pdf · $79.00 chargedA guard reads job.policy, so the bound can be the client's. Here match is a merits value only the client sets, and the guard holds the AI and the proofreader to it. See policy.
checklist lists what a person affirms, item by item. An attestation missing an item is refused, the same way.
A signal names a fact and can move the job. It never refuses an output. Blocking is a guard's job.
| Op | API | CLI | MCP | SDK | Site | Docs | App |
|---|---|---|---|---|---|---|---|
job.approve | POST /:portal/jobs/:id/approve, POST /jobs/:id/approve, POST /jobs/:id/sign, POST /owner/jobs/:id/approve | jobs approve <job> | never: a person acts | never: a person acts | 8 error pages | owner console, delivery portal |
Events: step.refused.
Operations has every column of every row.
| Code | Category | HTTP | Why |
|---|---|---|---|
guard_refused | guard | 422 | A guard refused the output, and says why. |
The lines that use it in the example brands, as their files write them, and what check read aloud for each file.
advise: { by: 'attorney', stamp: true, est: '45min', checklist: ['every flag is addressed', 'the memo answers the goals'] },services/contract-review.ts · 16 lines · $99 per job, within 48 hours, charged on acceptance.
steps consent · client · consent → flag · ai → attack · ai · adversarial → advise · attorney · client · stamped · 2-item checklist → send · aiThe legal example runs every one of its files, captured.
prepare: { by: 'preparer', est: '1h', checklist: ['every changed line traces to a source'] },services/amended-return.ts · 22 lines · $900 per job, within 30 days, charged when file or aar is accepted.
steps compute · code · cites depreciation and carryforward schedules → draft · ai · cites the workpapers and the records the organizer took → check · ai · adversarial · 2 lenses → prepare · preparer · * · 1-item checklist → sign · signer · * · stamped in the paid-preparer block → authorize · owner · sign → file · IRS and states, unless a partnership → aar · IRS · Form 8082, for a partnership · emits k1.adjustedThe tax example runs every one of its files, captured.
guard: { held: (m, job) => m.attended(job.input.account) >= 10 || 'no one from the account stayed 10 minutes' } },
guard: { closed_value: (v, job) => v >= job.input.value * job.policy.floor || 'below the floor you set' } },services/deal.ts · 42 lines · nothing on effort; 5% of closed_value at won, proven by the account's payment, held 60 days by bank, 120 by card.
steps source · ai → qualify · ai → book · ai · setter when warm → meet · ai · closer from humans_from, committee or person · skipped for B2A · guard held: the account attends 10 minutes → propose · ai · the closer's span → negotiate · ai · the closer's span → close · ai · the closer's span · guard closed_value at least value × floor → nurture · nurturer · routedThe sales example runs every one of its files.