Your code as a step

The running jobjob_7Hq2 · working · $49.00 held

A function can do the whole job or one step of it. It gets the input and the job, returns output, and can name the rule its calculation follows on the record.

A code step answers one question: which part of the work is a calculation you already know how to do?

services/paged-translation.ts
    count: { by: async ({ document }) => ({ pages: Math.ceil((await document.text()).length / 1800) }), cite: 'a standard page: 1,800 characters' },
    translate: 'ai',
Run
npx services.dev check
magic values: none
  steps   count · code · cites a standard page: 1,800 characters → translate · ai → review · ai · adversarial

On a work step

KeyWrittenLeft outDoes
byDoerrequiredWho proposes the output: 'ai', 'person' or a role word, a URL, your function, or another of your Services.
cite'source' | (string & {})none'source': every output field cites the input it rests on, and the review fails a field that doesn't. A string: the authority a calculation follows, recorded on the line.

In your code, on the job

KeyWrittenLeft outDoes
inputDatarequiredThe order's input, each file with a text() reader.
ai(instructions, ...files) => Promise<string>requiredCalls the model with the Service's brief. Its cost is the ledger's AI cell.
outcome(won) => voidrequiredReports what a job won, for a share: job.outcome({ recovery: 3000, evidence }).
outputPartialrequiredWhat committed steps returned.
policyPolicyValuesrequiredThe order's policy, every default filled.
signals{ <name>: boolean }requiredThe signals raised so far.
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.

Make deliver a function and it does all the work, here with your own model. It returns the whole output, and the record prints code where it printed ai:

services/translation.ts
import { Service } from 'services.dev'
import { translate } from '../model.ts'

export default Service({
  name: 'Translation',
  input: { document: 'file', to: 'language: a BCP 47 tag, such as fr-CA' },
  output: { document: 'file' },
  deliver: async ({ document, to }) => ({ document: await translate(document, to) }),
  price: 49,
})
Run
npx services.dev dev
captured
an agent ordered Translation at $49
job_7Hq2 · delivered · document.fr-CA.pdf · $49.00 charged
  record  draft · code | review · ai · pass
  ledger  +$49.00 · AI $0.42 · you $48.58

The AI left in the ledger is its review.

As a step, a function is called with (input, job) and returns part of the output. The steps after it read what it returned on job.output, beside the order's job.policy, the raised job.signals and the job.feedback a redo reads: the last table in Every form. Each file input arrives with a text() reader.

cite puts the rule a calculation follows on its line in the record, so anyone replaying the job can check the arithmetic against it:

Run
curl http://localhost:8787/owner/jobs/job_7Hq2   # the count step's line on the record
magic values: none
{
  "type": "step.committed",
  "step": "count",
  "by": "code",
  "fields": [
    "pages"
  ],
  "cite": "a standard page: 1,800 characters"
}

A code step proposes, like every doer, and the gate commits it. Refused, your code would propose the same again, so the job stops. A step that throws stops the job, and the buyer pays $0.

Inside a function, job.ai(instructions, ...files) calls the same AI as 'ai', with the same brief.

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

Operations has every column of every row.

WrittenWhat TypeScript says
deliver: async input => ({ document: input.document }), price: 49Property 'recovery' is missing in type '{ document: InFile; }' but required in type '{ readonly document: FileRef; readonly recovery: number; }'.

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

tax · services/estimate.ts · 17 lines
    record: { by: async (_, job) => ({ paid: job.output.amount }), when: job => decided(job) === 'pay it' },
npx services.dev check · captured/tax-check.txt
services/estimate.ts · 17 lines · $79 per job, within 48 hours, charged on delivery.
  steps   compute · code · cites prior-year safe harbor, cumulative by quarter → approve · owner · decide → review · ai · adversarial → pay · Treasury and states · one for each jurisdiction with an installment → record · code

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