How a Turn Learns From Its Own Actions

In Codewhale, a turn is not a single request followed by a single answer. It is a bounded feedback cycle that turns a user task into model requests, admitted tool calls, tool results, diagnostics, and a terminal lifecycle state. Understanding this loop lets a reader trace one local edit from its proposed action to the evidence that supports the next step—and also see where cancellation, context pressure, or a failed transport can stop the work.

The important shift from the previous architecture map is temporal. The Runtime is not merely a place that receives a task; it repeatedly decides whether it can take another step, what information belongs in the next request, and whether the work has ended honestly. The model remains central, but it is one participant in a controlled sequence.

A turn begins with a bounded request

When Codewhale starts a turn, the engine captures the selected model client and the current tool policy. It establishes the turn’s wall-clock and step budgets, watches for cancellation, and carries forward the mode and authority that should govern the work. This prevents a turn from becoming an unbounded loop just because the model continues producing tool calls.

The loop also accepts steering input and notices child-agent completions while work is underway. A person may redirect the task, or a delegated worker may finish while the parent is still reasoning. Those events become part of the turn’s working history rather than being hidden in a separate channel that the model discovers too late.

Before another provider request is authorized, Codewhale checks whether the conversation is approaching its route-specific context budget. If pressure is high, it may perform bounded compaction: older material is summarized and the session continues with a smaller history. If recovery cannot bring the request within the effective budget, the turn fails with the conversation preserved rather than pretending that an over-limit request succeeded.

This is already a useful distinction between a model call and a Runtime turn. A model call is a request to a provider. A turn is a supervised sequence that may contain several provider requests, tool executions, recovery attempts, and a terminal outcome. The latter is the unit a person needs to understand when asking what happened to a task.

The loop has to preserve several kinds of continuity at once. Conversation history gives the model the reasoning context. The tool catalog gives it a bounded set of actions. The turn context carries cancellation, budgets, and the current authority. The Runtime state records what has settled. These are related, but they are not interchangeable. A tool result should not silently change the approval posture; a model response should not rewrite a durable lifecycle state; a compaction pass should not be treated as a new user instruction.

This is also why a turn can stop at a request boundary rather than only after a command fails. If the wall-clock budget is exhausted, the loop stops before authorizing another billable model request while retaining the work already produced. If the model-step budget is reached while work remains, Codewhale can grant a bounded final-report opportunity or coordinate owned children before ending. If cancellation arrives, the active turn returns an interrupted outcome instead of letting an in-flight continuation masquerade as ordinary completion. The boundaries are part of the mechanism, not merely status messages displayed after the fact.

A small tool surface, with depth behind it

The model does not receive every registered capability as a long first-turn menu. Codewhale keeps a compact canonical surface for common operations such as reading, writing, editing, shell execution, delegation, and progress. Specialized capabilities—Git inspection, web access, durable tasks, MCP tools, plugins, and other advanced actions—can be deferred and discovered when the task needs them.

That design reduces two kinds of confusion. A model has fewer near-duplicate names to choose among, and a person can inspect a tool call without scanning an inventory of every possible integration. Deferral does not necessarily mean that capability has been removed. It means the capability is not placed in the initial model-visible set and must pass the current policy before it is activated.

The exact count of the eager surface is not a stable fact to repeat casually. The public tool-surface document gives a seven-name summary, while the current source snapshot includes additional goal controls alongside the core operations and keeps tool_search as a synthetic discovery capability. The important, evidence-safe conclusion is the design principle: Codewhale presents a compact canonical surface and defers specialized tools. The documentation and source should not be silently harmonized into a fixed number when they disagree.

The catalog also protects the stability of its non-deferred head. The tool array participates in the provider’s prefix context, so changing its order or contents unexpectedly can force a costly re-prefill. Deferred tools are added without casually reshaping the stable core. In other words, tool discovery is not only a usability feature; it is also a performance and request-identity concern.

Compatibility introduces another distinction. An older name may remain registered so that a saved transcript or an exact legacy call can still be replayed, while that name is hidden from a new model’s catalog. Discoverability and dispatchability are therefore not identical. This lets Codewhale simplify what a new model sees without treating history as disposable.

The request, gate, action, and result

Once the loop has prepared the next request, the selected provider streams a response. That response may contain ordinary text, reasoning, or one or more tool calls. A tool call is not yet a filesystem or shell action. It enters the Runtime’s admission and authorization path, where the current mode, policy, approval posture, and worker authority determine whether it may proceed. The next chapter examines those gates in detail; here the key point is that the loop waits for an outcome before treating the action as a new fact.

If the call is admitted, Codewhale executes it and records a bounded result. A file read returns information about the requested content. A write or edit returns an execution result that can be followed by diagnostics. A shell call returns a bounded observation rather than an invitation to copy an unlimited process transcript into the next request. The model receives that result as new context and can decide whether another action is necessary.

The cycle is easiest to see in one edit:

