Skip to content
zeeshare.com

writing / CCAR-F journey

Claude certification journey, from a backend engineer's seat

Claude Agent SDKPart 1

The agent loop is just a while loop

6 min readdomain-1
Exam domain 1Agentic architecture and orchestration27% of the exam
On this page
  1. Where this fits in the exam
  2. An agent is a loop with one decision in it
  3. Four wrong ways to stop the loop
  4. The tool_use_id rule
  5. Who decides whether a tool may run
  6. The six permission modes
  7. Two kinds of “why did it stop”
  8. What I actually ran
  9. What I’d tell another engineer
  10. Sources

In short: An agent is a loop with one decision in it. Every reply carries a stop_reason. tool_use means run the tool, hand the result back and call again. end_turn means the model is done. This is Part 1 of my CCAR-F study log, and it covers the start of Domain 1.

I’m a backend engineer with 8+ years behind me, studying for the CCAR-F exam so I can work as a Forward Deployed Engineer. This series is my study log. I’m writing it as I go, mistakes included, so that the next engineer on this road has a map.

Part 1 is the foundation. Everything after it sits on top of what’s here.

Where this fits in the exam

CCAR-F has five domains. Pass mark is 720 out of 1000, with no minimum per domain.

Domain
1. Agentic Architecture & Orchestration
2. Tool Design & MCP
3. Claude Code Configuration & Workflows
4. Prompt Engineering & Structured Output
5. Context Management & Reliability

Domain 1 is the biggest slice, and the agent loop is its first task. That is why I’m starting here.

An agent is a loop with one decision in it

You send the model a request. The response carries a field called stop_reason. That field tells your code what to do next:

  • tool_use: the model wants a tool run. Run it, hand the result back, call again.
  • end_turn: the model is done.

That’s the whole control flow. The SDK normally hides it. The course makes you write it by hand first, about fifteen lines, so you know what the SDK is doing for you later.

The loop from this section: one decision, two outcomes

Backend analogy (mine): it’s a worker polling a queue. tool_use means “there’s a job, do it and ack it.” end_turn means “queue’s empty, exit.”

Four wrong ways to stop the loop

The course lists these because they show up in real codebases, and the exam offers them as wrong answers:

  1. Reading the text for a word like “DONE” or judging whether it sounds finished.
  2. Treating “the response contains text” as completion. A model can write text and ask for a tool in the same turn.
  3. Using an iteration cap as the main stopping rule. A cap is a safety net, not the decision.
  4. Not appending tool results to history. If you ran a tool but never returned the result, the model treats it as if it never happened.

QuizA reply contains some text and also asks for a tool. What should the loop do?

Show the answer

Answer: Run the tool, hand the result back and call again

The stop_reason on that reply is tool_use, so there is still a job to do. Text in a reply does not mean the model is done.

The tool_use_id rule

Every tool_use block has an id. Your tool_result must carry that id back.

Backend analogy (mine): it’s a foreign key. A tool result with no matching tool call is an orphan row, and the database (here, the API) rejects it.

The practical rule: before you append your tool result, append the assistant’s own message first, exactly as it came back. Skip that step and the course says you get a 400 error. I have not triggered that error myself yet. I skipped the break-it-on-purpose exercise, so I’ll go back to it.

Who decides whether a tool may run

Three settings that sound alike and aren’t:

  • tools: what the agent can see. The toolbox.
  • allowed_tools: what runs without asking. Pre-approval.
  • disallowed_tools: what is always blocked.

(The toolbox, pre-approval and ban wording is my own way to remember them.)

The six permission modes

A permission mode is one setting for the whole run. It controls how the agent may use tools.

ModeWhat it does
defaultStandard behavior. A call that needs approval and matches no allow rule is sent to your approval callback.
acceptEditsFile edits and filesystem commands inside the working directory are approved automatically.
planThe agent explores and plans. File edits are never approved automatically.
dontAskAnything that would prompt is denied instead. Tools you approved in advance still run.
autoA model classifier reviews actions such as shell commands and allows or blocks each one.
bypassPermissionsTools run without prompts. Deny rules and hooks can still block a call.

The one-line descriptions come from the Agent SDK permissions page, linked under Sources.

Remember: Two modes are worth remembering:

  • dontAsk suits unattended runs, because it denies anything not approved in advance instead of waiting for a human who isn’t there.
  • bypassPermissions belongs only in a sandboxed, non-interactive run, such as a container in CI.

Two kinds of “why did it stop”

stop_reason is about one model reply. terminal_reason is about the whole loop. Values include completed, max_turns, api_error and aborted_tools. When an agent stops earlier than you expected, print terminal_reason first.

What I actually ran

Two scripts, on my Mac, with uv and a small Haiku model.

  • hello_agent.py, with no tools: it finished with stop_reason of end_turn and terminal_reason of completed. I saw both on screen.
  • raw_loop.py, the hand-written loop with a fake weather tool: it made two model calls. The first ended with tool_use, the second with end_turn, and the final answer used the tool’s result correctly.

Then the part I liked most. I built a first version of the chat app on the plain query() call and watched it fail. I asked it a question, then asked what I’d asked before, and it said it had no access to previous conversation history. Each query() call starts a fresh session. That’s the stateless bug, and I confirmed it live before reading the fix. The next piece, a stateful client, is the one I’m running next.

What I’d tell another engineer

  • Learn stop_reason before anything else in the SDK. It’s the one idea everything else hangs on.
  • Predict before you run. Some of my predictions needed a second pass, and that is where the learning happened.
  • If you already write backend code, you don’t need analogies to the cloud. Map it to queues and foreign keys and it clicks fast.

Sources

Next: Part 2, a chat app that remembers.

Series

Claude certification journey, from a backend engineer's seat

  1. Part 1Claude Agent SDKThe agent loop is just a while loopyou are here

This is the latest part. The next one is linked here once it is published.