The tool loop (CONTEXT.md "Turn"): one input-to-final-answer cycle, run inside the Session's supervised Task (ADR 0001).
record user_message
loop:
fold History → call the Provider (streaming deltas as ephemeral Events)
if the model returned function_calls → run each via the Executor
(which records tool_call / tool_result), then repeat
else record the final assistant_message and stopHistory is always re-derived from the Log each iteration (ADR 0003): the stateless Provider sees tool results because they were persisted, not because we threaded them in memory.
Wire it into a Session like:
Pixir.Session.start_turn(sid, fn ctx -> Pixir.Turn.run(ctx, prompt) end)Options: :provider (module, default Pixir.Provider), :provider_opts (passed to
the provider — e.g. :auth, :transport), :dry_run (Turn-level dry-run, ADR
0005), :max_iterations.
Summary
Functions
Default tool-loop iteration cap. :infinity means no cap.
The late developer-context input item text (px2 Layer 2): the volatile,
session-scoped facts deliberately kept OUT of the cacheable instructions prefix.
Pairs with system_prompt/3 — see its doc for the pairing contract.
Run one Turn for user_text. Returns {:ok, final_text} or a structured error.
The default system prompt for a Turn (open knob). mode defaults to :build.
Types
Functions
Default tool-loop iteration cap. :infinity means no cap.
The late developer-context input item text (px2 Layer 2): the volatile,
session-scoped facts deliberately kept OUT of the cacheable instructions prefix.
Pairs with system_prompt/3 — see its doc for the pairing contract.
The base text is deliberately byte-stable across plan/build flips (mode is already
fully expressed by the instructions, and a changed input[0] would break WebSocket
continuation's prefix-extension check). The base variation is a posture line when the
EFFECTIVE permission deviates from the mode's default: a build-mode Turn forced
read-only — the one case the instructions cannot know about.
Presenter-supplied UX context is appended here as late, non-authoritative developer context. Presenters such as T3 Code may supply open-file, selection, branch, or diagnostic facts, but Pixir still renders them into Provider input itself.
Run one Turn for user_text. Returns {:ok, final_text} or a structured error.
The default system prompt for a Turn (open knob). mode defaults to :build.
px2 pairing contract (ADR 0020): this prompt is byte-stable per mode and names no
workspace. It tells the model a developer message identifies the workspace root, so
any direct Provider.stream caller using this prompt MUST also pass
developer_context: Turn.developer_context(ctx, mode, permission_mode) — otherwise
the model is promised a message that never arrives and has no workspace root at all.