Workflow DSL reference
The dialect is Starlark with assignments, if, for, comprehensions, def, lambda, load(), at the top level or inside a def. Every one of them runs at compile time: the compiled plan is a static graph, so a loop in the source unrolls into tasks rather than becoming a cycle.
prompt_file() and load() are the only file access, both confined below the pack directory, and a loaded module cannot re-export what it loaded. The surface has no processes, network access, clock, or randomness.
For what the engine does with the compiled graph, see Work graphs; for the normative rules, see the implementation contract.
Every lane
Available in every workflow type, playbooks included.
agent()
An agent turn driven by a prompt.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
prompt | str | The turn's prompt. |
harness | str | Agent harness, overriding [agent]. |
model | str | Model, overriding [agent]. |
effort | str | Reasoning effort, overriding [agent]. |
session | session | str | Join a durable conversation. A task in a session cannot be isolated. |
depends_on | list[task] | Dependencies. Readiness decides execution order; declaration order does not. |
needs | "any" | "all" | How many dependencies must be admitted before the task is ready. |
join | "all" | "passed" | "settled" | Which dependencies must have passed: all every one, passed at least one and only those are forwarded, settled none — it dispatches once every dependency is terminal, whatever it settled as, unless the run has already halted, and forwards each one as {status, note, output, files}. |
required | bool | False makes the task advisory: it blocks dependents but cannot invalidate the run. |
isolated | bool | Run in a disposable worktree. File changes are discarded; only JSON output continues. |
emits | list[str] | Result fields the task promises in its JSON output. |
emits_files | list[str] | Workspace files the task produces. A dependent is staged with the declared files of every dependency that passed. |
over | producer.field | Map the task over a dependency's emitted list, one instance per item. |
max_fanout | int | Instance cap for over, within the engine's ceiling of 256. |
stage | "iteration" | "epilogue" | epilogue runs once after the loop concludes, and only if the run kept a candidate. |
skill()
An agent turn whose prompt is a skill's instructions plus its arguments.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
skill | str | Skill directory below the pack; its instructions become the prompt. |
args | dict | Arguments appended to the instructions. |
harness | str | Agent harness, overriding [agent]. |
model | str | Model, overriding [agent]. |
effort | str | Reasoning effort, overriding [agent]. |
session | session | str | Join a durable conversation. A task in a session cannot be isolated. |
depends_on | list[task] | Dependencies. Readiness decides execution order; declaration order does not. |
needs | "any" | "all" | How many dependencies must be admitted before the task is ready. |
join | "all" | "passed" | "settled" | Which dependencies must have passed: all every one, passed at least one and only those are forwarded, settled none — it dispatches once every dependency is terminal, whatever it settled as, unless the run has already halted, and forwards each one as {status, note, output, files}. |
required | bool | False makes the task advisory: it blocks dependents but cannot invalidate the run. |
isolated | bool | Run in a disposable worktree. File changes are discarded; only JSON output continues. |
emits | list[str] | Result fields the task promises in its JSON output. |
emits_files | list[str] | Workspace files the task produces. A dependent is staged with the declared files of every dependency that passed. |
over | producer.field | Map the task over a dependency's emitted list, one instance per item. |
max_fanout | int | Instance cap for over, within the engine's ceiling of 256. |
stage | "iteration" | "epilogue" | epilogue runs once after the loop concludes, and only if the run kept a candidate. |
command()
A deterministic shell task in the candidate workspace.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
run | str | The command, run through sh -c. |
depends_on | list[task] | Dependencies. Readiness decides execution order; declaration order does not. |
needs | "any" | "all" | How many dependencies must be admitted before the task is ready. |
join | "all" | "passed" | "settled" | Which dependencies must have passed: all every one, passed at least one and only those are forwarded, settled none — it dispatches once every dependency is terminal, whatever it settled as, unless the run has already halted, and forwards each one as {status, note, output, files}. |
required | bool | False makes the task advisory: it blocks dependents but cannot invalidate the run. |
isolated | bool | Run in a disposable worktree. File changes are discarded; only JSON output continues. |
emits | list[str] | Result fields the task promises in its JSON output. |
emits_files | list[str] | Workspace files the task produces. A dependent is staged with the declared files of every dependency that passed. |
over | producer.field | Map the task over a dependency's emitted list, one instance per item. |
max_fanout | int | Instance cap for over, within the engine's ceiling of 256. |
stage | "iteration" | "epilogue" | epilogue runs once after the loop concludes, and only if the run kept a candidate. |
evaluate()
A measurement command. Its last non-empty stdout line is a JSON object; pass = false vetoes the result and numeric score feeds grade() and top_k().
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
run | str | The command, run through sh -c. |
threshold | number | Grade the emitted score against this bound. An explicit pass wins. |
direction | "lower" | "higher" | Which side of the threshold passes. |
depends_on | list[task] | Dependencies. Readiness decides execution order; declaration order does not. |
needs | "any" | "all" | How many dependencies must be admitted before the task is ready. |
join | "all" | "passed" | "settled" | Which dependencies must have passed: all every one, passed at least one and only those are forwarded, settled none — it dispatches once every dependency is terminal, whatever it settled as, unless the run has already halted, and forwards each one as {status, note, output, files}. |
required | bool | False makes the task advisory: it blocks dependents but cannot invalidate the run. |
isolated | bool | Run in a disposable worktree. File changes are discarded; only JSON output continues. |
emits | list[str] | Result fields the task promises in its JSON output. |
emits_files | list[str] | Workspace files the task produces. A dependent is staged with the declared files of every dependency that passed. |
over | producer.field | Map the task over a dependency's emitted list, one instance per item. |
max_fanout | int | Instance cap for over, within the engine's ceiling of 256. |
stage | "iteration" | "epilogue" | epilogue runs once after the loop concludes, and only if the run kept a candidate. |
report()
Publish a rendered template to a controller-configured destination. The workflow selects a destination key, never an endpoint or a credential.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
destination | str | The configured sink to publish to. |
template | str | The template rendered into the message. |
result | task | The task whose result the template renders. |
required | bool | False makes the report advisory. |
session()
Declare a durable agent conversation. Tasks that share one run serially under one agent config, across dependency order and loop iterations.
| Argument | Type | Purpose |
|---|---|---|
name | str | Session identity, referenced by session =. |
harness | str | Default harness for tasks in the session. |
model | str | Default model for tasks in the session. |
effort | str | Default effort for tasks in the session. |
param()
Read a launch parameter. The params block must be the source's first statement, and a source that declares one compiles per run.
Takes one positional argument, name.
prompt_file()
Embed a UTF-8 file below the pack directory. Absolute paths, .., symlinks, non-files, and oversized inputs are refused.
Takes one positional argument, path.
workflow()
The source's final expression: the lane, the tasks that ship, and the result. A task constructed but not listed is a compile error.
Takes one positional argument, tasks.
| Argument | Type | Purpose |
|---|---|---|
type | "autoresearch" | "custom" | "playbook" | The lane, which decides which constructors exist. |
tasks | list[task] | Every task that ships. |
result | task | The task whose output is the workflow's result. |
Scored lanes only
Available to type = "autoresearch" and type = "custom". A playbook does not have these in scope at all, so naming one is an unknown-name error and a did-you-mean never offers one.
propose()
The loop's candidate-producing agent turn.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
session | session | str | The conversation the turn belongs to. |
depends_on | list[task] | Dependencies. |
apply()
Make the candidate live through the configured world. A failure means unscoreable, not worse.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
depends_on | list[task] | Dependencies. |
measure()
Run the manifest's frozen judge as one opaque measurement task.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
depends_on | list[task] | Dependencies. |
grade()
Fold evaluation evidence into a measurement. Evidence includes tasks that failed or never ran, which is what the score source alone cannot see.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
score | task | The task whose score the decision uses. |
tiebreak | task | Secondary score that breaks primary-score ties. |
evidence | list[task] | Tasks folded into the measurement. |
join | "all" | "passed" | Which evidence must have passed. |
decide()
Apply the engine's keep-or-discard rule to a measurement. An autoresearch workflow must end here.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
measurement | task | The measurement being ruled on. |
depends_on | list[task] | Dependencies, defaulting to the measurement. |
top_k()
Engine-owned reducer: the best k dependency outputs by numeric score.
| Argument | Type | Purpose |
|---|---|---|
name | str | Task identity, unique within the workflow. |
k | int | How many dependencies survive. |
direction | "lower" | "higher" | Which score wins. |
depends_on | list[task] | The candidates being reduced. |
required | bool | False makes the reducer advisory. |
default_autoresearch()
Expand the built-in propose/apply/measure/decide loop into visible nodes, plus the tasks passed to it.
Takes one positional argument, extra_tasks.
Reserved fields
Names the engine reads and writes for itself. They are not constructor arguments; they appear in a task's own JSON output and in the inputs it receives.
A task's own JSON output
Read out of the object the task returns.
| Field | Type | Meaning |
|---|---|---|
status | "pass" | "fail" | "skipped" | Settles the task, overriding an exit code or pass. Any other value is ignored. |
Inputs the engine writes
Present alongside the dependency entries, never wrapped in one.
| Field | Type | Meaning |
|---|---|---|
item | str | This mapped instance's key, one per item of the list over names. |
kept | object | The kept candidate, in an epilogue task only. |
outcome | object | How the main graph ended and what each of its tasks settled as, as {"exit": str, "tasks": {name: {"status", "note"}}}, in an epilogue task only. |