{"id":3991,"date":"2026-10-11T21:35:21","date_gmt":"2026-10-11T21:35:21","guid":{"rendered":"https:\/\/www.examtopics.biz\/blog\/?p=3991"},"modified":"2026-10-16T21:06:58","modified_gmt":"2026-10-16T21:06:58","slug":"claude-agent-loops-tool-results-stop-reasons","status":"publish","type":"post","link":"https:\/\/www.examtopics.biz\/blog\/claude-agent-loops-tool-results-stop-reasons\/","title":{"rendered":"Anthropic CCA-F: Claude Agent Loops, Tool Results and Recovery"},"content":{"rendered":"<p>A Claude application that uses external tools is not a single prompt that somehow completes every operation the model proposes. It is a sequence of model decisions and application-controlled actions. Claude can request a tool call, but client-side code must validate the request, run the permitted operation, return its outcome, and decide whether another model turn is needed. The difference between a proposed action and a verified result is the foundation of reliable agent systems.<\/p>\n<p>This article explains the Messages API exchange, the role of <code>tool_use<\/code> and <code>tool_result<\/code> blocks, how to interpret <code>stop_reason<\/code>, and how to recover when a tool, context window, or network request fails. A fictional support-workflow example keeps the mechanics concrete. The aim is not to reproduce certification questions; it is to make architectural decisions understandable and testable.<\/p>\n<h2>Why model output cannot be treated as external execution<\/h2>\n<p>Consider a customer asking whether an order qualifies for a return. Claude may request order details, retrieve a policy, and explain the outcome. If the model writes \u201cI looked up your order,\u201d that statement alone does not establish that a lookup took place. A reliable client records the actual tool request, validates which customer is authorized to view which order, runs the lookup through approved software, and supplies the result for further analysis.<\/p>\n<p>The <a href=\"https:\/\/platform.claude.com\/docs\/en\/agents-and-tools\/tool-use\/how-tool-use-works\" rel=\"nofollow\">Claude tool-use model<\/a> separates two responsibilities. The model selects a declared capability and supplies arguments. The host application controls client-tool execution, business validation, secrets, timeouts, logging, and permissions. A JSON schema can improve the structure of a call, but it does not decide whether the authenticated user may access the requested record.<\/p>\n<p>An agent loop is therefore a stateful protocol, not merely a repeated instruction to \u201ckeep going.\u201d It needs bounded execution, consistent message history, a way to describe failures, and clear conditions for reporting success. More autonomy is useful only when the system can tell what has actually happened.<\/p>\n<h2>Five stages of a client tool-use cycle<\/h2>\n<h3>1. Declare narrow tools with clear contracts<\/h3>\n<p>A client application provides Claude with <a href=\"https:\/\/www.examtopics.biz\/blog\/claude-mcp-tool-design-errors-permissions\/\">tool definitions<\/a> containing names, descriptions, and input schemas. For a support example, <code>get_order<\/code> might accept an order identifier and return read-only status fields, while <code>check_return_eligibility<\/code> interprets policy using verified order facts. Neither tool needs permission to modify the order. Giving a read-only workflow a general command executor creates risk without delivering a useful capability.<\/p>\n<p>Descriptions should distinguish what each tool can establish. A good <code>get_order<\/code> contract might promise status, delivery date, and permitted item categories for an order in the authenticated account. The application\u2014not the model\u2014maps the session identity to allowed order IDs. It also decides which returned fields are safe to include in the next model message.<\/p>\n<h3>2. Inspect every tool_use block and its unique ID<\/h3>\n<p>When Claude requests a client tool, the assistant message contains one or more <code>tool_use<\/code> blocks. Each has an <code>id<\/code>, a tool <code>name<\/code>, and an <code>input<\/code> object. The response normally has <code>stop_reason: tool_use<\/code>. Do not try to recover a tool call by searching prose for a function name: that loses the machine-readable input contract and can confuse commentary with instructions.<\/p>\n<p>A single model turn can request several tools. Preserve each identifier and determine whether the calls are independent. Two read-only lookups may run concurrently if neither depends on the other. A policy decision that depends on an order status must wait for that status rather than invent an intermediate value.<\/p>\n<h3>3. Validate and execute through application policy<\/h3>\n<p>The host resolves the requested tool name against an allowlist, validates inputs, confirms the customer can access the target, and invokes the owning service with scoped credentials. It should apply a timeout and an appropriate result-size limit. The model never needs the service password or an unrestricted query interface to answer a return-policy question.<\/p>\n<p>Failed validation is a meaningful outcome, not a reason to bypass authorization. A tool should report \u201corder not accessible in this account\u201d without exposing another person&#8217;s information. If a downstream service is unavailable, preserve the distinction between an unsuccessful lookup and a lookup that established a negative answer.<\/p>\n<h3>4. Return matching tool_result blocks in a user message<\/h3>\n<p>The next message to Claude contains <code>tool_result<\/code> blocks. Each result includes the <code>tool_use_id<\/code> of the call it answers. Retain the original assistant tool-use message in the conversation immediately before the corresponding results. If several client tools were requested together, return a result for every ID, including explicit errors where necessary, and follow the API&#8217;s rules for placing tool results before other user content.<\/p>\n<p>The <a href=\"https:\/\/platform.claude.com\/docs\/en\/agents-and-tools\/tool-use\/handle-tool-calls\" rel=\"nofollow\">tool-call handling documentation<\/a> describes how errors are returned. A client tool result can use <code>is_error: true<\/code> to indicate that execution failed. This is not the same as a refusal by the model or an HTTP error from the Messages API. A clear error lets the model ask for clarification or report uncertainty without fabricating missing data.<\/p>\n<h3>5. Continue, but verify the application outcome separately<\/h3>\n<p>After receiving tool results, Claude may request another tool or provide a final response. Repeat only while the application has a justified step remaining and budget permits it. A model response ending with <code>end_turn<\/code> means that Claude finished producing that response. It does not prove that a payment, shipping change, deployment, or other external operation completed.<\/p>\n<p>For a read-only question, a final answer based on verified records may be sufficient. For a workflow with side effects, the authoritative external system must independently confirm the state before the application says the operation succeeded. This division between conversational completion and operational completion is essential for dependable automation.<\/p>\n<h2>Trace a three-turn return-eligibility request<\/h2>\n<p>The following identifiers and order details are invented for teaching purposes. They describe the message relationship, not a recording from a running application. Assume customer C-17 has already authenticated and requests, \u201cCan I return order ORD-42? The item arrived damaged.\u201d The host exposes only two read-only tools: <code>get_order<\/code> and <code>check_return_eligibility<\/code>. It intentionally exposes no return-label creation or refund execution tool.<\/p>\n<h3>Turn A: request and answer the order lookup<\/h3>\n<p>Claude requests <code>tool_use(id=\"toolu_order_A\", name=\"get_order\", input={order_id:\"ORD-42\"})<\/code> and stops with <code>tool_use<\/code>. The host verifies that ORD-42 belongs to the authenticated customer and returns a permitted subset of facts: delivery status, purchase date, and relevant item category. The following user message contains <code>tool_result(tool_use_id=\"toolu_order_A\", content={status:\"delivered\", age_days:9, category:\"electronics\"})<\/code>. No change to the order has occurred.<\/p>\n<p>The application keeps the assistant message containing the original tool request immediately before the tool-result message. It also keeps the verified account identity in its own trusted session state. The identifier <code>toolu_order_A<\/code> is not an authorization token; it only correlates this request to the corresponding result.<\/p>\n<h3>Turn B: check eligibility using established facts<\/h3>\n<p>Claude then requests <code>tool_use(id=\"toolu_policy_B\", name=\"check_return_eligibility\", input={order_id:\"ORD-42\", reason:\"DAMAGED\"})<\/code>. The host checks the authenticated order and sends a matching tool result such as <code>{eligible:true, evidence_required:true, human_review_required:true}<\/code>. The result says only that the policy preliminarily allows a review. It is not proof that a return was accepted, that a label was issued, or that a refund was made.<\/p>\n<p>Claude may now tell the customer that the request qualifies for initial review and that evidence and a person\u2019s <a href=\"https:\/\/www.examtopics.biz\/blog\/claude-agent-sdk-hooks-human-approval\/\">approval<\/a> are required. If the response ends with <code>end_turn<\/code>, the informational task can finish accurately, while the operational return case remains pending. That distinction should be visible both in the answer and in the application\u2019s workflow status.<\/p>\n<h3>Turn C: handle denial without inventing a result<\/h3>\n<p>Run the same flow with an unauthorized order. The host rejects <code>get_order<\/code> and returns a <code>tool_result<\/code> associated with <code>toolu_order_A<\/code> and <code>is_error:true<\/code>. The model must not use fabricated order data to call eligibility, nor should the application quietly switch to another account. The next appropriate step may be a request for an accessible order identifier or a human handoff. A polished answer is not a substitute for the missing verified facts.<\/p>\n<h2>Know what each stop_reason actually means<\/h2>\n<p>Anthropic\u2019s <a href=\"https:\/\/platform.claude.com\/docs\/en\/build-with-claude\/handling-stop-reasons\" rel=\"nofollow\">stop-reason reference<\/a> distinguishes model-generation status from API errors. Handling these values explicitly prevents common mistakes such as treating truncation as completion or treating a server-tool pause as a client-tool request.<\/p>\n<p><strong>end_turn: <\/strong>The assistant finished its response. Use the content as a model response, but confirm any real-world side effect independently.<\/p>\n<p><strong>tool_use: <\/strong>A tool call requires client handling. Validate every client tool_use block and return the matching tool results.<\/p>\n<p><strong>max_tokens: <\/strong>The output-token limit was reached. Treat the response as truncated. Do not execute incomplete tool arguments; adjust or continue safely.<\/p>\n<p><strong>stop_sequence: <\/strong>A caller-specified stopping sequence was emitted. Inspect stop_sequence ; decide completion only according to a tested application contract.<\/p>\n<p><strong>pause_turn: <\/strong>A server-side tool loop paused after reaching its iteration limit. Resume with the assistant content as documented for server tools, within an application budget.<\/p>\n<p><strong>refusal: <\/strong>Claude declined the response. Handle the refusal explicitly, without disguising it as operational success.<\/p>\n<p><strong>model_context_window_exceeded: <\/strong>The available model context window was filled. Preserve essential facts and treat the returned content as incomplete.<\/p>\n<p>When <code>max_tokens<\/code> interrupts a response, it might cut off a tool request before all arguments have arrived. Do not pass a partial JSON fragment to a real service. Reconstruct or continue the response following the latest SDK guidance, then validate the completed tool input before execution. The same conservative principle applies to a streaming connection that ends before a complete response can be assembled.<\/p>\n<p>A <code>stop_sequence<\/code> is not a universal \u201ctask succeeded\u201d flag. Its significance comes from the caller\u2019s configured sequence and downstream parser. A model can reach the marker without having executed a tool or produced all fields required by a business workflow. Validate the whole output contract instead of inferring success from a delimiter.<\/p>\n<p>The <code>pause_turn<\/code> case concerns server-side tool execution. The continuation mechanism does not mean the host should invent a <code>tool_result<\/code> for a server tool that has not finished. In mixed client\/server tool cases, keep the declared tools and the waiting tool blocks consistent across the resumed request. A production implementation should use the current documented continuation pattern rather than treating every pause as a fresh conversation.<\/p>\n<h2>Parallel tool calls need matching results and real dependencies<\/h2>\n<p>One assistant turn may contain several <code>tool_use<\/code> blocks. Suppose a support agent asks for a read-only shipment event and a separately authorized return-policy lookup. The client can run those independent reads at the same time, but it must still return one <code>tool_result<\/code> per tool-use ID in the next appropriate user message. Missing a result because its tool timed out can leave the conversation structurally incomplete or cause a model to reason from evidence that never arrived.<\/p>\n<p>Dependency matters more than throughput. An eligibility operation that requires the shipping status cannot safely execute against a guessed \u201cdelivered\u201d value. A write operation cannot race ahead of an approval check. Organize dependencies in ordinary program logic, then use concurrency only within independent groups. Log the mapping of request ID, tool name, normalized parameters, result ID, status and latency so that a failure can be reconstructed.<\/p>\n<p>Keep result messages compact and privacy-aware. Return facts relevant to the next decision, not complete customer records or internal infrastructure payloads. Good response design reduces exposure and context usage, while explicit missing-value markers are better than omitting fields that the model might guess.<\/p>\n<h2>Client tools, server tools, and the MCP boundary<\/h2>\n<p>A client-defined tool is executed by your application. Anthropic also offers server tools that execute within the platform\u2019s tool infrastructure. The control flow differs: a server-side tool may run without the host submitting an ordinary client <code>tool_result<\/code>, and mixed turns may contain pending server-tool blocks. Read the response block types, not only the top-level stop reason, before deciding how to continue.<\/p>\n<p>The Model Context Protocol provides a separate interoperability layer for accessing declared tools and other capabilities through compatible clients. MCP does not itself imply that a model executed arbitrary server code or that a successful schema validation grants permission. For this article the relevant skill is handling the client\u2019s observable tool-use exchange. Tool selection descriptions, server configuration, MCP transport and error semantics deserve their own focused architectural treatment rather than being repeated here.<\/p>\n<p>Do not confuse similarly named error fields at different layers. Claude API client-tool results can use <code>is_error<\/code>, while MCP tool execution results use <code>isError<\/code>. A JSON-RPC protocol error is another distinct event. The integration layer should translate these statuses intentionally and preserve enough context for the model and the human operator to understand the failure.<\/p>\n<h2>Separate model, tool, transport, and business failures<\/h2>\n<h3>A denied request is not an unavailable service<\/h3>\n<p>An accessible-looking order number can still be outside the authenticated account. A good tool responds with an authorization-safe denial without leaking whether another customer\u2019s order exists. A service outage is different: it means the application lacks the data needed to answer, not that the order failed eligibility. Preserve these distinct meanings in both program state and the model-facing result.<\/p>\n<h3>A model completion is not an external receipt<\/h3>\n<p>If Claude returns <code>end_turn<\/code> while a separate workflow still awaits human review, the conversation may be complete but the case is pending. Similarly, an HTTP 200 response from a tool endpoint may prove only that a request was accepted. Before claiming a delivery update or payment change succeeded, obtain a status record from the system that owns that operation.<\/p>\n<h3>A timeout may conceal an already-completed side effect<\/h3>\n<p>Read-only lookups can often be retried with bounded exponential backoff. Side-effecting calls require stricter treatment. When a timeout occurs after sending a change request, keep the original transaction or idempotency identifier and inspect the owning service for its outcome. A new call with a new identifier can cause a duplicate action. If the state remains ambiguous, mark it \u201cunconfirmed\u201d and escalate rather than inventing a successful or failed result.<\/p>\n<h2>Design a bounded loop instead of unlimited autonomy<\/h2>\n<p>Set limits on model turns, total tool calls, per-tool timeouts, response size and cumulative cost. A model can request the same unhelpful lookup repeatedly when a source is unavailable. Without a bound, an innocuous support question can run until the user\u2019s latency and usage budgets are exhausted. Each stop condition should have a named application state and a clear user-facing message.<\/p>\n<p>Store durable facts outside the model transcript when the workflow needs them: authenticated actor, approved resource IDs, completed tool operations, pending manual review, the last known external status, and references to the evidence. A summary of the conversation is useful to the model, but it is not a replacement for a database record that proves what happened. Keep the model\u2019s narrative separate from the system\u2019s control plane.<\/p>\n<p>For a support status workflow, sensible terminal states include <em>answered<\/em>, <em>more information needed<\/em>, <em>human review pending<\/em>, <em>service unavailable<\/em>, <em>refused<\/em>, and <em>budget exceeded<\/em>. These are not interchangeable. Displaying the correct state helps users act appropriately and keeps operations teams from misinterpreting a completed assistant message as a closed business case.<\/p>\n<h2>Test cases that reveal hidden loop defects<\/h2>\n<p><strong>Normal lookup:<\/strong> An authorized order lookup succeeds and the eligibility tool says human review is required. Assert that each <code>tool_use_id<\/code> has one matching result, the final response accurately describes review as pending, and no write tool ran.<\/p>\n<p><strong>Unauthorized order:<\/strong> The lookup is denied. Assert that no information about another customer is returned, no eligibility decision is made from invented facts, and the user is directed to an appropriate verification step.<\/p>\n<p><strong>Two independent tools, one error:<\/strong> One read succeeds while another times out. Assert that both requested IDs receive results, including an explicit error, and the final explanation distinguishes verified information from missing evidence.<\/p>\n<p><strong>Truncated tool arguments:<\/strong> The model reaches <code>max_tokens<\/code> before its tool input is complete. Assert that no partial command is executed and the recovery strategy preserves the original request context.<\/p>\n<p><strong>Paused server tool:<\/strong> A response has <code>pause_turn<\/code>. Assert that the application follows the correct server-tool continuation pattern, retains waiting result blocks and stops after its own continuation budget.<\/p>\n<p><strong>Ambiguous external operation:<\/strong> A permitted side effect times out. Assert that the system reconciles the original operation ID before considering a retry and never reports success based solely on a generated sentence.<\/p>\n<p>These tests are more informative than asking whether the agent \u201cseems reliable.\u201d Each has a measurable failure condition, and each directs the fix to the right layer\u2014message structure, execution authorization, recovery, or external verification\u2014rather than adding a vague instruction to the prompt.<\/p>\n<p>A final regression case should vary the observation point instead of changing the user&#8217;s instruction. Let the backend commit an approved adjustment, then lose its response before the client receives the matching tool result. The model must not invent a receipt, and the client must reconcile the external operation ID before considering a retry. For someone using third-party <a href=\"https:\/\/www.examtopics.biz\/cca-f\">CCA-F practice<\/a> questions, this is a useful way to challenge answer explanations: distinguish model stop reasons, application-controlled tool execution and the business system&#8217;s actual state. A correct design names what can be retried, which evidence is missing, how authority is checked and the point at which the loop must stop.<\/p>\n<h2>How this fits Claude Certified Architect \u2013 Foundations<\/h2>\n<p>In a return-eligibility workflow, the model&#8217;s request and the completed business action are separate events. The client should preserve the tool-use identifier, validate arguments against the caller&#8217;s authority, perform the permitted lookup and return a result that describes what the service actually observed. If a write times out after execution, the application must reconcile a stable operation identifier before deciding whether another call is safe.<\/p>\n<p>A useful regression fixture exercises a successful lookup, a missing permission, an invalid tool-result identifier and a lost acknowledgement after a possible side effect. Each case needs a different expected next action. Only the application and the external service can confirm whether a transaction committed; a fluent explanation from the model is not a receipt. This separation makes failures diagnosable instead of encouraging indiscriminate retries.<\/p>\n<p>A good architecture is not the one with the most tool calls. It is the smallest design that gets verified facts, limits authority, handles failures honestly and finishes in a state a human or downstream program can actually trust.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A Claude application that uses external tools is not a single prompt that somehow completes every operation the model proposes. It is a sequence of [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33,29],"tags":[],"class_list":["post-3991","post","type-post","status-publish","format-standard","hentry","category-ai-machine-learning","category-certifications"],"_links":{"self":[{"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/posts\/3991","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/comments?post=3991"}],"version-history":[{"count":5,"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/posts\/3991\/revisions"}],"predecessor-version":[{"id":4696,"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/posts\/3991\/revisions\/4696"}],"wp:attachment":[{"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/media?parent=3991"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/categories?post=3991"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.examtopics.biz\/blog\/wp-json\/wp\/v2\/tags?post=3991"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}