A turn is one loop. The agent makes one model call per pass. If that call asks for tools, they face the gate, run, and their results come back for the next pass. The first message without tool calls is the answer.
ground → agent ─(no tool calls)─→ answer
↑ │ tool calls
└── tools ← approval (a fully rejected batch goes straight back to agent)ground
builds the context once per turn: the working folder, your standing instructions (~/.saturn/SATURN.md, then the folder's SATURN.md), the knowledge-base manifest, your memory, today's date and time, and any attachments. No model call.
agent
one native tool-calling call. Its reply either carries tool calls or is the answer, which streams under ── response as it's written.
approval
asks the gate policy about each call. Anything it doesn't auto-approve stops the turn for you. See the approval gate.
tools
runs the approved calls, records any egress, and fences instruction-shaped content in the results before the model sees them.
The agent works in rounds. Calls in one pass run together, so it batches calls only when none needs another's result. "Read the file, then email whoever it names" reads the file first and writes the mail on the next pass, instead of guessing the address. A chat question costs one model call; a single lookup costs two.
::the plan checklist
On a task that needs several tool calls, the agent records a checklist with the plan tool and updates it as steps complete. The checklist renders live in the rail. It also shows in the gate's e explain view, in /trace why, in a replay, and in the headless --json plan field. The agent skips it for a single lookup or a chat answer.
The checklist records what the agent intends, not what happened. plan is read_only and changes nothing outside the turn, so it never faces the gate. The answer's account of what was done comes from the tool calls that actually ran.
::pause, steer, abort
| you do | what happens |
|---|---|
Esc on an empty line | the turn pauses at the agent's next pass and shows the checklist, if there is one: [Enter] continue · type a correction to steer · q abort |
type a correction, then Esc | the correction is added to the conversation and the agent reads it on its next pass. The turn keeps going; nothing restarts. |
q at the pause | the turn stops at your request |
Ctrl+C | cancels the turn outright |
A correction typed just before an Esc pause isn't lost: it lands when the turn resumes. Steering is the same key story as queuing: Enter defers a line to the next message, and Esc acts on it now.
::when it asks instead of guessing
When a value, choice, or confirmation is missing and no tool can supply it, the agent calls ask_user with one question. The turn pauses, you type an answer, and the answer comes back as that call's result. ask_user always runs alone: if the model batches other calls with it, those are sent back with "ask first". Asking changes nothing, so it never faces the gate. Headless there's nobody to ask, so the tool reports that no answer exists and the model has to say what is still unknown.
::bounds and honest endings
- –
runtime.max_iterations(default 16) caps the passes that may run tools. From that pass on, no tool call runs: the model answers from what it has and says what was not done. - –A call identical to one already made twice this turn, with nothing changed in between, is refused as a loop. A legitimate re-read still runs.
- –A call you declined at the gate is never re-issued this turn.
- –An unknown tool, missing or malformed arguments, or arguments that belong to a different tool are sent back to the model with the right shape, with no gate and no extra model call. A malformed reply is retried once.
- –A messaging call naming a phone number or email address that appears in nothing you typed and nothing a tool returned is refused before it reaches you. See your mac.
::thinking, only where it helps
runtime.think defaults to adaptive: a pass thinks, within runtime.think_budget (4096 tokens), only when the tool round just before it had an error, which is where the model needs a new approach. A chat answer, a clean lookup, and the final pass of a capped turn run without thinking. off never thinks; on thinks on every pass but the capped one. The reasoning never enters the answer, and /trace why shows what a thinking pass thought.