Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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(), schema_file(), and load() are the only file access, all 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.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
promptstrThe turn's prompt.
harnessstrAgent harness, overriding [agent].
modelstrModel, overriding [agent].
effortstrReasoning effort, overriding [agent].
sandboxstrAn [agent.sandbox.<name>]: its image, and only the secrets, relay files, broker reach, and egress it lists. Unset runs in the [agent] sandbox.
sessionsession | strJoin a durable conversation. A task in a session cannot be isolated.
repairintRepair turns, up to 3. When a passing turn's output misses a declared field or file, or breaks its type or schema, the same session is resumed with the masked validation notes and asked to fix it in place, then checked again. Repairs share the attempt's timeout and cost. Default 0; refused on command and evaluate.
depends_onlist[task | optional(task)]Dependencies. Readiness decides execution order; declaration order does not.
needsstrThe substrate capability the task needs, such as "decision". The default "any" runs everywhere. A required task whose capability is unavailable truncates the plan before dispatch; an advisory one is skipped with its dependents.
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}.
requiredboolFalse makes the task advisory: it blocks dependents but cannot invalidate the run.
isolatedboolRun in a disposable worktree. File changes are discarded; only JSON output continues.
emitslist[str] | dict[str, type]Result fields the task promises in its JSON output. The dict form also promises each field's type: "string", "integer", "number", "boolean", "list", "object", "link", "links", or a list of labels the value is one of. A passing output missing a field, or holding one of the wrong type, fails the task. Types are checked where the graph reads them: over needs a list, a top_k or grade score a number, and a route(source = ...) question labels it can answer. A link is one http(s) url and links a list of them, each naming a result the task produced outside the run (a pull request, a pushed branch, an issue), which the run and task views then link out to. A schema_file(...) promises a value its JSON Schema admits, and is checked against each consumer exactly: over needs "type": "array" with string items (by type, const or enum), a score a numeric type with no non-number in its enum, and a route a const, enum or boolean whose every value it can answer. A when label such a source can never give is refused.
emits_fileslist[str] | dict[str, schema | None]Workspace files the task produces. A task is staged with the declared files of every ancestor that passed, not only its direct dependencies, under inputs/<producer>/; a join = "settled" task also gets those of a direct dependency that failed. JSON outputs, unlike files, come from direct dependencies only. The dict form maps a path to schema_file(...) or None; a file with a schema must hold JSON the schema admits when the task passes, or the task fails.
overproducer.fieldMap the task over a dependency's emitted list, one instance per item.
max_fanoutintInstance cap for over, within the engine's ceiling of 256.
keyedlist[producer.field]Object fields of unmapped dependencies, keyed by item. Each instance receives only its own item's entry in place of the whole field. Needs over.
revisetask | list[task]The tasks this task sends back when it settles failing. They run again, in dependency order, with the verdict under revision, then this task does, until this task stops failing or max_rounds is spent. Every task on a path between them and this task must be listed. Playbooks only; not with over.
max_roundsintRound cap for revise, counting the first, from 2 to the engine's ceiling of 5.
timeoutstrHow long one attempt may run, as 90s, 10m, or 2h. At the limit the attempt's whole process group is killed and the task settles failed with a note naming the limit; it is not retried. The run's --max-time bounds every attempt as well, and a playbook refuses a timeout longer than it before dispatching anything.
stage"iteration" | "epilogue"epilogue runs once after the loop concludes, and only if the run kept a candidate.
historyintRead this many earlier runs of the launch series, from 1 to the engine's ceiling of 30, under history. A run launched outside a series gets an empty list. Playbooks only.
whenroute.questionRun only on a listed answer to one question of a route() this task depends on. Otherwise the task settles not_taken: no dispatch, no spend, no effect on validity, and every all-join dependent is not taken with it unless it lists the task as optional(...). Rejoin branches with join = "passed" or join = "settled". Playbook and custom workflows only.
answersstr | list[str]The answers when accepts: labels the question declares, or "uncertain". Defaults to "yes" for a noul and is required for a choice or a score. A choice whose options come from a field declares none, so only "uncertain".
otherwiseboolIn place of answers: every answer no other task lists and the question does not drop, "uncertain" included. Expanded at compile time. An unreachable otherwise is an error. On a choice whose options come from a field, it also stands for every option the choice resolves to, and is the only way to route them.

skill()

