AI steps and briefs

The running jobjob_7Hq2 · working · $49.00 held

An AI step works from a brief you write in Markdown. Every call is recorded with its model, the hash of each input and the brief it read, so any job replays.

An AI step answers one question: what the AI was told, and what it read.

Leave deliver out, and services/translation.md briefs the one AI step:

services/translation.md
# Translation

The AI reads this brief on every job. Write it the way you'd brief someone new.

## How the work is done

- Translate the whole document into the language in `to`.

On the Service

KeyWrittenLeft outDoes
deliverDeliver'ai', briefed by services/<id>.mdWho does the work: 'ai', a person or a role word, a URL, your function, or named steps in order.

Filled when the folder loads, never written

KeyWrittenLeft outDoes
briefs{ <name>: Brief }noneThe AI's brief per step, read when the folder loads: services/<id>/<step>.md, else services/<id>.md.

In your code, on the job

KeyWrittenLeft outDoes
ai(instructions, ...files) => Promise<string>requiredCalls the model with the Service's brief. Its cost is the ledger's AI cell.
feedbackstring[]requiredWhat the work was told to fix, oldest first: a review's flagged findings, a send-back's note, an outside system's rejection codes. The AI reads it on every redo.

A step with its own job gets its own brief at services/<id>/<step>.md. Every other step reads services/<id>.md. Localization's reviewer, qa, has one, and its evidence bundle shows each call read the brief it should:

Run
curl http://localhost:8787/owner/jobs/job_7Hq2/export   # each artifact's text left out
magic values: metadata.sandbox.review = flag_once
decisions: 10, each pinned to simulated-1; briefs services/localization.md and services/localization/qa.md

Every AI call writes decision.made to the record: the model it was pinned to, a hash of each input, the brief and its version, and what the call cost in cents. The first draft below reads the document and the language. The redo reads one thing more: the hash of the feedback, the review's finding.

Call
→ POST /translation {"document":"lease.pdf","to":"fr-CA","max_usd":49,"key":"decisions","metadata":{"sandbox":{"review":"flag_once"}}}
magic values: metadata.sandbox.review = flag_once
← job_7Hq2 · delivered · lease.fr-CA.pdf · $49.00 charged
  record  draft · ai | review · ai · flagged | draft · ai · redo | review · ai · pass
Run
curl http://localhost:8787/owner/jobs/job_7Hq2   # each decision.made for draft: the first, then the redo
magic values: metadata.sandbox.review = flag_once
{
  "type": "decision.made",
  "step": "draft",
  "by": "ai",
  "model": "simulated-1",
  "inputs": {
    "document": "sha256:cf7622e8980f0ddeafa28c7011a972fd931be541b939ce9819aeba2e94925ee9",
    "to": "sha256:5d6d4dd7ebd9caaa51cd2290ad24d68d2dda75714877d7cdc6a6e6de33097e9c"
  },
  "brief": {
    "file": "services/translation.md",
    "version": "sha256:858f32d14010584487adfdbf1f0ce69048895a5c745a9966a8a04d0940929c32"
  },
  "ai": 42
}
{
  "type": "decision.made",
  "step": "draft",
  "by": "ai",
  "model": "simulated-1",

A changed brief gets a new version, so a job that ran before the change still names the brief it read. Only the owner reads decisions. A buyer's job and a buyer's events never carry them.

A flagged review, a buyer's send-back note or an outside system's rejection codes become the job's feedback, and the AI reads it on every redo. The AI may spend at most 20% of the price on one job, redos included. Past that, the job stops and the buyer pays $0. Here dev({ review }) from services.dev/dev swaps in a review that flags every round, and the budget runs out:

Call
→ POST /translation {"document":"lease.pdf","to":"fr-CA","max_usd":49,"key":"flagged"}
magic values: none
← job_7Hq2 · canceled · ai_cap · $0
  record  11 reviews flagged, 10 redos
  ledger  AI $9.24 · you −$9.24

A URL makes an AI you already run the step, as deliver: 'https://…' or { by: 'https://…' }:

RequestPOST <url> with content-type: application/json, a services-job header carrying the job id, and the order's input as the body
Answera 2xx whose JSON is the step's output
A guard refuses itasked again, up to three proposals in all; then the job stops at $0, step_failed
A non-2xx, or a throwthe job stops at $0, step_failed, with the status on the record
With remote: falsethe URL isn't called: the simulated AI stands in, as in every capture here

In your code, job.ai(instructions, ...files) calls the same AI as 'ai', with the same brief, and its cost lands in the ledger's AI cell.

No call of its own: it changes what the job carries, on every surface that reads one.

Events: review.done.

Operations has every column of every row.

check gateWhy
price_below_costA delivered job could lose money: payout, nested Services and the AI cap add up to more than the price.

The lines that use it in the example brands, as their files write them, and what check read aloud for each file.

legal · services/formation.ts · 30 lines
    documents: 'ai',
npx services.dev check · captured/legal-walk.txt
services/formation.ts · 30 lines · $299 per job, within 48 hours, charged on form_entity's receipt.
  steps   consent · founders · consent → advise_entity · attorney · client · 1-item checklist → review · ai · adversarial → form_entity · the state → rename · founders · answer · routed → documents · ai → adopt · founders · sign → advise_83b · attorney · client · 1-item checklist

The legal example runs every one of its files, captured.

tax · services/amended-return.ts · 22 lines
    draft: { by: 'ai', cite: 'the workpapers and the records the organizer took' },
npx services.dev check · captured/tax-check.txt
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.adjusted

The tax example runs every one of its files, captured.