sequenceDiagram participant U as User participant R as Runtime turn participant M as Model client participant C as Tool catalog participant G as Admission gate participant T as Repository tool participant L as Diagnostics U->>R: Submit task R->>C: Prepare available tools R->>M: Send task and tool surface M-->>R: Stream text or tool call R->>G: Check the proposed action G-->>R: Admit, ask, or block R->>T: Execute admitted call T-->>R: Return bounded result R->>L: Inspect successful edit L-->>R: Queue diagnostics when available R->>M: Send result and diagnostics M-->>R: Continue or finish

The diagram has two feedback paths. The ordinary path sends a tool result back to the model. The edit path may also ask a language server for diagnostics before the next provider request. Both paths are controlled by the Runtime; neither requires the model to infer silently that its action worked.

Fresh evidence without destabilizing the request

After a successful file edit, Codewhale can derive the affected path and ask the configured language-server manager for diagnostics. The diagnostics are queued rather than immediately spliced into every piece of state. Immediately before the next provider request, the Runtime drains the queue into a synthetic runtime message. The model then sees the result of the edit as fresh input on its next reasoning step.

The failure rule is deliberately asymmetric. A missing or crashing language server should not block the agent. Diagnostics can improve the feedback loop, but they are not the only path by which a turn can proceed. If the server is unavailable, Codewhale should report less evidence, not invent an error or deadlock the task.

The same principle governs context compaction. Runtime-generated facts such as diagnostics, steering input, and child completions are appended to the conversation history. They do not silently rebuild the pinned system prompt and tool prefix after every tool step. That preserves prefix-cache stability while allowing the model to receive new information. A declared context change—such as an explicit mode or goal operation—can re-pin the prefix; ordinary volatile results remain history.

Context is also more than a raw token count. Codewhale treats the effective window as route-specific and tracks where the value came from: a configured provider or model override, provider-reported metadata, a catalog, or a conservative fallback. Unknown or unverified limits remain labeled as such. Optional native memory follows the same rule. It is disabled by default, and when enabled its bounded notes are marked as untrusted user data; a local note is still sent to the selected model as prompt context.

These qualifications prevent a familiar failure mode in AI tooling: treating a number that controls a budget as proof of a provider capability. A conservative fallback may let the loop operate, but it does not prove that the model serves that window. The turn can make a safe operational choice without turning an estimate into a fact.

Before asking what the loop proves, it helps to see how its observations survive beyond the current screen. Codewhale’s state layer distinguishes a conversation thread from its messages, checkpoints, jobs, and dynamic tools. The Runtime adds Thread, Turn, and Item records plus an append-only event sequence. A turn can therefore be inspected as a lifecycle rather than reconstructed from the last paragraph that happened to be visible in the terminal.

This persistence changes the meaning of recovery. A process restart can mark an in-flight turn interrupted and preserve the binding that prevents an idempotent retry from creating a duplicate operation. A side-git snapshot can restore workspace files without rewriting conversation history. An offline queue can preserve a submitted prompt while the provider is unavailable. These mechanisms do not make a task correct, but they prevent a transport interruption from erasing the distinction between work that was attempted, work that settled, and work that still needs attention.

The loop’s boundedness also protects the parent from noisy or oversized observations. Tool results can be summarized or kept behind handles rather than copied without limit into the next request. Child completions can arrive as compact lifecycle events instead of full transcripts. Memory, when enabled, is bounded and marked as untrusted context. Each choice trades some detail for a stable request, but the trade is explicit: the system should say when data was omitted, summarized, unavailable, or unverified rather than filling the gap with a plausible default.

What the loop can prove

A turn’s evidence has layers. The model’s final answer is a statement. A tool result is evidence that a particular call settled with a particular result. A diagnostic is evidence that a configured checker observed a condition after an edit. A persisted Runtime record is evidence about lifecycle state: queued, running, completed, failed, interrupted, or canceled. A workspace snapshot is evidence that files can be restored to a recorded point; it is not evidence that the implementation was correct.

The distinctions matter when a model stops early. If a step budget is reached, Codewhale can request a bounded final report rather than ending silently. If a stream fails, the loop may use a limited retry path. If cancellation arrives, the turn should end as interrupted rather than presenting a partial answer as a clean completion. If context recovery fails, the conversation remains saved while the turn reports that it could not proceed.

None of this makes the loop an oracle for semantic correctness. It makes the path from action to claim inspectable. A test that exits successfully may still test the wrong behavior. A language server may report no diagnostics while a design requirement remains unmet. A durable completion state may record successful lifecycle settlement while a verifier later marks the task incorrect. Codewhale’s contribution is to keep those facts from collapsing into one unqualified sentence.

The turn therefore learns from its own actions in a precise sense: it receives structured consequences of tool calls and uses them to decide what to request next. It does not learn that every action was wise, and it does not transform every absence of an error into proof of success. The next question is where the gates sit between a model proposal and a running command, and which of them remain active even when the user chooses a more autonomous posture.

References