An agent turn whose prompt is a skill's instructions plus its arguments.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
skillstrSkill directory below the pack; its instructions become the prompt.
argsdictArguments appended to the instructions.
harnessstrAgent harness, overriding [agent].
modelstrModel, overriding [agent].
effortstrReasoning effort, overriding [agent].
sandboxstrAn [agent.sandbox.<name>]: its image, and only the secrets, relay files, broker reach, and egress it lists. Unset runs in the [agent] sandbox.
sessionsession | strJoin a durable conversation. A task in a session cannot be isolated.
repairintRepair turns, up to 3. When a passing turn's output misses a declared field or file, or breaks its type or schema, the same session is resumed with the masked validation notes and asked to fix it in place, then checked again. Repairs share the attempt's timeout and cost. Default 0; refused on command and evaluate.
depends_onlist[task | optional(task)]Dependencies. Readiness decides execution order; declaration order does not.
needsstrThe substrate capability the task needs, such as "decision". The default "any" runs everywhere. A required task whose capability is unavailable truncates the plan before dispatch; an advisory one is skipped with its dependents.
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}.
requiredboolFalse makes the task advisory: it blocks dependents but cannot invalidate the run.
isolatedboolRun in a disposable worktree. File changes are discarded; only JSON output continues.
emitslist[str] | dict[str, type]Result fields the task promises in its JSON output. The dict form also promises each field's type: "string", "integer", "number", "boolean", "list", "object", "link", "links", or a list of labels the value is one of. A passing output missing a field, or holding one of the wrong type, fails the task. Types are checked where the graph reads them: over needs a list, a top_k or grade score a number, and a route(source = ...) question labels it can answer. A link is one http(s) url and links a list of them, each naming a result the task produced outside the run (a pull request, a pushed branch, an issue), which the run and task views then link out to. A schema_file(...) promises a value its JSON Schema admits, and is checked against each consumer exactly: over needs "type": "array" with string items (by type, const or enum), a score a numeric type with no non-number in its enum, and a route a const, enum or boolean whose every value it can answer. A when label such a source can never give is refused.
emits_fileslist[str] | dict[str, schema | None]Workspace files the task produces. A task is staged with the declared files of every ancestor that passed, not only its direct dependencies, under inputs/<producer>/; a join = "settled" task also gets those of a direct dependency that failed. JSON outputs, unlike files, come from direct dependencies only. The dict form maps a path to schema_file(...) or None; a file with a schema must hold JSON the schema admits when the task passes, or the task fails.
overproducer.fieldMap the task over a dependency's emitted list, one instance per item.
max_fanoutintInstance cap for over, within the engine's ceiling of 256.
keyedlist[producer.field]Object fields of unmapped dependencies, keyed by item. Each instance receives only its own item's entry in place of the whole field. Needs over.
revisetask | list[task]The tasks this task sends back when it settles failing. They run again, in dependency order, with the verdict under revision, then this task does, until this task stops failing or max_rounds is spent. Every task on a path between them and this task must be listed. Playbooks only; not with over.
max_roundsintRound cap for revise, counting the first, from 2 to the engine's ceiling of 5.
timeoutstrHow long one attempt may run, as 90s, 10m, or 2h. At the limit the attempt's whole process group is killed and the task settles failed with a note naming the limit; it is not retried. The run's --max-time bounds every attempt as well, and a playbook refuses a timeout longer than it before dispatching anything.
stage"iteration" | "epilogue"epilogue runs once after the loop concludes, and only if the run kept a candidate.
historyintRead this many earlier runs of the launch series, from 1 to the engine's ceiling of 30, under history. A run launched outside a series gets an empty list. Playbooks only.
whenroute.questionRun only on a listed answer to one question of a route() this task depends on. Otherwise the task settles not_taken: no dispatch, no spend, no effect on validity, and every all-join dependent is not taken with it unless it lists the task as optional(...). Rejoin branches with join = "passed" or join = "settled". Playbook and custom workflows only.
answersstr | list[str]The answers when accepts: labels the question declares, or "uncertain". Defaults to "yes" for a noul and is required for a choice or a score. A choice whose options come from a field declares none, so only "uncertain".
otherwiseboolIn place of answers: every answer no other task lists and the question does not drop, "uncertain" included. Expanded at compile time. An unreachable otherwise is an error. On a choice whose options come from a field, it also stands for every option the choice resolves to, and is the only way to route them.

