AITraining2U

Programs

Resources

Case Studies

Quick Links

Enquire Now
Starter Domain 1 · Agentic Architecture & Orchestration ~40 min

Build a bare agentic loop from stop_reason

Drive a tool-using agent by hand so the loop stops being magic.

Write the smallest possible agent: one weather tool, one while loop, no framework. You call the Messages API, read stop_reason, and decide what happens next. Everything else in this domain is a variation on the loop you write here — if you can write it from memory, most of Domain 1 becomes readable rather than memorised.

What to build

  1. Define one tool with a JSON Schema input (a get_weather taking a city string is enough).
  2. Send a user message with the tool in the tools array.
  3. Read stop_reason on the response. Branch on it rather than on the text content.
  4. When stop_reason is "tool_use", pull the tool_use block's id, name and input.
  5. Execute the tool locally, then append the assistant turn and a user turn containing a tool_result block whose tool_use_id matches.
  6. Loop back to the API with the full message history. Exit when stop_reason is "end_turn".
  7. Add a max-iterations guard so a misbehaving model cannot loop forever.

Starting point

messages = [{"role": "user", "content": "Weather in Kuala Lumpur?"}]

for _ in range(MAX_TURNS):
    r = client.messages.create(model=MODEL, max_tokens=1024,
                               tools=TOOLS, messages=messages)

    if r.stop_reason != "tool_use":
        break                      # end_turn, max_tokens, stop_sequence, refusal

    messages.append({"role": "assistant", "content": r.content})
    results = []
    for block in r.content:
        if block.type == "tool_use":
            results.append({
                "type": "tool_result",
                "tool_use_id": block.id,        # must match, not just exist
                "content": run_tool(block.name, block.input),
            })
    messages.append({"role": "user", "content": results})

Done when

  • The loop terminates on "end_turn" and never on the presence or absence of text.
  • Every tool_result carries the tool_use_id of the block it answers.
  • The full conversation, including prior tool calls and results, is resent on each turn.
  • An iteration cap exists and is hit cleanly rather than by crashing.
  • You can name all six stop_reason values without looking them up.

If you want to go further

  • Handle stop_reason "max_tokens" distinctly — the turn was truncated, not finished.
  • Log each iteration's token usage and watch the history cost grow turn over turn.

The trap this exercise teaches

Treating the loop as "call model, get answer". The loop is driven by stop_reason, and a tool_use turn is not an error or an edge case — it is the normal path.

Before you start

The theory behind this build is covered in The agentic loop and stop_reason. If any step below is unfamiliar, read that first — the exercise assumes it. Primary source: Claude Docs — Tool use.

Check yourself against the exam

This exercise sits in Domain 1, which is 27% of the CCAR‑F exam. Once you have built it, run a domain drill in the study app and see whether the questions read differently.