Workflows
A workflow is a list of steps. A step is a prompt and the model that answers it.
Steps
{
"id": "extract",
"prompt": "Pull the key facts from {{input.text}}",
"model": "anthropic/claude-haiku-4.5",
"retries": 2,
"needs": [],
"output": { "title": "string", "facts": "string[]" }
}| Field | Type | Description |
|---|---|---|
id | string | Required. Unique within the workflow. input is reserved. |
prompt | string | Required. Up to 100,000 characters. |
model | string | Required. One of the models. |
retries | number | How many more times to try after a temporary failure. Default 2, max 5. |
needs | string[] | Steps that must complete first. Default none. |
output | object | A JSON shape for the answer. Default plain text. |
A workflow has at least one step.
Templates
A prompt includes the run's input and earlier outputs through placeholders. Replace <field> with a field name, <step> with a step's id, and <n> with a position:
| Write | Becomes |
|---|---|
{{input.<field>}} | A field of the run's input |
{{input.<field>.<field>}} | A field inside an input object, at any depth |
{{<step>.output}} | A step's output |
{{<step>.output.<field>}} | A field of a step's JSON output |
{{<step>.output.<field>.<n>}} | An item of a list, counting from 0 |
Objects and lists are written in as JSON. A path that leads nowhere is written in as nothing.
A step can only read the steps listed in its own needs. If brief reads {{summary.output}}, summary must be in brief's needs, even when another step already needs it. A deploy that breaks this is rejected.
A step that needs another step without reading it still receives that step's output, added before the prompt in <step-id> tags.
Every top-level input field a prompt reads must be in the invoke, or the invoke is rejected with invalid_input. Fields inside an input object are not checked; a missing one is written in as nothing.
Parallel steps
Steps that do not need each other run at the same time. Here summary and keywords start together, and brief waits for both. See How it works.
{
"steps": [
{
"id": "summary",
"prompt": "Summarise {{input.text}}",
"model": "openai/gpt-5.4-mini"
},
{
"id": "keywords",
"prompt": "List the keywords in {{input.text}}",
"model": "openai/gpt-5.4-mini"
},
{
"id": "brief",
"prompt": "Write a brief. Summary: {{summary.output}} Keywords: {{keywords.output}}",
"model": "anthropic/claude-sonnet-5",
"needs": ["summary", "keywords"]
}
]
}Output shapes
Give a step an output shape to have it answer in JSON. Each key is a field; each value is its type.
| Value | Field |
|---|---|
"string", "number", "boolean" | That type |
"string[]", "number[]", "boolean[]" | A list of that type |
{ … } | A nested object, in the same shorthand |
| Any other string | A string, with the value as its description |
Every field is required. An object with a type key is read as JSON Schema and used as is. A shape serialises to at most 8,000 characters.
"output": {
"title": "string",
"facts": "string[]",
"tone": "one word for the tone of the text"
}Later steps read fields with {{extract.output.title}}.
Checks at deploy
A deploy is rejected with invalid_structure when a workflow:
- repeats a step id, or names
inputas a step id - lists a step in
needsthat does not exist, or the step itself - has a loop through
needs - uses a template that is malformed, names an unknown step, or reads a step missing from
needs - has an unclosed
{{