command()

A deterministic shell task in the candidate workspace.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
runstrThe command, run through sh -c.
depends_onlist[task | optional(task)]Dependencies. Readiness decides execution order; declaration order does not.
needsstrThe substrate capability the task needs, such as "decision". The default "any" runs everywhere. A required task whose capability is unavailable truncates the plan before dispatch; an advisory one is skipped with its dependents.
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}.
requiredboolFalse makes the task advisory: it blocks dependents but cannot invalidate the run.
isolatedboolRun in a disposable worktree. File changes are discarded; only JSON output continues.
emitslist[str] | dict[str, type]Result fields the task promises in its JSON output. The dict form also promises each field's type: "string", "integer", "number", "boolean", "list", "object", "link", "links", or a list of labels the value is one of. A passing output missing a field, or holding one of the wrong type, fails the task. Types are checked where the graph reads them: over needs a list, a top_k or grade score a number, and a route(source = ...) question labels it can answer. A link is one http(s) url and links a list of them, each naming a result the task produced outside the run (a pull request, a pushed branch, an issue), which the run and task views then link out to. A schema_file(...) promises a value its JSON Schema admits, and is checked against each consumer exactly: over needs "type": "array" with string items (by type, const or enum), a score a numeric type with no non-number in its enum, and a route a const, enum or boolean whose every value it can answer. A when label such a source can never give is refused.
emits_fileslist[str] | dict[str, schema | None]Workspace files the task produces. A task is staged with the declared files of every ancestor that passed, not only its direct dependencies, under inputs/<producer>/; a join = "settled" task also gets those of a direct dependency that failed. JSON outputs, unlike files, come from direct dependencies only. The dict form maps a path to schema_file(...) or None; a file with a schema must hold JSON the schema admits when the task passes, or the task fails.
overproducer.fieldMap the task over a dependency's emitted list, one instance per item.
max_fanoutintInstance cap for over, within the engine's ceiling of 256.
keyedlist[producer.field]Object fields of unmapped dependencies, keyed by item. Each instance receives only its own item's entry in place of the whole field. Needs over.
revisetask | list[task]The tasks this task sends back when it settles failing. They run again, in dependency order, with the verdict under revision, then this task does, until this task stops failing or max_rounds is spent. Every task on a path between them and this task must be listed. Playbooks only; not with over.
max_roundsintRound cap for revise, counting the first, from 2 to the engine's ceiling of 5.
timeoutstrHow long one attempt may run, as 90s, 10m, or 2h. At the limit the attempt's whole process group is killed and the task settles failed with a note naming the limit; it is not retried. The run's --max-time bounds every attempt as well, and a playbook refuses a timeout longer than it before dispatching anything.
stage"iteration" | "epilogue"epilogue runs once after the loop concludes, and only if the run kept a candidate.
historyintRead this many earlier runs of the launch series, from 1 to the engine's ceiling of 30, under history. A run launched outside a series gets an empty list. Playbooks only.
whenroute.questionRun only on a listed answer to one question of a route() this task depends on. Otherwise the task settles not_taken: no dispatch, no spend, no effect on validity, and every all-join dependent is not taken with it unless it lists the task as optional(...). Rejoin branches with join = "passed" or join = "settled". Playbook and custom workflows only.
answersstr | list[str]The answers when accepts: labels the question declares, or "uncertain". Defaults to "yes" for a noul and is required for a choice or a score. A choice whose options come from a field declares none, so only "uncertain".
otherwiseboolIn place of answers: every answer no other task lists and the question does not drop, "uncertain" included. Expanded at compile time. An unreachable otherwise is an error. On a choice whose options come from a field, it also stands for every option the choice resolves to, and is the only way to route them.

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().

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
runstrThe command, run through sh -c.
thresholdnumberGrade the emitted score against this bound. pass = false fails a score within it; pass cannot pass a score outside it.
direction"lower" | "higher"Which side of the threshold passes.
depends_onlist[task | optional(task)]Dependencies. Readiness decides execution order; declaration order does not.
needsstrThe substrate capability the task needs, such as "decision". The default "any" runs everywhere. A required task whose capability is unavailable truncates the plan before dispatch; an advisory one is skipped with its dependents.
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}.
requiredboolFalse makes the task advisory: it blocks dependents but cannot invalidate the run.
isolatedboolRun in a disposable worktree. File changes are discarded; only JSON output continues.
emitslist[str] | dict[str, type]Result fields the task promises in its JSON output. The dict form also promises each field's type: "string", "integer", "number", "boolean", "list", "object", "link", "links", or a list of labels the value is one of. A passing output missing a field, or holding one of the wrong type, fails the task. Types are checked where the graph reads them: over needs a list, a top_k or grade score a number, and a route(source = ...) question labels it can answer. A link is one http(s) url and links a list of them, each naming a result the task produced outside the run (a pull request, a pushed branch, an issue), which the run and task views then link out to. A schema_file(...) promises a value its JSON Schema admits, and is checked against each consumer exactly: over needs "type": "array" with string items (by type, const or enum), a score a numeric type with no non-number in its enum, and a route a const, enum or boolean whose every value it can answer. A when label such a source can never give is refused.
emits_fileslist[str] | dict[str, schema | None]Workspace files the task produces. A task is staged with the declared files of every ancestor that passed, not only its direct dependencies, under inputs/<producer>/; a join = "settled" task also gets those of a direct dependency that failed. JSON outputs, unlike files, come from direct dependencies only. The dict form maps a path to schema_file(...) or None; a file with a schema must hold JSON the schema admits when the task passes, or the task fails.
overproducer.fieldMap the task over a dependency's emitted list, one instance per item.
max_fanoutintInstance cap for over, within the engine's ceiling of 256.
keyedlist[producer.field]Object fields of unmapped dependencies, keyed by item. Each instance receives only its own item's entry in place of the whole field. Needs over.
revisetask | list[task]The tasks this task sends back when it settles failing. They run again, in dependency order, with the verdict under revision, then this task does, until this task stops failing or max_rounds is spent. Every task on a path between them and this task must be listed. Playbooks only; not with over.
max_roundsintRound cap for revise, counting the first, from 2 to the engine's ceiling of 5.
timeoutstrHow long one attempt may run, as 90s, 10m, or 2h. At the limit the attempt's whole process group is killed and the task settles failed with a note naming the limit; it is not retried. The run's --max-time bounds every attempt as well, and a playbook refuses a timeout longer than it before dispatching anything.
stage"iteration" | "epilogue"epilogue runs once after the loop concludes, and only if the run kept a candidate.
historyintRead this many earlier runs of the launch series, from 1 to the engine's ceiling of 30, under history. A run launched outside a series gets an empty list. Playbooks only.
whenroute.questionRun only on a listed answer to one question of a route() this task depends on. Otherwise the task settles not_taken: no dispatch, no spend, no effect on validity, and every all-join dependent is not taken with it unless it lists the task as optional(...). Rejoin branches with join = "passed" or join = "settled". Playbook and custom workflows only.
answersstr | list[str]The answers when accepts: labels the question declares, or "uncertain". Defaults to "yes" for a noul and is required for a choice or a score. A choice whose options come from a field declares none, so only "uncertain".
otherwiseboolIn place of answers: every answer no other task lists and the question does not drop, "uncertain" included. Expanded at compile time. An unreachable otherwise is an error. On a choice whose options come from a field, it also stands for every option the choice resolves to, and is the only way to route them.

