AnthropicClaude Certified Architect – Foundations2026-101.1 Design and implement agentic loops for autonomous task execution
Preserve every call and matching result
Completed by the knowledge check
Learning objective
Preserve assistant tool_use blocks, execute every requested call, and return matching tool_result blocks by tool_use_id in the next user turn.
Core idea
A tool round trip is part of the conversation, not an external operation whose result you can paste anywhere. The assistant requests a specific operation through a tool_use block. Your application preserves that request and returns a tool_result whose tool_use_id matches the call’s id. Claude then has both the requested action and the observed result as context for its next decision. The Messages API is stateless: every request carries the full conversation history, so a result your application holds but does not append is evidence Claude never sees.
Preserve the complete assistant content array, not a reconstruction containing only tool names or text. For a batch of calls, resolve every requested client call and send the results together in the immediately following user message. A rejected or skipped operation still needs a matching error result; executing every request never means bypassing authorization.
See 1.1.1 for the stop-reason switch. This lesson focuses on what the transcript must contain before that switch sends the next request.
How it works
Keep the assistant request intact
For ordinary user-defined client tools, each tool_use block supplies id, name, and input. Dispatch by the tool name, validate and authorize its input in your executor, and associate the outcome with the block’s unique id. The tool name is not the correlation key: Claude can call the same tool more than once with different inputs.
Append an assistant message with role: "assistant" and the response’s complete content. That content can include text alongside tool calls. Retaining it records what Claude actually requested and keeps the conversation coherent. Filtering out text for dispatch is useful; replacing the saved assistant message with that filtered list is a different operation and loses content.
Next, append a user message containing the results. The Claude Messages API uses user and assistant messages for this exchange, rather than a separate tool or function role.
A minimal illustrative exchange for a user-defined order lookup has this shape:
[
{
"role": "assistant",
"content": [
{ "type": "text", "text": "I'll check that order." },
{
"type": "tool_use",
"id": "toolu_order",
"name": "lookup_order",
"input": { "order_id": "A42" }
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_order",
"content": "Order A42 shipped; carrier status is delayed."
}
]
}
]The example shows conversation blocks, not a complete API request or a built-in Anthropic tool. lookup_order represents an application-defined tool. In production, copy the id from the response instead of inventing it.
Resolve the whole batch
Claude can request several tools in one response. Extract every client tool_use block, resolve each one, and assemble one tool_result per call in the next user message. Match by identifier even when the calls finish in a different order. Sending only the fastest result leaves the other calls unresolved.
The Messages API does not prescribe execution order for ordinary client calls. You can execute independent read-only operations concurrently, while operations that share state or cause side effects can run sequentially. Collect their outcomes before sending the next model request. Parallel execution and a single result message are compatible: concurrency concerns the executor, while grouping concerns conversation structure.
If execution fails, set is_error: true and put a useful explanation in content. If policy denies a call, or an earlier failure makes a later operation unsafe, return a matching error result explaining why it did not run. Do not claim success or silently omit the call. A denied action is evidence the model needs to choose another path or explain the blocker.
This scheduling freedom has exceptions. Anthropic’s computer-use and browser-use member calls require sequential execution in returned order and stopping at the first failure. Their results also carry toolset-specific requirements. The ordinary user-defined tools in this lesson do not imply that every Anthropic tool has the same execution contract.
Respect adjacency and block ordering
No message can intervene between the assistant’s call message and its corresponding user result message. A logging note, a progress update, or a newly arrived customer message belongs outside that pending exchange. Store application events separately until the tool round trip is resolved.
Within the user result message, put all tool_result blocks before any ordinary text. An introduction such as “Here are the results” before the first result violates the formatting requirement. Text after the results is permitted for a client-only turn, but Anthropic identifies it as a common cause of empty end_turn responses, so send result-only messages.
Mixed client/server turns need stricter treatment. If the assistant also contains a server_tool_use with no result yet, preserve that assistant content, return only the client tool_result blocks, and keep the same tools array in the follow-up request. The server operation finishes on Anthropic’s side. Additional user text ends that open turn prematurely; for a server tool Claude called directly, the request fails with HTTP 400 invalid_request_error naming the unresolved server tool. Do not fabricate a local result for the pending server call.
Keep externally sourced material inside tool_result rather than moving it into the system prompt or ordinary user text. That retains its role as evidence from a tool. It does not make hostile content trustworthy, but avoids promoting retrieved instructions into a higher-authority message.
Key distinctions and trade-offs
Tool name versus call identity: name chooses the implementation; id identifies this invocation; tool_use_id connects its result. One implementation can have several outstanding calls.
Execution outcome versus transcript validity: A service can return correct data while your next request is invalid because a result is missing or misplaced. Conversely, a valid is_error: true result can accurately report an operation that failed.
Concurrency versus causality: Independent lookups can run together. A mutation that depends on another operation needs controlled ordering. The executor owns scheduling, but every requested call still needs an outcome in the transcript.
Preserving the full response costs context. Rewriting it to save tokens risks losing the structure needed for the next decision. Handle broader context management deliberately; do not compress away unresolved call/result relationships.
Architecture / decision scenario
A support agent requests lookup_order twice, once for each shipment, plus lookup_customer_policy. All three calls are read-only and independent, so the executor runs them concurrently. The second shipment lookup finishes first; the first fails because its backing service is unavailable.
The application saves the assistant’s entire content array, including the explanatory text and all three calls. It builds three results keyed to the three original identifiers. The failed lookup gets is_error: true; the other two carry their observed data. A single user message contains all three results, with no progress message inserted in between.
Claude can now distinguish a policy result from a shipment result and decide whether another lookup is needed. It must not receive the successful shipment result under the failed shipment’s identifier merely because the tool names match.
If the same assistant turn also left a server search pending, the application keeps that server block intact and submits only the three client results with unchanged tool definitions. If a requested mutation were denied, it would also receive a matching error result instead of disappearing. The transcript therefore explains what happened for every call without granting execution authority through omission or invented success.
Common exam traps
- Returning results under
role: "tool". - Matching results by tool name or completion order.
- Handling only the first
tool_useblock. - Inserting a user message before the pending tool results.
- Placing introductory text before
tool_resultblocks. - Omitting a denied or skipped call instead of returning an error result.
- Discarding assistant text when saving the response history.
- Keeping a tool result in an application variable instead of appending it, so the next request omits the evidence Claude asked for.
What to remember
Preserve the assistant’s full response. Resolve every client call, correlate by id and tool_use_id, and return results together in the immediately following user message. Scheduling can vary; the call/result contract cannot.
Knowledge check
During testing, a support agent requests lookup_order and the application runs it successfully. The next response requests the same lookup again, and this repeats until a safety cap stops the run. The application stores each result in a variable and resends the same messages list each time. What fixes the loop?
tool_result matches its tool_use_idrole: "tool" placed right after Claude’s responsetool role — results go back as tool_result blocks in a user message.Claude requests lookup_order twice in one response, once for each of a customer’s two shipments. The executor runs both lookups concurrently, and the second one finishes first. How should the application return the results?
id and send both together in the next user messageid identifies the invocation, and the result’s tool_use_id connects the two. Every result for one response goes together in the next user message. Concurrency is the executor’s choice and does not need to be undone — correlation by identifier makes completion order irrelevant.Claude requests three tools in one response. Two are read-only lookups that succeed; the third is a refund that the application’s policy denies for this account. What should the next user message contain?
is_error: true and stating the denialis_error result reports it honestly; omitting the call or explaining it in text leaves the call unresolved, and executing it because the model asked bypasses authorization.While the executor runs two tool calls, the customer sends a new chat message. Where does that message belong in the conversation?
system prompt of the next request, with the tool results left unchangedtool_result blocks come first. Holding application events until the round trip resolves keeps the transcript valid; moving customer text into the system prompt gives it an authority it should not have.References
- Anthropic, Handle tool calls
- Anthropic, Stop reasons and fallback
- Anthropic, Parallel tool use
- Anthropic, Tool use with Claude
- Anthropic, Using the Messages API