From Prompt to Patch: The Turn Loop
In openai/codex, the important unit of action is a turn: the bounded cycle that starts with accepted input and ends only when the model, its tools, and the runtime agree that no more work is pending. This chapter follows that cycle from context capture to streamed model output, tool execution, feedback, and completion. The goal is practical: after reading it, you should be able to predict why a tool call causes another model request, why Codex records that call before execution finishes, and where interruption, parallelism, retries, and context limits change the path.
A turn is narrower than a thread. A thread gives the conversation a durable identity and retains the state needed for future work. A turn is the active operation inside it. The distinction matters because a single user request may require several model-provider requests, multiple tool handlers, and several event notifications while still belonging to one turn.
The sequence is not a promise that every turn follows every arrow. A response can end the turn without a tool, a cancellation can stop the cycle, and a failure can prevent the next request. The point is the direction of control: the provider proposes output, while Codex owns the transitions that turn that output into history, tool work, and further sampling.
A turn begins with a coherent snapshot
Codex does not start by sending the user's latest sentence directly to the model. It first admits the input into the session and captures a step context. That context is the runtime's view of the current turn: the effective model settings, environment, instructions, conversation history, and tool router that will govern the next request.
The snapshot is important because several things can change around an active turn. A client may submit more input while the model is working. A configuration update may affect a later turn. An MCP server may refresh. A user may interrupt the operation. If the first model request assembled each field independently at arbitrary times, the model could be shown one set of tools while the runtime executed another, or reason from settings that no longer match the action path. Capturing a step context gives one sampling request a coherent basis.
The prompt built from that context contains conversation items, base instructions, model-visible tool specifications, a setting that permits or disallows parallel tool calls, and—when requested—an output schema. The schema constrains the final response shape; it does not replace the tool loop. Tools still appear as capabilities the model may invoke, and their results still return through the conversation path.
The model connection has a similar division of ownership. Codex keeps provider selection, authentication, and some fallback state at session scope. It creates a model-client session for each turn, which can reuse a provider connection across follow-up requests within that turn. The session also carries turn-specific routing state. Reusing it across turns would leak state that belongs to the previous operation, so the boundary is deliberate: stable identity lives with the thread/session, while sampling state lives with the turn.
This preparation is not wasted ceremony. It answers the first control question: what exact world is the model being asked to act in? The answer includes not only the user's words but the runtime's current view of history, tools, settings, and environment. Once that view is fixed for the request, Codex can interpret the provider's stream against the same state it advertised.
The provider stream creates branches
The model provider returns a stream of typed events. Codex receives response creation information, output-item boundaries, text deltas, reasoning updates, usage data, and completion status. It turns those events into client-facing events while also maintaining internal state needed for the next transition.
At a high level, a completed response takes one of two paths. If the model produces an assistant response without requesting more work, Codex finalizes that item, records it in the turn history, and can treat the turn as complete; reasoning may accompany that response. If the model produces a function call or another supported tool-shaped item, Codex recognizes it as a tool call. The response is no longer the end of the turn; it is an instruction to continue the loop through a runtime-owned handler.
Streaming changes what the client sees, but it does not change who owns completion. Assistant text can be forwarded as deltas while the response is arriving. Tool arguments may also be exposed incrementally for suitable tools, allowing a client to display progress. Yet Codex waits for the relevant item boundary before treating the call as complete and dispatchable. This keeps partial provider output separate from the finalized action that the runtime will record and execute.
The distinction between an assistant message and a tool call also prevents an important ambiguity. An assistant message is content to add to the conversation. A tool call is a request to cross an execution boundary. The two may appear in the same provider response, but they do not have the same lifecycle. Codex finalizes ordinary response items into turn items; tool-shaped items go through the tool router and runtime instead.
That router is built for the current step. It maps the model's tool name and payload to a registered executable handler, checks whether the tool supports parallel calls, and retains the step context associated with the advertised capability. A tool that is present in the model's prompt is therefore not just a string name. It is part of a concrete plan connecting specification, dispatch, permissions, and result encoding.
A tool call becomes feedback, not a side effect outside the conversation
When Codex receives a completed tool call, it records the model's response item before the handler finishes. This ordering is one of the clearest signs that the turn loop is designed for interruption and recovery. If a process is slow, a user cancels the turn, or a handler fails after dispatch, the history still contains the model's proposed call rather than silently losing the event that caused the work.
After recording the call, Codex queues the handler as an in-flight future. The tool runtime waits for any readiness condition, enters a shared execution gate, and dispatches through the router. Tools that declare parallel support can share the read side of that gate. Tools that do not support parallel execution take the exclusive path. This is bounded concurrency: the model may request several calls, but the runtime decides which handlers may overlap.
The execution future returns a structured result. A normal failure is converted into a response item that identifies the failed tool call and gives the model information it can use. A fatal failure propagates differently and can end the turn. Cancellation also has a defined result: when a tool has not reached a terminal outcome, Codex can abort its task and return an “aborted by user” result with timing information. These distinctions let the next model step reason about a failed or interrupted action instead of mistaking silence for success.
Codex drains the in-flight results after the provider stream reaches its boundary. It then records the tool outputs in the conversation history. If the response indicated that more work is needed—or if pending input arrived while the tools were running—the outer turn loop continues. The next sampling request is constructed from the updated history, so the model can see what the tool actually returned before choosing its next action.
Consider a request to inspect a failing test and change the implementation. The first response might ask for a shell command. Codex records that request, runs the command through its tool runtime, and sends the result back as part of the next model input. The second response might ask for a patch. That patch is another tool call with its own runtime path, not an invisible consequence of the first command. The model is repeatedly reacting to observed state, while Codex ensures each transition is recorded and routed through the current capability plan.
This feedback structure is why “the model wrote the patch” is an incomplete description of what happened. The model proposed a sequence. The runtime translated each proposal into a typed call, ran the corresponding handler, stored the result, and made that result available for the next proposal. The useful behavior emerges from the loop between inference and execution.
Pressure changes the route without changing the ownership model
A real turn is not a straight line. Codex checks for pending input, token status, retryable provider errors, hook outcomes, and cancellation at several boundaries. These conditions change the route, but they do not transfer ownership of the state machine to the model or the tool process.
Pending input is one example. A user interface may allow a new message while a model response or tool handler is active. Codex does not necessarily inject that message into the middle of a provider stream. It records and drains input at controlled points, then decides whether the active turn needs another sampling step. The current source even distinguishes cases where continuation should resume before a steer is delivered, preserving the model/tool sequence instead of allowing concurrent input to scramble it.
Retries are another controlled branch. A turn-scoped model-client session can reuse the same provider connection and routing state for requests that belong to the turn. If a stream error is retryable, Codex applies bounded retry logic rather than blindly starting a new conversation. If the error is a context-window overflow or a usage limit, it updates the relevant state and returns the condition to the turn lifecycle instead of treating it like a transient network failure.
Context pressure can trigger compaction before a turn starts or after a response and its tools have increased the active window. Compaction is not just deletion of the newest item. The turn code invokes a dedicated compaction path and then rebuilds the context needed for continuation. When the model still needs to act after compaction, the loop resumes with the new prompt state. This is the trade-off of durable, multi-step work: retaining history provides continuity, but the active prompt must remain within the model's available window.
Hooks add another form of feedback. Before and during a turn, hooks can inspect input or produce additional context. At the apparent end of a turn, a stop hook can request a continuation prompt or stop the operation. Codex handles that outcome before deciding whether the turn is truly finished. The final answer is therefore not the only possible termination signal; the runtime's lifecycle policies also participate.
Cancellation follows the same principle. It propagates through the provider stream and child tool futures. A cancelled stream becomes a turn-aborted outcome, while a tool that has already reached a terminal result may be allowed to finish its result path. The exact behavior depends on where cancellation arrives, but the source makes the boundary explicit rather than pretending that an interrupt can erase work that has already been recorded or completed.
Completion means that no more feedback is required
The cleanest completion case is an assistant response with no follow-up work. Codex finalizes the response item, records usage and other turn state, runs the applicable stop hooks, and emits the completion events that clients consume. The caller may see streamed text before that point, but the turn is not complete merely because text appeared on screen.
A tool response has a different meaning. It is evidence for another inference request. The outer loop continues until the model no longer needs a tool, pending input no longer requires handling, and no lifecycle policy asks for continuation. At that point, the last assistant message can be returned as the turn's user-facing result.
This design gives openai/codex a specific kind of agency. It is not a single model invocation with a collection of callbacks attached. It is a stateful feedback controller. The model supplies proposals and interpretations; Codex owns snapshots, routing, persistence, cancellation, retries, and termination. Tools change the world and return evidence, but their outputs re-enter the conversation as model input rather than bypassing it.
That is also why the next question is about context. The turn loop explains when Codex samples and why it samples again. To understand what the model can infer at each step, we need to examine how history, settings, environment information, and project instructions are assembled into the bounded prompt that feeds the loop.