report()

Publish a rendered template to a controller-configured destination. The workflow selects a destination key, never an endpoint or a credential.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
destinationdictThe sink to publish to, as {"kind": "slack"}. The controller holds its endpoint and credential.
templatestrPack file rendered into the card body. Reads verdict, spent_usd, passed, failed, tasks (first 20), run, run_url, and result. Every inserted value is escaped for Slack.
resulttaskThe task whose declared fields the card and result.output carry; result.status alone when it did not pass.
severity_fieldstrA declared field of result whose value ("good", "warning", "danger") picks the card accent; any other value is neutral.
requiredboolFalse 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.

ArgumentTypePurpose
namestrSession identity, referenced by session =.
harnessstrDefault harness for tasks in the session.
modelstrDefault model for tasks in the session.
effortstrDefault 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. A supplied value may reach a prompt, with + and inside a region marked as external input, or a skill argument; str(), %, .format(), and string methods on it are refused, as is a value carrying the marker text. A command or evaluate task reads it from params in the inputs JSON at CRUCIBLE_INPUTS_FILE instead of its command line.

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.

schema_file()

Read a JSON Schema (draft 2020-12) below the pack directory, for a field type in emits or a file in emits_files. Its content, not its path, is compiled into the plan. Paths are confined as for prompt_file; a file that is not a valid 2020-12 schema, declares another $schema, or references a remote $ref is 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.

