Your code as a step
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?
count: { by: async ({ document }) => ({ pages: Math.ceil((await document.text()).length / 1800) }), cite: 'a standard page: 1,800 characters' },
translate: 'ai',npx services.dev check steps count · code · cites a standard page: 1,800 characters → translate · ai → review · ai · adversarialOn a work step
| Key | Written | Left out | Does |
|---|---|---|---|
by | Doer | required | Who 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
| Key | Written | Left out | Does |
|---|---|---|---|
input | Data | required | The order's input, each file with a text() reader. |
ai | (instructions, ...files) => Promise<string> | required | Calls the model with the Service's brief. Its cost is the ledger's AI cell. |
outcome | (won) => void | required | Reports what a job won, for a share: job.outcome({ recovery: 3000, evidence }). |
output | Partial | required | What committed steps returned. |
policy | PolicyValues | required | The order's policy, every default filled. |
signals | { <name>: boolean } | required | The signals raised so far. |
feedback | string[] | required | What 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:
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,
})npx services.dev devan 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.58The 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:
curl http://localhost:8787/owner/jobs/job_7Hq2 # the count step's line on the record{
"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.
| Written | What TypeScript says |
|---|---|
deliver: async input => ({ document: input.document }), price: 49 | Property '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.
record: { by: async (_, job) => ({ paid: job.output.amount }), when: job => decided(job) === 'pay it' },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 · codeThe tax example runs every one of its files, captured.