Deep dive
Claude Certified Architect Exam: A Field Guide to Agent Anti-Patterns
Frank Coyle has taught computer science for over 30 years and now teaches at Berkeley. He walks Anthropic's new Claude Certified Architect exam scenario by scenario — not to sell the certification, but because its six production scenarios encode what Anthropic has learned about how people actually break agents. His method is to name the anti-pattern first, then the fix, on the grounds that knowing what not to do is the shortest path to knowing what to do. What comes out is a compact architecture checklist: loop on stop_reason, keep CLAUDE.md hierarchical, give each sub-agent one job and two tools, fork context for subtasks, and compact before the window fills.
"Anthropic's CCA Exam as a Field-Guide for Agentic Engineering — Frank Coyle, UC Berkeley" by AI Engineer — Watch on YouTube →
Step-by-Step Breakdown
-
Study the anti-patterns, not just the patterns
Coyle's framing comes from the design-patterns movement of the early 1990s: object-oriented programming produced patterns for objects, and it also produced anti-patterns. Agents now have both. On a scenario-based exam, several answers will "work" — identifying the one thing you must not do is usually what isolates the correct choice. The same is true in production.
-
Know what the exam actually is before deciding to care about it
Released in March, so it is new. It is scenario-based, timed and proctored. It is available to companies inside the Anthropic ecosystem; individuals can pay $99 and sit it once every six months. The questions are multiple-choice, but each is built on realistic constraints rather than trivia. Coyle's argument for reading the syllabus even if you never sit the exam: Anthropic sees how people use the system and where it goes wrong, so the domain list is a decent map of what agentic engineering will throw at you.
-
The five domains and their weights
Agentic architecture 27%. Claude Code configuration and workflow 20%. Prompt engineering and structured output (JSON "all over the place"). Tool design and Model Context Protocol integration. Context management and reliability. Six production scenarios exist; the exam randomly selects four, and every question centres on those four.
-
Scenario 1 — a customer-support agent that loops on
stop_reasonThe anti-pattern is to call the model once, take the response back and use it. The pattern is a
whileloop driven bystop_reason. Coyle stresses the reason this structure is necessary: the LLM cannot execute anything. It is a probabilistic next-token predictor, so when you point it at a tool it does not run the tool — it returns the parameters your code needs in order to run it. So the loop calls the model with the message history and the tool definitions, readsstop_reason, and if the reason istool_useit executes the tool itself, feeds the result back as another message, and iterates. When the model stops for any other reason, the loop exits — and that exit is the natural place to score confidence and escalate to a human. -
Treat "ran out of tokens" as a distinct stop reason
The second reason to inspect
stop_reasonrather than just the text: one of the reasons is that the model hit its token limit. You still get a response, but it is based on whatever the model had produced when it was forced to stop. If you do not branch on that, you silently consume a truncated answer as if it were a complete one. -
Scenario 2 — code generation and the three-level CLAUDE.md hierarchy
Claude Code reads a
CLAUDE.mdmarkdown file for the things you want it to know. Coyle relays Anthropic's recommendation of three levels: one at the top level above your project, one inside the project folder, and per-directory files below that. The point is a hierarchy of rules that narrows as you descend, rather than one monolithic file trying to govern everything. -
Scenario 3 — multi-agent research: specialize, don't overload
The anti-pattern is one agent loaded with every tool. Coyle's analogy: you hire a carpenter and he shows up with plumbing, electrical and carpentry tools announcing he can do anything — you probably wanted a carpenter. The rule he draws from functional programming is that a function should do one thing; get each agent down to one job with one or two tools available to it.
-
Give a critic sub-agent only its slice — to avoid groupthink
His worked example is a critic agent that reviews a result. Pass it the claim and the evidence, and deliberately not the reasoning that produced the claim. When agents collaborate with full visibility into each other's thinking they converge — the same way a group at a party talks the one holdout into pizza. Each agent gets its own slice, and the disagreement survives long enough to be useful.
-
Scenario 4 — developer productivity: isolate, fork, compact
Two anti-patterns: letting every subtask dump its full output into the primary thread, and letting context grow unbounded. Context is tokens, tokens are money, and a fuller window also makes the model's answer worse — so a million-token window is not an invitation to fill it. The pattern is a context fork: send the subtask ("scan all the logs for errors") into a separate thread whose tokens and intermediate thinking never re-enter the main context, then merge only the summary back. Alongside that, check your token count and run compaction when it crosses a threshold — his example uses 150,000 tokens.
-
Scenario 5 — Claude Code in CI: never interactive
The anti-pattern is leaving interactive modes on inside a pipeline, where the agent will stop and ask for permission with nobody there to answer. Configure it to run straight through. He pairs this with a cost lever: put your prompts and work through batch processing for 50% lower token cost, with results promised within 24 hours. If the job can wait overnight, batch it.
The stop-reason loop
This is the structure Coyle walks through on screen, expressed as pseudocode — the block boundaries and the branch conditions are his; the identifiers are ours. Adapt to your SDK's actual field names.
while True:
# 1. Call the model with the running message history and the tool definitions.
# The model cannot execute anything — it can only tell you what to execute.
response = model.call(messages, tools)
# 2. Why did the model stop? This is the control signal for the whole loop.
if response.stop_reason == "tool_use":
result = run_tool(response.tool_params) # YOUR code runs the tool
messages.append(result) # feed the result back in
continue # let the model see the outcome
if response.stop_reason == "max_tokens":
# The answer is PARTIAL. Do not treat it as complete.
handle_truncation(response)
break
break
# 3. The loop exit is where a human belongs.
if confidence(response) < threshold:
escalate_to_human(response)
Anti-Patterns & Fixes Covered
Why it happens: It looks like a normal API call, and the model's reply reads like an answer even when it is really a request to run a tool.
Fix: Wrap the call in a loop driven by stop_reason. Execute the tool yourself when the reason is tool_use, append the result, and iterate.
Why it happens: A truncated response still arrives as text and still parses, so nothing visibly fails.
Fix: Branch on the stop reason. If the model ran out of tokens, the content is partial — take action rather than consuming it as a finished answer.
Why it happens: It is the fewest moving parts, and every new capability is one more tool on the same agent.
Fix: Specialize, don't overload — one job per agent, with one or two tools. Coyle frames it as the functional-programming rule that a function should do one thing.
Why it happens: Passing everything along feels like giving the next agent more to work with.
Fix: Pass a critic only the claim and the evidence. Withholding the reasoning is what stops the agents converging on one view.
Why it happens: A large context window makes unbounded growth feel free. It isn't — it costs tokens and degrades the answer.
Fix: Fork the subtask into its own thread and merge back only the summary. Check the token count and compact past a threshold (his example: 150,000).
Why it happens: Interactive permission prompts are the local default, and the pipeline inherits them.
Fix: Configure the run to go straight through without prompting. See our commands reference for the non-interactive flags.
Gotchas & Caveats
- The exam details — $99, once per six months, four of six scenarios — are as of this talk, and a certification released only in March is likely to move. Verify with Anthropic before paying.
- 150,000 tokens is Coyle's illustrative compaction threshold, not a published constant. Pick yours from your own model's window and cost.
- He is explicit that he does not know how Anthropic's compaction is implemented internally — treat it as a black box that shrinks context, not a documented transformation.
- Batch processing trades latency for 50% cost. The 24-hour figure is a ceiling, not a target; don't batch anything a human is waiting on.
- The talk ran into its time limit, so the structured-data-extraction patterns listed on his agenda are never reached.
Key Takeaways
stop_reasonis the control flow of an agent, not diagnostic metadata. Every loop decision — run a tool, escalate to a human, handle a truncated answer — hangs off it.- The model never executes your tools. It returns the parameters; your code executes. Designing as if the model acts is the root of a whole class of bugs.
- CLAUDE.md is meant to be hierarchical — top level, project, directory — not one file trying to govern everything.
- Sub-agent tool scoping is a reliability decision. One job, one or two tools; and withhold reasoning from a critic so it can actually disagree.
- Context discipline has three moves: isolate subtask output, fork context so intermediate thinking never re-enters the main thread, and compact past a token threshold.
- Two cheap wins for pipelines: turn interactive modes off, and batch anything that can wait for 50% off.





