> For the index of every page in Orbital's docs, read https://docs.runorbital.dev/llms.txt.

# History and threads

> What each prompt carries from earlier steps, and how sessions and threads continue

Look up what each prompt carries from earlier steps, and how sessions continue from one step to the next.

```toml title="syntax.toml"
[steps.answer.plan]
prompt = "Plan an answer to {{ inputs.goal }}."
thread = "answer"
next = "steps.answer.give"

[steps.answer.give]
prompt = "Give the planned answer."
thread = "answer"
```

Before each prompt, Orbital adds a preamble with the goal, a heading for each finished step, steering and relevant context. Repeated visits fold into one step heading with a visit count. A step's final message is not carried: a step hands the next one what it needs through its declared outputs, and a prompt that wants an earlier agent's prose quotes `{{ context.response.<id> }}`.

## Threads and restart

Turns normally start fresh sessions. `thread = "implementation"` shares a session across agent steps carrying that thread name. The steps of one thread must resolve to the same harness, and threads are not allowed inside parallel branches.

A route or `next` with `loop_restart = true` clears the values the loop wrote to context, the history of finished steps that later prompts show, and every thread's session. It keeps the original inputs, the run's identity, the visit counts and the budgets.

## Parallel branches

A `fan_out` step runs each of its child steps as a branch, in file order, up to `max_parallel` at a time. Every branch must reach the fan-out's `join`, a `fan_in` step. Branches cannot loop, hold a gate, set a thread or route out of their branch.

Each branch gets its own context and visit accounting, without the results an earlier round of the same fan-out left. Results arrive in the order of the child steps under `parallel.results`, with `node`, `outcome`, `failure_reason` and `context`. A branch agent's answer appears in the preamble of the fan-in's own turn only; any later step reads it by quoting `{{ context.response.<id> }}`, such as `{{ context.response.reviews.clarity }}`, so a loop through the fan-out does not grow every later prompt. Branches share working files, so use read-only reviews or disjoint writes. Successful collection enters the join; a partial failure takes a matching route from the fan-out's `routes`. With no such route the run is Paused and shows "Waiting on you".

A fan-in with a prompt runs one synthesis turn. Without a prompt it is only the meeting point. In templates use a quoted index, such as `{{ context.parallel.results['0'].context.assessment }}`. The [parallel guide](/workflows/run-steps-in-parallel/) validates that spelling in a complete workflow.

## Waits

A `wait` step requires a `duration`, for example `5m`. Waiting keeps the interface responsive. You can choose **Skip** to end the wait early, and the transcript records that choice. A wait keeps its wake time across a restart, and poll loops spend no agent turns from `max_visits`.

## Related

- [Run steps in parallel](/workflows/run-steps-in-parallel/): a complete fan-out and join that validates.
- [Template variables](/reference/template-variables/): how a prompt quotes an earlier agent's answer.
- [Gates and waits](/workflows/gates-and-waits/): when to pause a run for a person or a time.
- [Workflow file](/reference/workflow-file/#complete-example): a complete workflow that validates.
