Domain 1: Agents and Workflows
14.7% of examDecide between a workflow and an agent architecture
Key Points
- Workflow = LLMs/tools orchestrated through predefined code paths (deterministic, testable); agent = the LLM dynamically directs its own steps and tool use.
- The augmented LLM (model + retrieval + tools + memory) is the base building block both workflows and agents compose.
- Five workflow patterns: prompt chaining, routing, parallelization (sectioning/voting), orchestrator-workers, evaluator-optimizer.
- An agent proper runs an open-ended loop: plan -> call tools -> observe real environment results -> repeat until done or stopped.
- Anthropic's guidance: find the simplest solution first -- agentic autonomy must earn its added cost, latency, and unpredictability.
Decision Rules
When: A task has fixed, known steps that always run in the same order
→Use a workflow (prompt chaining), not an autonomous agent.
When: Input falls into distinguishable categories needing different handling
→Use routing.
When: Independent subtasks are known in advance vs. must be decided by a central LLM at runtime
→Use parallelization sectioning for the former, orchestrator-workers for the latter.
When: Output quality benefits from a critique-and-refine cycle
→Use evaluator-optimizer.
✗ Anti-Patterns to Reject
- Assuming agents always outperform workflows -- Anthropic recommends the simplest solution that works.
- Confusing orchestrator-workers (subtasks decided dynamically at runtime) with parallelization sectioning (subtasks known in advance).
- Treating any multi-step LLM pipeline as "an agent" merely because it has several stages.
Design manager/supervisor and subagent hierarchies
Key Points
- A manager/supervisor agent coordinates specialized subagents; each runs in its own context window and returns only a condensed result.
- Context isolation -- not delegation alone -- is the defining benefit of the subagent pattern.
- Specialization: each subagent can get a focused system prompt, tool set, and optionally its own model tier.
- Parallelism: independent subtasks delegated to subagents can run concurrently.
- Multi-agent hierarchies multiply token usage and add coordination overhead -- reserve them for genuinely separable, heavy tasks.
Decision Rules
When: A subtask requires reading far more material than the final answer needs
→Delegate it to a subagent for context isolation.
When: Subtasks are independent
→Run subagents in parallel for the parallelism benefit.
When: Considering a multi-agent design
→First check whether a single agent or a simpler workflow satisfies the requirement at lower cost and latency.
✗ Anti-Patterns to Reject
- Treating subagents as "just more prompts" instead of valuing their separate context window.
- Reaching for a manager/subagent hierarchy by default rather than only for genuinely separable, heavy tasks.
Construct Claude agents with the Agent SDK, custom loops, and hooks
Key Points
- The Claude Agent SDK provides a managed programmable agent loop, built-in tools, session management, subagents, and hooks.
- A custom loop cycles: send messages -> receive tool_use -> execute tools -> feed back tool_result -> repeat until stop_reason is end_turn.
- Anthropic-hosted/managed deployment lowers operational burden but gives less control; self-hosted maximizes control over data flow, networking, and least privilege at the cost of operating it yourself.
- Hooks (PreToolUse, PostToolUse) are ordinary code callbacks that fire at fixed points -- deterministic, unlike prompt instructions.
- Destructive or high-stakes tool calls belong in a hook, not a system-prompt sentence.
Decision Rules
When: Managed loop mechanics and Anthropic-maintained tooling are sufficient
→Use the Claude Agent SDK rather than hand-rolling the loop.
When: Full control over dispatch, logging, or stopping conditions is required
→Write a custom loop over the Messages API.
When: Data residency and least-privilege requirements are hard constraints
→Choose self-hosted deployment even though it carries more operational burden.
When: A rule must block a destructive or high-stakes tool call
→Enforce it in a PreToolUse or PostToolUse hook, not the system prompt.
✗ Anti-Patterns to Reject
- Putting a safety rule only in the system prompt and calling it a guardrail.
- Assuming "managed/hosted" always wins -- self-hosting is the correct call when data residency or least privilege demand it.
Recognize agent patterns and abstraction frameworks
Key Points
- The tool-use loop is the core agent cycle: model emits tool_use, harness executes, returns tool_result, model continues -- grounded in real environment feedback.
- Memory persists state across turns or sessions (a scratchpad file, an external store), distinct from in-session context-window management.
- Context-window management (pruning, compacting, isolating via subagents) is a continuously applied pattern, not a one-off fix.
- Claude Agent SDK, LangGraph, PydanticAI, and Strands each package these patterns with a different flavor.
- Understand the underlying API calls before adopting a framework -- hidden abstraction layers make debugging harder.
Decision Rules
When: A team wants type-validated, Pydantic-validated structured I/O in Python
→PydanticAI is the natural fit.
When: A task needs graph/state-machine orchestration of nodes and edges
→LangGraph fits.
When: State must survive across sessions, not just turns within one
→Implement memory (a scratchpad/external store), which is distinct from in-session context management.
When: Choosing an abstraction framework
→Pick it for the leverage it provides, not as a substitute for understanding the tool-use loop it wraps.
✗ Anti-Patterns to Reject
- Assuming a framework removes the need to understand the tool-use loop and context management.
- Confusing memory (persisted across sessions) with in-session context-window management.
- Picking a framework by name recognition instead of matching its actual flavor to the requirement.
Domain 2: Applications and Integration
33.1% of examTranslate business requirements into functional and infrastructure requirements
Key Points
- A business requirement translates into functional requirements (what the system must do) and infrastructure requirements (latency, throughput, residency, availability, budget).
- Five extraction questions: latency sensitivity, volume, accuracy/criticality, data sensitivity, and cost ceiling.
- A low-latency, user-facing chat and an overnight bulk-analysis job sit at opposite ends of nearly every one of these axes.
- Solution architecture is driven by the requirement, not by defaulting to the biggest model or the realtime API.
Decision Rules
When: "Cost is the primary concern and results aren't needed until morning"
→Read this as a batch requirement, not a reason to parallelize synchronous calls.
When: A requirement doesn't explicitly name latency, volume, criticality, sensitivity, or cost
→Extract all five before choosing an architecture.
When: Output feeds an automated action vs. a human review step
→Let that criticality difference change the model tier and reliability bar you design for.
✗ Anti-Patterns to Reject
- Defaulting to the biggest model or the realtime API regardless of the stated requirement.
- Treating latency, volume, accuracy, data sensitivity, and cost as independent knobs rather than one coherent profile.
Apply the systems life cycle to Claude applications
Key Points
- Claude applications still follow the standard SDLC: requirements -> design -> implementation -> testing/evaluation -> deployment -> operation -> maintenance.
- Non-deterministic, model-version-dependent behavior means evals with success criteria replace single equality assertions.
- Model-version pinning and regression testing gate every upgrade, not just the initial launch.
- Production monitoring of quality, latency, token cost, and error rate is an ongoing life-cycle activity.
Decision Rules
When: Testing a stochastic Claude output
→Build an eval with success criteria, not a single equality assert.
When: A new model version becomes available
→Re-run evals against the pinned prompt/model pair before adopting it.
When: An application already passed its launch evals
→Keep production monitoring running -- a passing launch eval does not make monitoring optional.
✗ Anti-Patterns to Reject
- Treating testing/evaluation as a single pre-launch gate rather than a recurring activity.
- Assuming a passing eval at launch means monitoring afterward is optional.
Work with the Messages API's core request/response mechanics
Key Points
- A request is a messages list (alternating user/assistant), plus model, required max_tokens, and optional top-level system, tools, temperature, stream.
- The system prompt is a top-level parameter, not a message with role: "system".
- stop_reason (end_turn, max_tokens, stop_sequence, tool_use) tells integration code why generation stopped and what to do next.
- usage reports input_tokens/output_tokens plus cache read/creation tokens -- the basis for cost modeling.
- The API is stateless: it keeps no memory between calls, so the full conversation must be resent every request.
- Streaming (server-sent events) lowers perceived latency without changing total tokens or cost; a tool_use stop_reason requires executing the tool and returning a tool_result; vision uses image content blocks alongside text.
Decision Rules
When: Setting the system prompt
→Use the top-level system parameter, never a role: "system" message.
When: A response's stop_reason is tool_use
→Execute the tool and send a tool_result block in a new user message -- it is not a final answer.
When: Building a multi-turn conversation
→Resend the full conversation on every call; the API retains no memory of prior turns.
When: Deciding whether to stream
→Expect lower perceived latency, not lower cost or fewer total tokens.
✗ Anti-Patterns to Reject
- Believing the system prompt is a role: "system" message.
- Forgetting that max_tokens is required on every request.
- Assuming streaming reduces total token cost.
Apply extended thinking, prompt caching, batch processing, and vendor choice
Key Points
- Extended thinking is an explicit reasoning budget spent before the answer; thinking tokens are billed as output tokens -- not a free upgrade.
- Prompt caching (cache_control) discounts a stable, reused prefix: cache reads are much cheaper, cache writes cost slightly more than normal input; it pays off through reuse.
- The Message Batches API processes many requests asynchronously within 24 hours at a substantial (roughly 50%) per-token discount.
- Realtime (Messages API, often streaming) fits interactive, user-waiting work; batch fits high-volume, cost-sensitive, 24h-tolerant work.
- The same Claude models are available via Amazon Bedrock and Google Vertex AI -- differences are auth, endpoint/region, and model-ID naming, not model behavior.
Decision Rules
When: A workload is high-volume, cost-sensitive, and tolerant of a next-day turnaround
→Use the Message Batches API, not parallelized synchronous calls.
When: Many requests share a long, unchanging prefix
→Mark it with cache_control for prompt caching.
When: A task's reasoning depth genuinely needs it
→Turn on extended thinking and accept the added output tokens and latency.
When: Choosing among the direct API, Amazon Bedrock, and Google Vertex AI
→Decide on cloud footprint, data residency, and procurement, not model behavior differences.
✗ Anti-Patterns to Reject
- "Batch is just parallel realtime calls" -- it is a distinct asynchronous API with its own SLA and discount.
- Applying extended thinking uniformly across a pipeline instead of only to steps that need it.
- Assuming vendor choice (Bedrock vs. Vertex AI vs. direct API) changes model quality.
Apply software-engineering foundations and error handling to Claude integrations
Key Points
- The Claude API is HTTPS + JSON: status codes, headers, request/response shape, idempotency, and pagination apply like any REST service.
- Async/await and concurrency are the right tools for I/O-bound LLM calls; the SDKs ship async clients for exactly this.
- Git branching, PRs, and history are the substrate for reviewing and rolling back prompt/model changes, same as any code change.
- Prompts and model IDs are reviewable, versioned artifacts, not incidental strings exempt from SDLC/code review.
- 429/529/5xx are transient -- retry with exponential backoff and jitter; 400/401 are your bug -- fix and resend, retrying unchanged won't help.
Decision Rules
When: An LLM call is I/O-bound inside a request path
→Use an async client to parallelize it rather than blocking synchronously.
When: A response returns 429 or 529/5xx
→Retry with exponential backoff and jitter.
When: A response returns 400 or 401
→Fix the payload or credentials; retrying unchanged will fail identically.
When: A prompt or model ID changes
→Route it through the same code review and version control as a code change.
✗ Anti-Patterns to Reject
- Applying backoff-and-retry to 400/401 errors.
- Treating prompts and model IDs as "just strings" exempt from code review and version control.
- Retrying without jitter, risking synchronized retry storms across clients.
Match instruction mechanisms to the Claude interface in use
Key Points
- Four interfaces, four distinct instruction mechanisms: API/SDKs (system param + messages/tools/params), claude.ai (chat + Project instructions/knowledge), Claude Desktop (chat + connected MCP servers), Claude Code (CLAUDE.md + settings.json + slash commands).
- Each row is a genuinely different authoring surface, not a stylistic variant of the same thing.
- Instructions don't transfer verbatim across surfaces -- a CLAUDE.md shapes Claude Code, it does not configure a raw Messages API call.
Decision Rules
When: Designing for a raw Messages API integration
→Remember its only instruction channel is the system parameter plus message content -- there is no CLAUDE.md concept there.
When: Designing for Claude Code
→Use CLAUDE.md, settings.json, and slash commands, not API-style system-parameter conventions.
When: A described design says "set up a CLAUDE.md for the chatbot"
→Recognize the wrong instruction mechanism matched to the wrong surface.
✗ Anti-Patterns to Reject
- Assuming instructions transfer verbatim across surfaces (CLAUDE.md does nothing for a raw Messages API call).
- Treating "Claude" as one monolithic product with a single instruction surface.
Design content boundaries, schema output, session hygiene, and plugin management
Key Points
- Content boundaries: keep trusted instructions separate from untrusted data (user input, retrieved documents, tool output); delimit clearly (e.g., XML-style tags).
- Schema design: define a JSON schema and use structured output/tool-forcing for machine-readable output that is strict but not brittle.
- Session hygiene: because the API is stateless and context is finite, deliberately decide what carries forward -- compact long threads, start fresh when polluted, don't let stale tool output accumulate.
- Plugin management: explicitly track which MCP servers/plugins are enabled, their permissions, and their versions.
Decision Rules
When: Untrusted content (user input, retrieved document, tool output) enters the prompt
→Delimit it clearly so it cannot be read as an instruction.
When: Designing a machine-readable output schema
→Make it strict enough to parse reliably but not so rigid it fails on reasonable variation.
When: A session's context becomes polluted with stale or irrelevant history
→Start a fresh session rather than continuing to patch a degraded thread.
When: Connecting plugins/MCP servers
→Track enablement, permissions, and versions explicitly, not as an install-once inventory.
✗ Anti-Patterns to Reject
- Placing unsanitized untrusted text directly in the prompt without delimiting it.
- Treating maximum schema rigidity as strictly safer, when an overly rigid schema fails on legitimate edge cases.
- Continuing to patch a polluted session with more instructions instead of starting fresh.
Manage Claude application configuration as versioned artifacts
Key Points
- CLAUDE.md is project/repo memory for Claude Code and belongs in version control, reviewed like code.
- settings.json is Claude Code's settings surface: permissions, hooks, tool allow/deny lists, environment, model selection, MCP servers.
- Model-version pinning: use an explicit model ID rather than a floating "latest" alias -- a reproducibility hazard.
- Prompt versioning: treat prompts as artifacts with version history so a quality regression can be traced to a specific change.
- Plugin dependencies: track plugin/MCP-server versions like any other software dependency.
Decision Rules
When: A team wants the same coding conventions applied for everyone on a repo
→Commit them to a project-level CLAUDE.md, not each developer's personal ~/.claude/CLAUDE.md.
When: Deploying to production
→Pin an explicit model ID and gate any upgrade behind re-run evaluations.
When: A quality regression appears in production
→Use prompt version history to correlate it to a specific prompt change.
✗ Anti-Patterns to Reject
- Relying on a floating "latest" model alias in production.
- Treating CLAUDE.md as a personal scratch file rather than checked-in, reviewed project memory.
- Treating plugin/MCP-server versions as unimportant background detail.
Domain 3: Claude Code
3.1% of examIdentify Claude Code's core component types
Key Points
- Five component types: Rules (standing conventions, often in CLAUDE.md), Skills (SKILL.md, loaded when relevant), Commands (built-in + custom slash commands in .claude/commands/), Agents (delegated subagents), Agent Memory (persisted context, notably CLAUDE.md).
- Skill vs. Command distinction: Skills load implicitly on relevance; Commands are explicitly invoked by name.
- CLAUDE.md is the primary instance of Agent Memory, not a separate mechanism.
- Built-in slash commands include /clear (reset context), /init (bootstrap CLAUDE.md), /help.
Decision Rules
When: A capability is invoked explicitly by name (/foo)
→It's a Command, whether built-in or custom.
When: A capability loads automatically because Claude judges it relevant to the task
→It's a Skill, defined by a SKILL.md.
When: A subtask is delegated to a focused-role, focused-tool-set helper
→It's an Agent (subagent), not a Command.
✗ Anti-Patterns to Reject
- Confusing Skills with Commands because both are Markdown-authored, reusable instructions -- the distinguishing factor is invocation.
- Treating Agent Memory and CLAUDE.md as two separate mechanisms.
Apply the CLAUDE.md memory hierarchy
Key Points
- CLAUDE.md is auto-loaded project memory, not executable configuration.
- Four hierarchy levels, broadest to most specific: enterprise/system, user (~/.claude/CLAUDE.md), project (./CLAUDE.md), subdirectory.
- More specific files layer on top of broader ones -- they refine, they don't replace.
- Project-level CLAUDE.md is checked into version control so the whole team shares the same guidance.
- /init bootstraps a starter CLAUDE.md from an existing codebase.
Decision Rules
When: A team wants the same conventions applied for everyone on a repo
→Use a project-level CLAUDE.md committed to version control.
When: Bootstrapping CLAUDE.md for an existing repository
→Run /init.
When: Permission rules, hooks, or tool allow/deny lists need a home
→Put them in settings.json, never in CLAUDE.md.
✗ Anti-Patterns to Reject
- Assuming the user-level ~/.claude/CLAUDE.md is what a team shares -- it is personal, not committed to the repo.
- Storing permission rules or hooks in CLAUDE.md.
Configure behavior and permissions via settings.json
Key Points
- settings.json (user: ~/.claude/settings.json, project: .claude/settings.json) configures tool allow/deny lists, hooks, environment variables, model selection, and MCP servers.
- It is the deterministic control surface -- an allow/deny rule or hook blocks a dangerous command regardless of what the model proposes.
- CLAUDE.md is context/memory (probabilistic influence on the model); settings.json is executable configuration (deterministic enforcement).
Decision Rules
When: A rule must block a destructive shell command regardless of model behavior
→Put it in settings.json as a permission rule or hook, not in CLAUDE.md.
When: Configuring tool allow/deny lists, hooks, environment variables, model choice, or MCP servers
→settings.json is the surface, at the correct scope (user vs. project).
✗ Anti-Patterns to Reject
- Putting permission rules, hooks, or tool allow/deny lists in CLAUDE.md.
- Assuming a well-written CLAUDE.md instruction is an adequate substitute for a settings.json permission rule.
Distinguish Claude Code's session and operating-mode features
Key Points
- Session management: conversations persist as resumable sessions; /clear resets context to stay focused.
- Headless mode runs non-interactively (e.g., claude -p) for scripting/CI, with no interactive TUI.
- Streaming mode emits incremental output, including structured stream-JSON, for programmatic consumption.
- Auto-mode is reduced-friction autonomous operation with fewer confirmations -- pair it with settings.json permission rules and hooks.
- Headless mode (interactivity) and auto-mode (autonomy) are independent axes, frequently confused.
- Best-practice loop: gather context -> plan -> act -> verify, tightened with custom commands and hooks rather than long, brittle prompts.
Decision Rules
When: Running Claude Code non-interactively in a CI pipeline
→Use headless mode (e.g., claude -p).
When: Output must be consumed incrementally or programmatically
→Use streaming mode.
When: Using auto-mode
→Pair it with settings.json permission rules and hooks -- never use it unguarded.
✗ Anti-Patterns to Reject
- Confusing headless mode (interactivity) with auto-mode (autonomy) -- they are independent axes.
- Using auto-mode without corresponding permission rules or hooks.
Domain 4: Eval, Testing, and Debugging
2.6% of examIdentify the type of a Claude application error
Key Points
- Five failure buckets: transport/HTTP (429/529/5xx/timeouts), request error (400/401), parsing/validation (code throws reading output), model-output error (well-formed but wrong), tool-loop error (wrong tool/malformed args/result not fed back).
- Three buckets live in the integration layer, one lives in the model's output, tool-loop errors straddle both.
- Core discipline: don't "fix" the prompt when the bug is in your code, and don't patch code when the model output is the problem.
- A JSON parse crash on a 200/end_turn response is an integration-layer parsing bug, not evidence the model is wrong.
Decision Rules
When: Code throws while reading a successful (200 status, end_turn) response
→Classify it as an integration-layer parsing bug and add defensive parsing.
When: Content is well-formed but factually or semantically wrong
→Classify it as a model-output error, not a parsing bug.
When: Classifying any failure
→Identify which of the five buckets it lives in before choosing a fix.
✗ Anti-Patterns to Reject
- "Fixing" the prompt when the bug is actually in the integration code.
- Treating a parsing exception as evidence the model hallucinated.
Isolate integration-layer failures from model-output failures
Key Points
- Reproduce-inspect-localize procedure: reproduce with the exact failing request; inspect the raw response (status, stop_reason, usage, content blocks) before any post-processing; localize by status and content quality.
- Non-2xx status localizes to the integration/transport layer; 2xx-but-throws localizes to parsing/validation; 2xx-and-parses-but-wrong localizes to model output.
- stop_reason: max_tokens means the output was truncated -- a common, easily misdiagnosed cause of "invalid JSON".
- Fix truncation by raising max_tokens, not by rewriting the schema or lowering temperature.
Decision Rules
When: Debugging any failure
→Reproduce with the exact request, then inspect the raw response before any post-processing runs.
When: stop_reason is max_tokens and the JSON looks malformed
→Raise max_tokens; don't redesign the schema or lower temperature.
When: Status is 200 with a clean stop_reason but your code still throws
→Treat it as a bug in your consumer, not evidence the model is wrong.
✗ Anti-Patterns to Reject
- Assuming the model is at fault just because your code raised an exception.
- Rewriting the schema or lowering temperature in response to a truncation-caused parse error.
Use trace analysis to find failure modes in multi-step workflows
Key Points
- A bad final answer in a multi-step agent is usually the end of a chain of steps, not an isolated event.
- Trace analysis: log every model call, tool call, arguments, tool result, and intermediate message, then walk the sequence.
- Look for the earliest deviation, not just the most visible or final one.
- Late-session quality degradation exposed in a trace often points to context bloat/drift, not a model defect.
Decision Rules
When: An agent produces a wrong answer after several steps
→Analyze the trace and find the earliest deviating step rather than only rewording the final prompt.
When: Quality degrades late in a long session
→Check the trace for context bloat or drift before assuming a model limitation.
✗ Anti-Patterns to Reject
- Debugging only the final output of a multi-step agent.
- Fixing only the last step, which often just moves the symptom rather than removing the cause.
Select recovery strategies and verify fixes with evals
Key Points
- Recovery strategy follows diagnosis: retry+backoff for 429/529/5xx; fix-and-resend for 400/401; defensive parsing+reprompt/repair for malformed output; raise max_tokens for truncation; ground-and-constrain for hallucination; graceful degradation/human-in-the-loop when automated recovery can't guarantee correctness.
- Evals close the loop: a representative test set, a scoring method (exact match, graded rubric, or LLM-as-judge), and a target metric.
- Non-deterministic output means a single manual spot-check cannot verify a fix -- only a repeatable eval can, and it also catches future regressions.
Decision Rules
When: A fix has been applied to any Claude-application bug
→Verify it with an eval set and metric, not a single manual re-run.
When: Content is hallucinated
→Ground and constrain (add sources, allow "I don't know", tighten instructions) rather than simply retry.
When: Automated recovery can't guarantee correctness
→Escalate to graceful degradation or human-in-the-loop instead of shipping a wrong answer.
✗ Anti-Patterns to Reject
- Treating "it looks fixed on one example" as verification.
- Applying retry-with-backoff to 400/401 errors instead of fixing the payload or credentials.
Domain 5: Model Selection and Optimization
16.8% of examExplain tokens, context windows, and autoregressive generation
Key Points
- A token is roughly 3-4 characters of English; limits and billing are measured in tokens, not characters or words.
- Generation is autoregressive: the model predicts one next token from everything so far, appends it, and repeats until a stop condition.
- The context window is the max tokens (input + output combined) a model can consider in one request; exceeding it fails the request or forces truncation/summarization.
- The window is one shared budget across system prompt, conversation history, tool definitions, tool results, and the response -- not separate per-category allowances.
Decision Rules
When: Estimating whether a request will fit in the context window
→Sum tokens across system prompt + history + tool defs + tool results + expected response, not just the user's message.
When: Reasoning about a bigger context window
→Recognize it permits more tokens, but does not make tokens cheaper or curation unnecessary.
✗ Anti-Patterns to Reject
- Assuming token counts map cleanly onto word or character counts.
- Assuming tool results have a separate budget from conversation history rather than one pooled budget.
Reason about sampling, non-determinism, thinking modes, and prompting fundamentals
Key Points
- Generation samples from a probability distribution at each step; temperature controls how focused (low) vs. diverse (high) that sampling is.
- Temperature 0 reduces randomness but does NOT guarantee identical output -- LLMs remain non-deterministic.
- Extended thinking is an explicit reasoning budget spent before the answer; adaptive thinking/effort levels vary depth automatically by difficulty -- both cost billed output tokens plus latency.
- Zero-shot, one-shot, and multi-shot/few-shot are the fundamental spectrum of example-based prompting; more examples cost more input tokens.
- Because exact reproducibility is never guaranteed, test with evals, not equality assertions.
Decision Rules
When: Asked whether temperature 0 makes Claude deterministic
→Answer no -- it reduces randomness but does not guarantee identical output.
When: A task's difficulty genuinely benefits from deeper reasoning
→Apply extended or adaptive thinking, accepting the added tokens and latency.
When: Testing an LLM-backed system
→Use evals with success criteria, not exact-match equality asserts.
✗ Anti-Patterns to Reject
- "Temperature 0 makes Claude deterministic."
- "Extended thinking is free and always on."
- Writing tests that assert exact string equality against LLM output.
Distinguish SDKs from raw REST and sync/async/streaming transport
Key Points
- The official Python and TypeScript SDKs are a convenience layer over the REST API (auth, serialization, typed errors, retries, streaming helpers), not a separate protocol.
- Raw HTTPS + JSON calls to the same API are always available as a fallback to the SDK.
- Async clients parallelize independent, I/O-bound calls; sync clients block per call -- this affects wall-clock time, not token cost.
- Streaming (server-sent events) and websockets (bidirectional) are transport/delivery concerns -- they change when/how tokens arrive, not how many are billed.
Decision Rules
When: Several unrelated model calls can run concurrently
→Use the async client rather than awaiting each one sequentially.
When: Asked whether streaming reduces cost
→Answer no -- it only changes delivery timing, not total tokens billed.
When: A realtime/bidirectional integration (e.g., voice) is needed
→Consider websockets rather than one-directional server-sent events.
✗ Anti-Patterns to Reject
- Treating the SDK as a fundamentally different API from REST.
- Assuming a streaming or websocket choice changes token cost or count.
Select among Claude model tiers against quality/latency/cost tradeoffs
Key Points
- Three tiers: Haiku (fastest/cheapest, high-volume/simple tasks), Sonnet (balanced workhorse for most production logic), Opus (most capable, highest cost/latency, hardest reasoning).
- Right-sizing means matching capability to task difficulty and value, not defaulting to the most capable tier "to be safe."
- Quality, latency, and cost trade against each other -- anchor the choice on the specific requirement.
- Mixed-model architectures route cheap steps to Haiku and hard steps to Sonnet/Opus within one workflow.
- A newer model release can change behavior even with an unchanged API contract -- pin the version and re-run evals before upgrading.
Decision Rules
When: A high-volume classification or routing step must be cheap and fast
→Use Haiku, not Opus.
When: A step is the hardest reasoning or highest-value step in a workflow
→Use Opus (or Sonnet if the value doesn't justify Opus's cost).
When: Upgrading production to a new model release
→Re-run evals and pin the version rather than switching immediately.
✗ Anti-Patterns to Reject
- "Always pick the most capable model to be safe" -- wastes cost and latency.
- Assuming a workflow needs one model tier throughout rather than a per-step mixed-model design.
Model token cost and track usage
Key Points
- Input and output tokens are priced differently; output tokens are typically more expensive than input tokens.
- Cache writes and cache reads have their own distinct rates within the overall pricing structure.
- Cost modeling = estimated tokens per request type x per-token price, summed across expected traffic.
- The usage field (input/output/cache tokens) on every response is the instrumentation for tracking real cost and catching bloat.
- Capping max_tokens to a realistic ceiling prevents paying for runaway generations.
Decision Rules
When: Modeling expected cost at scale
→Estimate token volume per request type times the applicable per-token price, summed across expected traffic.
When: Monitoring real spend
→Instrument the usage field on every response rather than relying only on modeled estimates.
When: Setting max_tokens
→Cap it to a realistic output length rather than leaving it unbounded.
✗ Anti-Patterns to Reject
- Assuming input and output tokens are priced the same.
- Treating cost modeling as a one-time estimate rather than something the usage field lets you continuously verify.
Reduce cost and latency with prompt caching and the Message Batches API
Key Points
- cache_control caches a stable, reused prefix; cache reads are heavily discounted, cache writes cost slightly more than normal input -- the savings come from reuse, not the first call.
- Cache checkpointing keeps a long, incrementally-growing prompt mostly cached as new content is appended.
- The Message Batches API gives a roughly 50% per-token discount for asynchronous jobs completed within 24 hours.
- Batching reduces cost, not latency -- it is slower by design; caching and right-sized models reduce both cost and latency.
Decision Rules
When: Many requests share a long, unchanging prefix
→Cache it with cache_control rather than resending or truncating it.
When: A workload is latency-tolerant, high-volume, and cost-sensitive
→Route it to the Message Batches API.
When: Optimizing a latency-sensitive step
→Use caching or a smaller model, not batching -- batching does not improve latency.
✗ Anti-Patterns to Reject
- Assuming batching improves latency because it processes "in bulk."
- Truncating a needed stable document to save tokens instead of caching the full content.
Domain 6: Prompt and Context Engineering
11% of examWrite clear, direct instructions and place system/user content correctly
Key Points
- State the task, constraints, and desired output explicitly -- ambiguity is the top cause of poor output.
- Positive framing ("respond only in JSON matching this schema") steers more reliably than long "don't" lists.
- Durable role, rules, and constraints go in the system prompt; the specific request and per-request data go in the user message.
- Output constraints (exact shape, length, structure) usually belong with the durable rules in the system prompt.
Decision Rules
When: Writing a standing rule that applies to every call
→Put it in the system prompt.
When: Supplying the specific request or data for this particular call
→Put it in the user message.
When: Tempted to add another "don't" to the instructions
→Prefer a positive instruction describing the target output instead.
✗ Anti-Patterns to Reject
- Putting per-request data in the system prompt and stable rules in the user turn.
- "More prohibitions = safer" -- long negative lists steer worse than positive, specific instructions.
Use few-shot examples, delimiters, and iterative refinement
Key Points
- Worked examples (zero-/one-/multi-shot) often lock in format and style more effectively than a paragraph of description.
- With long inputs, place the document first and the key instruction near the end, right before the response.
- XML-style tags and headings separate instructions from data and enable input sanitization.
- Untrusted user/retrieved text must be delimited and sanitized so it isn't read as an instruction -- ties directly to prompt-injection defense.
- Iterative refinement: diagnose the specific gap, change one thing, re-run, compare, and fold recurring lessons into the standing system prompt.
Decision Rules
When: Prose instructions alone don't reliably produce the target format
→Add worked examples instead of more description.
When: Prompting over a long source document
→Place the document first and the key ask near the end of the prompt.
When: Untrusted user or retrieved text enters the prompt
→Wrap it in delimiters and treat it as data, not instruction.
✗ Anti-Patterns to Reject
- Burying the key instruction at the top of a huge document.
- Changing multiple things at once during prompt refinement, making it impossible to attribute a quality change to one edit.
Manage the context window as a shared, finite budget
Key Points
- The context window is one shared budget: system prompt, tool schemas, history, tool results, and retrieved docs all compete for the same space.
- The goal is the smallest set of high-signal tokens that maximizes the odds of the desired outcome.
- Context rot is attention degradation as the window fills with irrelevant or stale content, even with room technically left.
- Context drift is the gradual loss of track of instructions or facts over a long interaction.
- Compaction, pruning, isolation, and re-stating key constraints counter drift -- not temperature or more prohibitions.
Decision Rules
When: A long agent session starts ignoring earlier instructions and quality drops
→Compact older turns and prune stale tool output; don't raise temperature or add prohibitions.
When: Deciding what to include in context
→Prefer the smallest high-signal set over maximizing what's included.
✗ Anti-Patterns to Reject
- "Just use the biggest context window and stuff everything in."
- Reaching for temperature or more prohibitions to fix context rot or drift.
Apply context curation techniques: pruning, compaction, isolation, and retrieval
Key Points
- Tool-output pruning: keep only what later steps need from a large tool payload; drop raw dumps from the ongoing history.
- Compaction: periodically summarize older turns into a compact recap, reclaiming budget while preserving the thread.
- Compaction is not truncation -- truncation blindly drops tokens and can lose critical facts.
- Context isolation: delegate a heavy subtask to a subagent with its own window; it returns a condensed result.
- Just-in-time retrieval: pull information in when needed rather than front-loading everything.
Decision Rules
When: A tool returns a large payload
→Prune it to what later steps need rather than carrying the full dump forward.
When: A session grows long
→Compact older turns into a summary rather than truncating blindly.
When: A subtask requires reading far more than the final answer needs
→Isolate it in a subagent with its own context window.
✗ Anti-Patterns to Reject
- Confusing compaction (preserves meaning) with truncation (blindly drops tokens, can lose critical facts).
- Front-loading an entire knowledge base instead of retrieving just-in-time.
Handle Claude's output defensively
Key Points
- For machine-readable output, use tool use/tool-forcing (a tool whose input schema is the target shape) or structured-output features; prefilling (e.g., "{") can nudge JSON-only output.
- Validate structure AND semantics -- well-formed JSON can still be wrong.
- Defensive parsing: tolerate extra prose, handle truncation (stop_reason: max_tokens), and retry, repair, or fall back on failure.
- Claude can be confidently wrong -- polish and certainty are not evidence of correctness; ground high-stakes claims and keep a human in the loop.
Decision Rules
When: Reliable machine-readable JSON is needed
→Define a schema and use tool-forcing/structured output, then validate the result.
When: A numeric or semantic field looks wrong despite valid JSON structure
→Validate semantics -- don't assume structure implies correctness.
When: Output is truncated (stop_reason: max_tokens)
→Handle it in defensive parsing and raise max_tokens; don't crash the application.
✗ Anti-Patterns to Reject
- Trusting output because it "looks right" or sounds confident.
- Parsing model text with brittle string operations and no error handling.
- Believing temperature 0 alone guarantees valid, parseable JSON.
Domain 7: Security and Safety
8.1% of examDefend against prompt injection, jailbreaks, and untrusted input
Key Points
- Prompt injection hides malicious instructions inside data the model processes (a web page, document, email, or tool result) -- the model cannot inherently distinguish data from instructions.
- A jailbreak is input crafted to bypass safety constraints directly (role-play framing, obfuscation, "developer mode").
- There is no syntactic boundary between instruction and data in natural language, unlike SQL injection -- the fix must be architectural, not linguistic.
- Core mitigations: isolate/delimit untrusted content, apply least privilege on tools, back both with guardrails/hooks, validate input and output.
- A larger, more instruction-following model can be MORE susceptible to injection, not less -- capability is not a security control.
Decision Rules
When: A Claude agent summarizes or consumes untrusted content (web pages, documents, tool results)
→Treat it as untrusted, delimit it, and back it with least-privilege guardrails/hooks.
When: Asked how to mitigate prompt injection
→Reject temperature changes, polite prompt caveats, and "use a bigger model" as non-solutions.
When: An injection might slip through content isolation
→Rely on least privilege to bound the blast radius of whatever it triggers.
✗ Anti-Patterns to Reject
- Raising temperature as an injection mitigation.
- A polite system-prompt request ("don't obey injected instructions") treated as an enforceable control.
- Switching to a larger, more capable model to reduce injection risk.
Prevent PII exposure and data leakage
Key Points
- Minimize PII sent to the model; redact or tokenize sensitive identifiers before they reach it; only send what policy permits.
- Guard against the model or its tools exposing secrets, other users' data, or internal system details.
- Scope tool and data access per user so the agent structurally cannot read data it shouldn't see.
- Never put secrets in prompts or logs -- both are leakage surfaces.
- CIA + privacy (authentication, authorization, confidentiality, privacy, integrity) must hold end to end; the LLM is one component, not a replacement for ordinary security practice.
Decision Rules
When: Sending user data to Claude
→Redact or tokenize PII first and send only what's necessary.
When: Scoping an agent's tool access
→Restrict it so it structurally cannot read data the current user shouldn't see, rather than trusting the model to decline.
When: Writing logs or constructing prompts
→Never place secrets or raw PII inside them.
✗ Anti-Patterns to Reject
- Assuming keeping PII out of the final visible answer is sufficient -- leakage can occur via logs or intermediate tool calls.
- Treating the model itself as the security boundary instead of scoping access at the tool/API layer.
Layer guardrails and enforce hard rules with deterministic hooks
Key Points
- Effective guardrails are multiple independent layers -- input filtering, restricted tool permissions, output validation/moderation, monitoring -- so one layer failing doesn't defeat the system.
- Deployments must respect Anthropic's Usage Policy (AUP).
- Secure-by-design: privacy, identity/access management, and least privilege belong in the design from the start, not bolted on later.
- Hooks (PreToolUse, PostToolUse, stop hooks) are deterministic code callbacks that run every time regardless of the model's decision.
- A prompt instruction is probabilistic; a hook is deterministic -- this is why hooks are the answer for "prevent a destructive action."
Decision Rules
When: Asked what makes guardrails "effective"
→Answer multiple independent layers -- not a single strong system-prompt instruction or the newest model.
When: A rule must block a destructive shell command
→Enforce it in a PreToolUse hook or permission rule, not a prompt sentence.
When: Gating task completion on objective criteria
→Use a stop hook as a verification gate (e.g., a passing test or build).
✗ Anti-Patterns to Reject
- Treating a single strong system-prompt instruction as an effective guardrail.
- Using the newest/largest model as a substitute for layered controls.
- Turning off tools entirely for all tasks instead of scoping them to least privilege.
Manage identity, secrets, and API keys correctly
Key Points
- API keys and secrets belong in environment variables or a secrets manager -- never hard-coded, committed to version control, or pasted into prompts/logs.
- Use separate keys per environment (dev/staging/prod); rotate on a schedule; revoke immediately on exposure.
- Authenticate every request (identity) and separately verify authorization/access level (least privilege) before the agent acts on a caller's behalf.
- Log and monitor authorized and attempted access so misuse is detectable.
Decision Rules
When: Storing an API key
→Use an environment variable or secrets manager, scoped per environment, and rotated on a schedule.
When: An agent is about to act on a caller's behalf
→Verify authorization/access level, not just that the caller authenticated successfully.
When: A key is exposed
→Revoke it immediately rather than waiting for the next scheduled rotation.
✗ Anti-Patterns to Reject
- Hard-coding or committing an API key "for the team."
- Pasting a key into the system prompt.
- Assuming authentication alone (verifying who the caller is) is sufficient without a separate authorization check.
Domain 8: Tools and MCPs
10.6% of examImplement tools and understand the function-calling loop
Key Points
- Tool-use loop: pass a tools array (name, description, input_schema) -> Claude emits a tool_use block (stop_reason "tool_use") -> your code executes it -> return a tool_result matched by tool_use_id -> Claude continues to end_turn.
- Claude never executes a tool itself -- it only requests the call; your application code runs it.
- Tool description quality (what it does, when to use it, what each parameter means) is the single biggest driver of correct tool selection.
- A precise input_schema (types, required fields, enums, per-field descriptions) produces well-formed arguments but doesn't replace a good description.
- Structured errors (an is_error flag or message) let Claude recover or retry instead of guessing; right-size the tool set to avoid overlap and context bloat.
Decision Rules
When: Claude's response has stop_reason "tool_use"
→Execute the tool yourself and return a tool_result block matched by tool_use_id.
When: Claude keeps picking the wrong tool
→Improve the tool's description first, not just the schema or the temperature.
When: Designing the tool catalog for an agent
→Keep it focused and non-overlapping rather than maximizing the number of tools offered.
When: A tool call fails
→Return a structured, informative error so Claude can recover or retry intelligently.
✗ Anti-Patterns to Reject
- "Claude executes the tool" -- it only requests the call; your code runs it.
- Forgetting to feed the tool_result back with the matching tool_use_id.
- Assuming more tools or a bigger catalog is strictly better.
Understand MCP servers, their primitives, and transports
Key Points
- MCP (Model Context Protocol) is an open standard ("a USB-C port for AI") for connecting AI applications to external systems; build once, reuse across any MCP-compatible client.
- Three core primitives: tools (model-callable actions), resources (readable data/content loaded into context), and prompts (reusable parameterized templates) -- not just tools.
- The client lives inside the AI application and connects to one or more servers; each server advertises and handles its own tools/resources/prompts.
- Transports: stdio (local subprocess, single-user) vs. Streamable HTTP/sockets (remote, multi-client).
- Canonical use case: a capability that must be reusable across multiple Claude applications and maintained independently.
Decision Rules
When: A capability (e.g., an internal REST service) must be reusable across multiple Claude apps and maintained independently
→Build an MCP server, not app-local integration logic.
When: Asked what MCP exposes
→Answer tools, resources, AND prompts -- not just tools.
When: The deployment is a local, single-user integration
→Use stdio; for a remote/shared service serving multiple clients, use Streamable HTTP/sockets.
✗ Anti-Patterns to Reject
- "MCP only exposes tools."
- Hard-coding integration logic into each app's prompt instead of building a shared MCP server.
- Picking HTTP/sockets for a local, single-user subprocess scenario, or vice versa.
Choose the right agentic customization mechanism
Key Points
- Four mechanisms: built-in tools (Anthropic-provided, least effort), custom tools (app-specific logic living with one app), Skills (packaged instructions/procedures via SKILL.md, no running service), MCP servers (reusable across apps, independently maintained).
- Selection heuristic: does a built-in already do it? Use it. App-specific? Custom tool. Reusable know-how, no service needed? Skill. Shared across apps, independently maintained? MCP server.
- Built-in tools have fixed capabilities and cannot automatically reach an arbitrary internal API.
Decision Rules
When: The capability already exists as a built-in (web search, code execution, computer use)
→Use it rather than rebuilding it.
When: A capability is app-specific and lives with one application
→Build a custom tool.
When: The need is reusable knowledge/procedure with no running service required
→Package it as a Skill, not an MCP server.
When: A capability must be reused across multiple apps and maintained independently
→Build an MCP server, not an app-local custom tool.
✗ Anti-Patterns to Reject
- "A built-in tool can reach any internal REST API."
- Confusing a Skill (packaged instructions) with a deployed service.
- Standing up an MCP server for reusable knowledge that needs no running service -- that's over-engineering; it's the Skill sweet spot.