Context
What run context holds, where each value comes from, and when it is available
Look up what a run’s context holds, where each value comes from and when a step can read it. Routes and prompts read context by dotted path.
[steps.review]kind = "probe"observe = "github.pr"routes = [{ if = "github.pr.state == 'MERGED'", to = "steps.merged" }]next = "steps.wait"Context holds the goal, the declared inputs, accepted agent outputs, command facts, probe and action records, and each step’s outcome. context.github.pr.state and github.pr.state read the same value.
Inputs and defaults
Section titled “Inputs and defaults”Each [inputs.<name>] table declares an input. An input is required unless it sets required = false or a default. Names are lowercase snake_case and cannot occupy the namespaces Orbital and its probes write. goal is built in; [inputs.goal] may set only label, hint and default. Starting a run requires a goal and every required input, and rejects undeclared inputs. An absent optional value renders empty.
[inputs.notes]kind = "text"label = "Notes"hint = "Anything the plan should take into account"default = "Keep it short"label and hint give the input the label and hint the new-run form shows. An input without a label shows its name. A value given when the run starts replaces the default. Input kinds lists every kind and its keys.
A ticket or epic input is looked up when the run is created, so a ticket Orbital cannot read refuses the run rather than failing a step later. Templates then read its fields, such as {{ inputs.ticket.title }} or {{ inputs.epic.body }}, and {{ inputs.ticket }} on its own renders the reference the run was given. The run keeps the fields under internal.inputs.<name>, so a loop restart keeps them with the original inputs.
Inputs are copied into context when the run starts, so {{ context.work }} can later change while {{ inputs.work }} keeps the original. Loop restart restores the original inputs. Routes read context only, never inputs.*.
Agent outputs
Section titled “Agent outputs”An agent step declares its outputs under outputs and finishes by calling the handoff tool with them, for example:
{"verdict":"pass","findings":[]}That call fits these declarations:
outputs.verdict = { kind = "choice", options = ["pass", "reject"] }outputs.findings = "json"Orbital gives the agent the exact output contract and accepts only declared keys with matching types.
| Kind | Contract |
|---|---|
choice |
One of the declared options. Without options, one of the values the step’s routes test. |
text |
A non-empty string. The editor calls it Paragraph. |
short_text |
A non-empty string with no line break. |
list |
An array of objects, each with exactly the list’s item fields, stored as JSON text in context. It must hold an item unless it sets allow_empty = true. |
number |
A number, kept as a number in context, so size == 3 compares it. |
yes_no |
true or false, kept as a boolean in context, so risky == true compares it. |
json |
Any JSON value, unchecked, stored as JSON text in context. |
work |
A work scope, one of the four kinds below. |
ticket |
A ticket URL that Orbital checks it can read. Later templates read its fields like a ticket input. |
Work scopes are Leaf with a ticket URL and a Parent or None parent, Hierarchy with a ticket and a hierarchy, Candidate with a description and evidence, or Goal with goal text. Required descriptive values are non-empty. Ticket URLs use HTTP or HTTPS, and a leaf cannot be its own parent. {{ current_work }} renders the saved scope for shared delivery prompts. A missing scope does not silently fall back to a previous ticket.
Malformed output triggers up to two correction turns in the same session. If correction fails, the step fails and follows failure routing. Context changes only after acceptance. The final prose stays available as {{ context.response.<id> }}, where a grouped or imported step’s id is dotted, such as context.response.reviews.clarity.
Command facts
Section titled “Command facts”A command step writes exactly the dotted names its facts table declares, plus <id>.failed. It cannot overwrite the paths probes and actions write or the failure paths.
Probe and action records
Section titled “Probe and action records”A probe step writes per-folder facts under the folder name, such as web.github.pr.raw. Selected pull request and thread facts also roll up, including github.pr.state and github.threads.unresolved. <folder>.github.threads.open holds only the unresolved review threads as readable text, so quote it rather than <folder>.github.threads.raw in a prompt that addresses feedback; the raw value keeps every thread, resolved ones included. git.diff and git.worktree facts stay per folder. git.change and tracker.tickets are read once for the run.
| Probe | Writes |
|---|---|
github.pr |
github.pr.state, github.pr.checks_green, github.pr.checks_total, github.pr.checks_pending, github.pr.checks_failing, github.pr.required_checks_*, and per folder <folder>.github.pr.raw, <folder>.github.pr.head, <folder>.github.pr.url and <folder>.github.pr.new_feedback, the open review feedback no step has handled yet, with each comment’s author. |
github.threads |
github.threads.unresolved, and per folder <folder>.github.threads.open and <folder>.github.threads.raw. |
git.diff |
Per folder <folder>.git.diff.*, such as <folder>.git.diff.changed_lines. |
git.change |
git.change.diff and git.change.unpublished. |
git.worktree |
Per folder <folder>.git.worktree.*. |
tracker.tickets |
tracker.tickets.text, tracker.tickets.total and tracker.tickets.unreachable. |
Before format version 3 these facts had no probe name in front, such as pr.state and <folder>.diff.raw. Those old names still work as aliases in conditions, needs and prompts, and the loader warns with the name to write instead. Converting a DOT workflow writes the new names.
The worktree.remove action writes run-wide git.worktree.clean and git.worktree.status. The github.pr.open action writes github.pr.url, github.pr.number and github.pr.state, the same paths the github.pr probe uses.
Pull request routing prioritises MERGED, CLOSED, CONFLICTS, CI_FAILED, CHANGES_REQUIRED, then WAITING. Across several repositories the rollup takes the worst state in the order CLOSED, CONFLICTS, CI_FAILED, CHANGES_REQUIRED, WAITING, MERGED, and reports MERGED only when every observed repository has merged. A pull request that merges or closes while the probe reads it is observed once more and routed as MERGED or CLOSED instead of failing the probe. CI_FAILED means a check’s job ran and failed. When GitHub never ran a failed check’s job, because of billing or a spending limit, no runner, or a job it did not start or cancelled before any step ran, the probe takes no route. The run is Paused on the probe step and shows “Waiting on you”, with GitHub’s reason and the names of those checks. Fix the cause on GitHub, then resume the run to measure the pull request again. Raw pull request evidence gives repair prompts the check details; open review feedback is in <folder>.github.threads.open, and every thread in <folder>.github.threads.raw.
Required checks
Section titled “Required checks”For each folder, the github.pr probe’s github.pr.checks_total, github.pr.checks_pending, github.pr.checks_failing and github.pr.checks_green describe required checks only. The corresponding github.pr.required_checks_* summaries are exact aliases. The top-level roll-ups combine the repositories’ results, with failing and pending counts becoming booleans. Optional checks remain in raw diagnostics and never affect these summaries or the delivery state.
A readable observation with no required checks sets github.pr.required_checks_observed=true and github.pr.required_checks_settled=true, with totals and pending and failing counts at zero. The green flags remain false because no check passed. If the probe falls back to Actions workflows, requirement information is unknown. It sets github.pr.required_checks_observed=false, omits the summary families and does not claim settlement. Raw output retains workflow diagnostics and the unknown requirement status.
Step outcomes
Section titled “Step outcomes”After each step, Orbital writes the step’s outcome to outcome, as succeeded or failed, with failure_reason empty on success. Both are readable from routes and prompts.
Availability
Section titled “Availability”The validator checks that a value is produced on every path leading to the step that reads it. A step’s needs can give a value a default, so a path that does not produce it still validates. A branch cannot read a sibling’s outputs, or the results the previous round of its fan-out left. After the join, read branch values through parallel.results, whose entries carry node, outcome, failure_reason and context, in the order of the fan-out’s child steps. Numeric dotted segments address them, for example parallel.results.0.context.assessment; in templates the index is quoted.
Related
Section titled “Related”- Add branches: how routes read these values.
- Template variables: how prompts read these values.
- Pass context between steps: outputs feeding later steps, in a worked example.
- Workflow file: a complete workflow that validates.