.toon file format. For tutorials, see the TOON Overview.
File Structure
A.toon file is a TOON (Token-Oriented Object Notation) document with the following top-level keys:
Top-Level Keys
name
Required. String. The workflow identifier used in persistence, logs, CLI, and API.
input
Required. Either an inline schema block or a reference to an imported Schema.Class.
Inline:
agents
Optional. Named agent declarations. Required only when steps use prompt: and agents are not imported.
| Field | Type | Required | Description |
|---|---|---|---|
type | string | yes | Agent runtime: claude-code, codex, gemini, pi, kimi, forge, anthropic, openai, api |
model | string | conditional | Model identifier. Required for anthropic, openai, and api types. Optional for CLI agents (claude-code, codex, gemini, pi, kimi, forge) which have built-in defaults. |
instructions | string | no | System prompt / persona |
tools | ”string[]“ | no | Tool names the agent can use |
subscription | boolean | no | Use subscription billing (Claude Code) |
timeoutMs | number | no | Hard timeout in milliseconds |
idleTimeoutMs | number | no | Inactivity timeout in milliseconds |
fullAuto for Codex, permissionMode for Claude Code, sandbox for Gemini).
type: api
The api type is a generic provider-based agent that requires explicit provider and model fields. Currently supported providers are anthropic and openai.
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | yes | Provider name: anthropic or openai |
model | string | yes | Model identifier for the provider |
schemas
Optional. Named output schemas that can be referenced by multiple steps.
components
Optional. Named, parameterized step groups.
steps
Required. Array of nodes that define the workflow graph.
imports
Optional. Object with sub-keys: schemas, services, components, workflows, plugins, agents.
Field Types
| TOON Syntax | Semantics | Effect Equivalent |
|---|---|---|
string | UTF-8 string | Schema.String |
number | IEEE 754 double | Schema.Number |
boolean | true or false | Schema.Boolean |
"a" | String literal | Schema.Literal("a") |
"a" | "b" | String literal union | Schema.Literal("a", "b") |
"string[]" | Array of strings | Schema.Array(Schema.String) |
"number[]" | Array of numbers | Schema.Array(Schema.Number) |
string? | Optional string | Schema.optional(Schema.String) |
T? | Optional T | Schema.optional(T) |
| nested block | Struct | Schema.Struct({...}) |
- field: type | Array of objects | Schema.Array(Schema.Struct({...})) |
Node Kinds
Every entry insteps: is a node. Nodes are either steps (default) or control-flow nodes (identified by kind:).
Step Node (default)
prompt, run, or handler.
| Property | Type | Required | Description |
|---|---|---|---|
id | string | yes | Unique step identifier |
agent | string | for prompt | References a declared agent |
prompt | string | no | Prompt text (mutually exclusive with run/handler) |
run | string | no | Inline TypeScript (mutually exclusive with prompt/handler) |
handler | string | no | TypeScript function reference (mutually exclusive with prompt/run) |
output | schema/string | yes | Output schema — inline block or named reference |
needs | string/array | no | Explicit dependencies on other step ids |
maxAttempts | number | no | Retry count (flat alternative to nested retry: block) |
retry | object | no | Retry policy with maxAttempts, backoff, initialDelay |
timeout | duration | no | Step timeout (e.g. 5m, 30s) |
cache | object | no | Cache policy with by and version |
skipIf | string | no | Condition expression to skip the step |
handler (advanced)
The handler field references an external TypeScript module that exports a function. The format is ./path/to/module.ts or ./path/to/module.ts#namedExport. If no export name is specified, the default export is used. The function receives the step context (with input, upstream step outputs, and services) and returns the step output.
kind: sequence
kind: parallel
kind: loop
kind: approval
kind: branch
kind: worktree
kind: workflow
Invokes an imported workflow as a sub-workflow. The use field references a workflow alias declared in imports.workflows. Input fields are mapped via the input block and support interpolation.
kind: component
Interpolation Grammar
Interpolation occurs insideprompt:, request:, skipIf:, until:, condition:, and component with: values.
Syntax
Expression Forms
| Form | Example | Resolves To |
|---|---|---|
input.field | {input.topic} | Workflow input field |
stepId.field | {analyze.summary} | Upstream step output field |
stepId.nested.field | {config.deploy.env} | Nested output field |
params.field | {params.content} | Component parameter |
loop.iteration | {loop.iteration} | Current loop iteration (1-based) |
id | {id} | Caller id (inside components) |
| Ternary | {input.score > 7 ? 'good' : 'bad'} | Conditional value |
| Method call | {input.tags.join(', ')} | Result of method |
| String concat | {'Hello ' + input.name} | Concatenated string |
{} are evaluated as JavaScript. All standard operators, ternaries, and method calls are supported.
Duration Syntax
Timeouts and delays use duration strings:| Format | Example |
|---|---|
| Milliseconds | 250ms |
| Seconds | 30s |
| Minutes | 5m |
| Hours | 1h |
Import Blocks
Imports use TOON’s tabular array format for compact declarations. Each import category is a tabular array with{from,use} or {from,as} field headers.
Schema Import
Service Import
Component Import
Workflow Import
Plugin Import
Plugins have per-entry config objects, so they use expanded list items:Execution Semantics
- Steps in
steps:execute sequentially by default (top to bottom) kind: parallelchildren execute concurrentlykind: sequenceis explicit sequential grouping (useful inside parallel)kind: looprepeats children untiluntil:is true ormaxIterationsis reachedkind: approvalsuspends execution durablykind: branchtakes one path based oncondition:kind: workflowinvokes an imported workflow as a sub-workflow- Dependencies declared in
needs:are resolved before the step runs - Implicit dependencies from
{stepId.field}interpolation are also resolved
Compilation Target
A.toon file compiles to the same WorkflowNode graph as the Effect builder API. At runtime, there is no behavioral difference between a TOON workflow and an Effect builder workflow.