TimoBy Amotion AI

Agentic loops: CCAR-F task statement 1.1

CCAR-F · Agentic Architecture & Orchestration (27% of the exam)

Task statement 1.1 sits in Agentic Architecture & Orchestration, the largest CCAR-F domain at 27% of the exam. It tests whether you can build the loop that lets Claude call tools, read the results and decide what to do next until the task is finished.

What the official guide covers

The Claude Certified Architect Foundations exam guide (version 1.0, effective July 2026) lists this under task statement 1.1, "Design and implement agentic loops for autonomous task execution":

Knowledge ofSkills in
The loop lifecycle: send a request, inspect stop_reason ("tool_use" or "end_turn"), run the requested tools, return the resultsContinuing the loop when stop_reason is "tool_use" and stopping when it is "end_turn"
How tool results are added to the conversation history so Claude can reason about the next stepAdding tool results to the conversation between iterations
The difference between model-driven decisions and fixed decision trees or tool sequencesAvoiding anti-patterns: parsing Claude's text to decide when to stop, using an iteration cap as the main stop rule, treating any text reply as "done"

How the loop works

  1. Send the user's request, the system prompt and the tool definitions to the Messages API.
  2. Read stop_reason on the response.
  3. If it is "tool_use", the response contains one or more tool_use blocks. Run each tool in your own code.
  4. Append Claude's response to the conversation, then add one user message that holds a tool_result block for every tool_use block. Each result carries the matching tool_use_id.
  5. Send the updated conversation back and repeat from step 2.
  6. If it is "end_turn", Claude has finished. Use the response.
while True:
    response = client.messages.create(model=MODEL, max_tokens=4096, tools=TOOLS, messages=messages)
    messages.append({"role": "assistant", "content": response.content})
    if response.stop_reason == "end_turn":
        break                                   # the task is finished
    if response.stop_reason == "pause_turn":
        continue                                # server tool paused: send the turn back as it is
    if response.stop_reason != "tool_use":      # max_tokens, refusal, stop_sequence, context full
        raise RuntimeError(f"Loop stopped early: {response.stop_reason}")  # handle per the table below
    results = [run_tool(block) for block in response.content if block.type == "tool_use"]
    messages.append({"role": "user", "content": results})   # all tool_result blocks, one message

The loop exits normally only on end_turn. Every other stop reason gets its own handling, set out in the table below. Claude chooses which tool to call next from what it has learned so far. Your code decides nothing about the order. That is the model-driven decision-making the guide refers to.

Rules that decide exam answers

  • Stop on stop_reason, not on text. A reply such as "I'll check the order now" is not a stop signal. Only "end_turn" means the task is finished.
  • Return every result in one message. When Claude calls several tools in one response, send all the tool_result blocks together in the next user message. Separate messages break the format and make Claude call tools one at a time.
  • Results come first. In the user message, tool_result blocks must come before any text. Nothing may sit between the assistant's tool call and the user's results.
  • Report failures as results. If a tool fails, return a tool_result with is_error: true and a clear message. Claude can then correct the input and try again.
  • An iteration cap is a safety net, not the stop rule. Keep a cap to catch runaway loops, but the normal exit is "end_turn".

What to do with each stop_reason

stop_reasonWhat it meansWhat the loop should do
tool_useClaude is calling one or more toolsRun them, return every result, continue
end_turnClaude has finishedUse the response and exit
max_tokensThe reply hit your token limitRaise the limit or continue; a cut-off tool call must be retried with a higher limit
pause_turnA server-tool loop reached its iteration limitSend the response back as it is to continue
refusalClaude declined to respondRead stop_details; do not treat it as success
stop_sequenceOne of your stop sequences firedCheck which one and handle it
model_context_window_exceededThe conversation filled the model's context windowUse what was returned, then trim or summarise the history before continuing

Agent loop or fixed workflow?

The exam also tests when not to use an agentic loop. Anthropic separates workflows, where your code fixes the order of steps, from agents, where Claude decides the next step from what it has learned.

SituationBetter choiceWhy
The steps are known and always run in the same orderFixed workflowCheaper, faster and easier to test
The next step depends on what a tool returnsAgentic loopClaude chooses the next tool from the results
A step must happen every time, such as a compliance checkWorkflow step or hook, not a prompt instructionCode guarantees it; Claude's choice does not

Where it appears in the exam

Domain 1 is a primary domain in three of the six exam scenarios: Customer Support Resolution Agent, Multi-Agent Research System and Developer Productivity with Claude. Four scenarios are drawn for each exam, so expect loop questions in most sittings.

Two sample questions

These are original Timo practice questions. They are not official exam questions.

Question 1

A support agent built on the Messages API sometimes stops before it has looked up the customer's order. The loop exits when Claude's reply contains no question mark. In the failed cases, Claude's last reply was "I'll look up your order now." What should the team change?

Answer: B. The loop must follow stop_reason. The reply that ended the loop was a tool call in progress, so stop_reason was "tool_use". A and D still decide from the wrong signal, and C relies on wording that Claude may not produce.

Question 2

Claude returns one response with two tool_use blocks: get_order and get_refund_policy. How should the application return the results?

Answer: C. Every tool_use block needs a tool_result with the same tool_use_id, all in the next user message, with results before any text. A splits the results, B puts text first, and D leaves a tool call unanswered, which the API rejects.

Build exercise

Build a loop with two tools, get_order and get_refund_policy, against the Messages API.

  1. Log stop_reason on every iteration and confirm the loop exits only on end_turn.
  2. Ask a question that needs both tools and check that Claude calls them in one response and that you return both results in one user message.
  3. Make get_order fail for one order ID and return is_error: true with a clear message. Watch Claude correct the input and retry.
  4. Add an iteration cap of 10 and log a warning if it is ever reached. If it is, find the cause instead of raising the cap.

Practise this topic

Sources