ArgumentTypePurpose
type"autoresearch" | "custom" | "playbook"The lane, which decides which constructors exist.
taskslist[task]Every task that ships.
resulttaskThe task whose output is the workflow's result.
history_recordtaskThe task each run records for the later runs of its launch series: its status, and the fields it declares in emits when it passed. Not a mapped task; an epilogue task records even when the main graph failed. Playbooks only.

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.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
sessionsession | strThe conversation the turn belongs to.
depends_onlist[task]Dependencies.

apply()

Make the candidate live through the configured world. A failure means unscoreable, not worse.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
depends_onlist[task]Dependencies.

measure()

Run the manifest's frozen judge as one opaque measurement task.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
depends_onlist[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.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
scoretaskThe task whose score the decision uses.
tiebreaktaskSecondary score that breaks primary-score ties.
evidencelist[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.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
measurementtaskThe measurement being ruled on.
depends_onlist[task]Dependencies, defaulting to the measurement.

top_k()

Engine-owned reducer: the best k dependency outputs by numeric score.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
kintHow many dependencies survive.
direction"lower" | "higher"Which score wins.
depends_onlist[task]The candidates being reduced.
requiredboolFalse 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.

Playbook and custom lanes only

Available to type = "playbook" and type = "custom". An autoresearch workflow keeps or discards on a frozen measure, so it has neither these nor when.

route()

Engine-owned decision: answers typed questions about its dependencies' outputs and records one label per question, which other tasks branch on with when. Every label of a question some when refers to, "uncertain" included, must be listed by a when or by the question's drop.

ArgumentTypePurpose
namestrTask identity, unique within the workflow.
questionsdict[str, question]Question id to noul(), choice(), or score(). gate.<id> names one for when.
min_confidencenumberA decision model answers, through the broker's decision capability. An answer whose probability is below this, in (0, 1], is recorded as "uncertain". Exactly one of min_confidence and source.
sourcetaskA dependency's output answers instead: it emits one declared label (or a boolean, for a noul) under each question id. Deterministic, free, and needs no capability. Any other value fails the route. When the dependency types its emits, each question's field must be typed with labels the question answers, or "boolean" for a noul.
humanboolTrue: a person allowed to approve the run answers, from the controller UI, after seeing the dependencies' declared outputs and files. Needs the human capability. Tasks that do not depend on the route keep running while it waits.
reviewpathWith human: a Markdown template in the pack, rendered over the evidence (inputs, run, gated) and shown above it. Every inserted value is escaped.
timeoutdurationWith human: how long the request stays open, from when it opens; the run's wall-clock ceiling by default. An unanswered request records every question as "uncertain".
fileslist[str]Declared JSON files of dependencies the model reads, under files in its state, by dependency and path. Each must be declared by a dependency with a schema_file(...). Not with source.
overproducer.fieldDecide once per item. A task mapped over the same list reads each item's answer with when; one mapped over another list, or not mapped, cannot.
max_fanoutintInstance cap for over, within the engine's ceiling of 256.
keyedlist[producer.field]Object fields of unmapped dependencies, keyed by item. Each instance receives only its own item's entry in place of the whole field. Needs over.
depends_onlist[task]Dependencies. Their outputs are the state the questions are asked about.
requiredboolFalse makes the route advisory.
join"all" | "passed" | "settled"Which dependency outputs form the state, as on any task.
stage"iteration" | "epilogue"As on any task.
whenroute.questionRun only on a listed answer to one question of a route() this task depends on. Otherwise the task settles not_taken: no dispatch, no spend, no effect on validity, and every all-join dependent is not taken with it unless it lists the task as optional(...). Rejoin branches with join = "passed" or join = "settled". Playbook and custom workflows only.
answersstr | list[str]The answers when accepts: labels the question declares, or "uncertain". Defaults to "yes" for a noul and is required for a choice or a score. A choice whose options come from a field declares none, so only "uncertain".
otherwiseboolIn place of answers: every answer no other task lists and the question does not drop, "uncertain" included. Expanded at compile time. An unreachable otherwise is an error. On a choice whose options come from a field, it also stands for every option the choice resolves to, and is the only way to route them.

noul()

A yes/no question for route(). It answers "yes" or "no".

ArgumentTypePurpose
askstrWhat to decide.
dropstr | list[str]Answers that deliberately lead nowhere, so no when has to list them.

choice()

A one-of-N question for route().

ArgumentTypePurpose
askstrWhat to decide.
optionslist[str] | dict[str, str | None] | producer.fieldAt least two distinct identifier labels, optionally each with a description the model sees. "uncertain" is reserved. Or an unmapped dependency's field, read at each decision: the list itself, or, on a route with over, an object keyed by item holding each item's list. Each entry is a label or {"value": label, "description": str}; at most 64, a repeated label keeps its first entry, and fewer than two fails that decision. The answer records the options it chose among. Needs min_confidence.
multipleboolTake one or more labels. Only a human = True route asks it; a when runs if any listed label was chosen.
dropstr | list[str]Answers that deliberately lead nowhere, so no when has to list them.

pick()

A question for a human = True route whose options are a list a dependency produced. The route's output holds the picked values under the question id, so over = gate.question fans out over them. No when routes on it.

ArgumentTypePurpose
askstrWhat to pick.
sourceproducer.fieldA list of strings in the output of a task the route depends on, read when the route opens its request.
multipleboolTake one or more values rather than one.

score()

An ordinal question for route(). It answers its most probable level, the lowest on a tie, and records a score in [0, 1]: the expected level position over the normalized distribution, 0 for the lowest level and 1 for the highest. A source answers one level label, scored by its position, and "uncertain" records no score.

ArgumentTypePurpose
askstrWhat to decide.
levelslist[str] | dict[str, str | None]At least two distinct identifier labels, lowest first in the order written, optionally each with a description the model sees. "uncertain" is reserved.
dropstr | list[str]Answers that deliberately lead nowhere, so no when has to list them.

optional()

Mark an entry of depends_on that may settle not_taken. Under join = "all" the task dispatches past it as though it passed, and its inputs carry no entry for it; one that failed or was blocked still blocks. Refused under another join, on a dependency that can never settle not_taken, and on a task the reviewer revises.

Takes one positional argument, task.

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.

FieldTypeMeaning
status"pass" | "fail" | "skipped""fail" or "skipped" settles the task that way, whatever its exit status, pass or threshold. "pass" cannot pass a task that exited nonzero or did not pass its grade. Any other value is ignored.
notestrWhy the task failed or was skipped, recorded as its note when it is a non-blank string: after the exit status in place of the stderr tail when a command exits nonzero, before the threshold and log handles when an evaluation does not pass, and in place of the default note when status is "fail" or "skipped". The control plane shows it as a parked run's reason. Read only from a result that fails or skips.
completebooltrue on a passing main-graph command or evaluate task of a playbook ends the run early and valid: nothing else in the main graph dispatches, undispatched tasks stay unsettled, and epilogue tasks still run. The shutdown outcome is complete. Any other task's true is refused on its row and the run continues. A task may not list it in emits.
reasonstrWhy the run completed early, recorded with the shutdown. A task may not list it in emits.

Inputs the engine writes

Present alongside the dependency entries, never wrapped in one.

FieldTypeMeaning
historyobjectEarlier terminal runs of the launch series, as {"records": [record], "dropped": int}, oldest first by end time, at most the task's history depth. Each record is {"run", "started_at", "ended_at", "outcome", "verdict", "revision", "link", "entry": {"task", "status", "output"}}. dropped counts records the operator's size limit removed from the oldest end. In a task that declares history only; an agent reads it as marked external input.
itemstrThis mapped instance's key, one per item of the list over names.
keptobjectThe kept candidate, in an epilogue task only.
outcomeobjectHow the main graph ended and what each of its tasks settled as, as {"exit": str, "tasks": {name: {"status", "note", "output", "files"}}}, in an epilogue task only: each entry is what a settled join receives, per_instance included for a mapped task. files says whether that task's declared files, passing or failing, are staged under inputs/<name>/.
paramsobjectEvery declared parameter's bound value under its name, in its declared type, and {} where the source declares none, in a command or evaluate task only.
revisionobjectThe verdict that sent this task back, as {"round": int, "max_rounds": int, "reviewer": str, "review": {"status", "note", "output", "files"}}, from the second round of a revise loop on.