A support agent calls a billing tool, receives the result and stops before replying to the customer. In another case, an answer cut off by a token limit is saved as a completed decision. Both failures come from treating every model response as an end state. The host application must inspect Claude’s response state, execute permitted tool requests, append results to the working exchange and stop only when completion criteria are satisfied. That control loop illustrates an architecture responsibility tested in Anthropic CCA-F: the model may request the next action, but application code owns budgets, stop conditions, retries and externally visible side effects.
The host owns the control loop
Claude can propose a tool call, but a client-executed tool is run by the application. The model returns a structured tool-use block with an identifier, tool name and arguments. The host checks permissions and parameters, invokes the corresponding operation and sends back a result linked to the original tool-call ID. Only then can Claude incorporate the observation into subsequent reasoning. A conversational transcript alone does not execute external business logic; the application’s loop is responsible for those actions and their consequences.
This separation is essential for testing. If a tool call is blocked, the host must return a clear denial or error and prevent side effects. If a lookup succeeds, its result must be attached to the correct request. Missing or misassociated tool results can make the assistant reason from the wrong transaction. A reliable implementation records each iteration with request ID, authorized operation, returned result and any outstanding work so that an interrupted task can be diagnosed.
Interpret stop reasons instead of assuming completion
The Messages API reports a stop_reason to describe why generation stopped. A natural end_turn indicates the assistant has finished its current response; tool_use means the host is expected to handle tool requests; max_tokens or a context limit may mean content was truncated. A custom stop sequence is another deliberate termination condition. These states cannot be handled with one generic branch that extracts text and declares success.
The correct host behavior depends on the reason and the content blocks. On tool use, execute authorized calls and return matched results. On a natural final turn, validate whether the expected answer or task outcome was produced. On truncation, do not treat incomplete JSON as a completed record. A refusal is a separate outcome and should be handled according to the application policy. Designing these branches is more important than telling Claude in a system prompt to always finish.
Handle client tool results as a protocol
A tool request carries a unique identifier. After execution, the application returns a tool_result referring to that identifier rather than merely appending a sentence that says the lookup succeeded. If two requests run in parallel, their results must remain correctly paired even when one finishes later. Preserve their separate success or failure conditions instead of merging raw outputs into an unstructured narrative. The host should never invent a result for a tool that did not run.
The next model request includes the preceding assistant tool-call content and the new result blocks. This gives Claude the concrete observations it needs. Tool errors should be represented clearly, including whether the operation was attempted and whether any side effect may have occurred. If a payment call timed out, the application should reconcile the transaction with the provider before repeating it. Tool-loop mechanics and safe recovery belong to the same correctness model.
Distinguish server tools and client tools
Some tools execute on Anthropic’s side, while user-defined client tools require the host application to run them. That distinction affects continuation behavior. A response involving a server-side tool may already contain its tool result; a response involving a client tool may pause pending the application’s result. In mixed cases, the host must understand whether a server tool is still waiting rather than assuming all advertised calls have finished. Correct implementations inspect the actual response blocks, not just tool names.
Server-side loops may also pause after reaching an iteration limit. A pause_turn state is not a final answer and should not be mistaken for a permission failure. Continue the conversation according to the documented pattern, subject to the application’s total work budget and safety checks. The architect should avoid embedding an unbounded retry that continues forever; a paused operation still consumes resources and may be approaching a deadline beyond which the task is no longer useful.
Protect against truncation and partial output
Imagine a document extractor returning a customer ID, amount and policy assessment. If generation stops because the requested token limit was reached halfway through the final field, the application must not persist the partial text as an accepted transaction record. Validate the response shape and completion state before committing anything downstream. The correction may involve a supported continuation or retry with an appropriate limit, but it should not silently fill missing values with guesses.
A context-window limit is different from an ordinary requested output limit. The former can mean that the conversation itself has grown too large for faithful continuation. The application may need to summarize history, remove stale tool output or reload compact structured state. Any such transformation should preserve essential identifiers, verified facts and unresolved uncertainties. A shorter prompt that loses the transaction ID is not an improvement merely because it allows another model call to succeed.
Set application-level iteration budgets
A loop budget is not solely about counting model turns. A pre-tool enforcement hook can stop unauthorized actions regardless of remaining budget. For independent work that can finish later, asynchronous Message Batches may replace an interactive loop, but need their own expiry and acceptance gates. Neither an extra model turn nor a cheap batch result establishes that an external operation completed safely.
An unconstrained tool loop can repeatedly search the same document or alternate between two services without progressing. Bound model turns, external calls, elapsed time and spending according to the task’s business value. For a shipping status inquiry, repeated lookup attempts may be less useful than a clear message saying the carrier is temporarily unavailable. For a lengthy research task, a larger budget may be justified, provided intermediate evidence is preserved and the user can see what remains open.
The stopping rule should reflect progress as well as count. Track whether each iteration obtains new relevant evidence, resolves an open question or completes a validated step. If a worker keeps proposing the same search, return a structured no-progress condition and route to another approach or human review. This is not a prompt-engineering trick; the host makes a deterministic decision to protect time and resources. The model can explain the limitation without being allowed to overrule it.
Treat tool use as part of a transaction boundary
When a tool changes external state, the loop needs a business transaction identifier independent of the model turn. A refund may commit even if the conversation’s acknowledgment is lost. A reliable host stores idempotency keys and checks authoritative status before retries. Do not infer from end_turn that a service committed or from tool_use that a call did not yet take effect. These labels describe generation state, not the state of a remote ledger.
The orchestration layer can keep a durable operation log with prepared, submitted, confirmed and unresolved states. If a service returns an ambiguous timeout, suspend additional writes until status is reconciled. The model may continue read-only investigation, but it should not issue new refunds simply to obtain a reassuring answer. This separation is a key architectural skill: language-model continuity and business-side effects advance through related but independently verified state machines.
Write tests for every terminal branch
A useful test suite exercises natural completion, tool-use continuation, multiple tool results, malformed arguments, denied tools, provider errors, token-limit truncation, paused server loops and model refusal. For each case, define whether the host should return an answer, retry, ask for clarification, escalate or stop safely. Test that forbidden actions never execute, that results match their tool-call IDs and that no partial response is accepted as a complete business object.
A test might intentionally provide an unknown tool name or omit one result in a multi-tool round. The host should reject the inconsistent state and preserve evidence for debugging. Another test might have Claude finish naturally but omit a required user-facing summary. That situation needs output validation and perhaps a controlled follow-up prompt, not unconditional success. Protocol correctness and business completeness are separate conditions, and production monitoring should report them separately.
A customer support loop from lookup to resolution
The customer asks whether a double charge has been reversed. Claude requests a payment lookup, causing a tool_use response. The host verifies account access, runs the lookup and returns a structured result linked to the tool-call ID. Claude sees that one authorization was voided but another payment settled. It may request an additional transaction status check. When it eventually produces an answer, the host validates that the referenced payment IDs and statuses come from the tool results and have not been guessed.
If the second lookup is unavailable, the response explains the unresolved status without claiming completion. If the conversation was truncated, the application preserves the verified payment states and obtains a complete final message before sending it. If a refund is requested, a separate permission gate protects that write. This is the difference between an agent that merely calls tools and a trustworthy production workflow: every transition is interpreted, authorized and checked against the external truth it is meant to represent.