The Six Scenarios β Worked Walkthroughs
The official CCAR-F exam guide lists six scenario contexts. The exam takes its questions from these contexts. This list is the public blueprint, and it helps you a lot: if you study the contexts, then on exam day you recognize the situation instead of guessing. Everything below is original study material built on that public blueprint. For each context you get a reference architecture, the decisions it tests, and the wrong-answer patterns to watch for. Nothing on this page is remembered, copied or rebuilt from real exam questions.
π§ How to read a scenario like an architect: the five-question actor test. For every question stem below (and on the exam), silently ask the same five questions, one per domain: Who decides? (the model proposes; the harness executes, Domain 1) Β· Who runs it? (the model chooses, the harness runs, Domain 2) Β· Who guarantees it? (the prompt only persuades / the API enforces / the harness validates, Domain 3) Β· Whose process executes? (your dispatcher / an MCP server / Anthropic infrastructure, Domain 4) Β· Who manages the memory? (hard limits vs choosing what goes into context, Domain 5). Sometimes two answer options both βworkβ. Then the most appropriate one is almost always the option that gives each action to the correct actor.
S1 Β· Customer support agent (Agent SDK + MCP + escalation)
flowchart LR
U[Customer chat] --> A[Agent SDK loop]
A --> M1[MCP: CRM server]
A --> M2[MCP: billing server]
A --> G{Harness gates: confidence Β· allowlist Β· risk}
G -->|high-risk or low-confidence| E[Escalate: ticket + context packet + human]
G -->|ok| ACT[Tool action] --> R[Reply from approved templates]What it tests: when to escalate to a human (confidence is below a minimum; the request is out of scope, meaning outside the job this agent was built for; a system it depends on is down; the user asks for a human). Also: an allowlist of tools per category; treating MCP tool results as untrusted; summarizing the conversation state in long sessions; idempotent side effects (a refund cannot run twice); and honest, reduced service when a backend is down.
πͺ€ Planted trap: "add a prompt instruction so it never issues refunds over $50". This is wrong. The limit belongs in a harness gate (code in your application), and refunds above the limit need HITL (human-in-the-loop) approval.
S2 Β· Claude Code for team code generation
What it tests: what belongs in the project CLAUDE.md (shared conventions, build and test commands) and what belongs in user memory; slash commands for prompts you repeat with different parameters; skills for procedures; hooks (a PostToolUse hook formats a file after each write; a PreToolUse guard checks dangerous Bash commands before they run); settings precedence (enterprise > project > user); permission allowlists; and a .mcp.json file checked into the repo for servers the whole team shares.
πͺ€ Planted trap: enforcing standards with memory instructions, when a hook is the mechanism that guarantees them.
π See it run β one "add an endpoint" request through the team setup
Entry point: a developer types "add a DELETE /invoices/:id endpoint."
- Claude Code (the harness) loads the project
CLAUDE.md. Its shared conventions say that every new endpoint needs a schema, a unit test and a docs entry. - Claude Code calls the Claude API. The model returns an Edit that writes
src/api/invoices.ts. - When Claude Code applies the Edit, the
PostToolUsehook (matcher: Write|Edit) fires. Prettier reformats the file in a deterministic way (same input, same output) and uses no model tokens. - Next, the model proposes
Bash(rm -rf build). ThePreToolUseguard checks the command and finds a banned pattern, so it exits with code 2. Claude Code blocks the action and sends the reason back to the model. - The model changes its plan to
npm run build. That command is on the permission allowlist, so it runs. - Settings precedence (enterprise > project > user) decided every gate above. So the developer cannot quietly weaken the guard in local settings. The hook, not a memory instruction, is what guaranteed the formatting and the safety check.
S3 Β· Multi-agent research system (coordinator + subagents)
flowchart TD C[Coordinator: plan Β· decompose Β· synthesize] --> S1a[Subagent: source search] C --> S2a[Subagent: deep read] C --> S3a[Subagent: verify claims] S1a & S2a & S3a --> C
What it tests: why to use subagents (each one gets its own separate context); what a subagent sends back to the coordinator (short findings, not full transcripts); reading in parallel but writing one at a time; a hub-and-spoke shape (all workers report to one coordinator) instead of workers talking directly to each other; how cost and latency multiply with more agents; when one agent is enough; and checking by a judge. A judge is a second, separately calibrated model that checks the answer. Its result is only one signal: you still verify factual claims against sources or with deterministic checks.
πͺ€ Planted trap: letting all workers share one context window. Separate windows are the whole reason to use workers.
S4 Β· Developer productivity tooling (built-ins + MCP)
What it tests: what each built-in tool does: Read/Write/Edit (file operations), Bash (powerful, so it needs a gate), Grep/Glob (read-only search); giving Bash narrow permissions (Bash(npm run test:*)); when to add an MCP server and when to run a shell command instead; headless runs inside scripts; and sandbox / least-privilege thinking (give only the access the task needs).
πͺ€ Planted trap: granting blanket
Bash(*), when scoped allowlists are the answer the exam expects.
π See it run β "fix the failing auth test" through the built-in tools
Entry point: a developer says "run the auth tests and fix the one that fails."
- Claude Code uses Grep/Glob (read-only search) to find the test file. There is no permission prompt, because these tools cannot change anything.
- Read loads the failing test and the source code it tests.
- The model proposes
Bash(npm run test:auth). The harness compares it with the allowlistBash(npm run test:*). It matches, so it runs. Nobody ever granted blanketBash(*). - The failing output comes back as a
tool_result. The model proposes an Edit tosrc/auth.ts, and the ruleEdit(src/**)allows it. - Claude Code runs the scoped test command again, and the test passes.
- A side request to Read
.envfor a secret is denied by theRead(.env*)rule, so least privilege holds. The scoped allowlist sent the run down the safe path. With the blanket-Bash trap, the model would have had the whole shell.
S5 Β· Claude Code in CI/CD
flowchart LR
PR[Pull request] --> GH[GitHub Action]
GH --> CC[claude -p headless Β· stream-json]
CC --> REV[Review comments / suggested edits]
REV --> GATE{Blocking?}
GATE -->|deterministic checks: tests, lint| BLOCK[Fail the check]
GATE -->|advisory: AI review| COMMENT[PR comment]What it tests: headless mode and output formats; least-privilege tokens; pinning the model version and the action version; advisory gates vs blocking gates (block only on deterministic criteria); a budget limit per run; audit logging; and hooks inside CI that guarantee formatting and tests.
πͺ€ Planted trap: making the AI review a blocking gate. The exam's rule: block on deterministic checks, and only advise on judgment.
π See it run β one pull request through the pipeline
Entry point: a developer opens a pull request. The event triggers the GitHub Action.
- The runner starts
claude -pin headless mode with--output-format stream-json. It uses a least-privilege token that only works for this repo. - The harness calls the Claude API. The model reviews the diff and returns its findings as JSON.
- The Action reads that JSON and posts it as a PR comment. The comment is only advice; it never blocks the merge.
- At the same time, the deterministic gate runs the tests and lint.
- The
Blocking?branch reacts to deterministic results only: if tests fail, the check fails and the merge is held. The AI review stays a comment. --max-turnslimited the run, so a loop could not quietly use up the budget. The pinned model and action versions made the run reproducible. Every step was written to the audit log.
S6 Β· Structured data extraction (JSON-schema validated)
What it tests: the structured-output ladder (JSON asked for in the prompt β prefill β schema as a forced tool β validate-and-repair loop); checking stop_reason before parsing; additionalProperties: false; low temperature; the batch API for large volume; eval sets that measure accuracy per field; and documents that are larger than the context window (split at document boundaries, extract from each chunk, then merge in a deterministic way).
πͺ€ Planted trap: "sometimes the JSON is cut off". The cause is
max_tokenstruncation, not a prompting problem.
π See it run β one invoice through the extraction ladder
Entry point: a nightly job sends the text of one invoice to the Claude API. The extraction schema is set up as a forced tool, and temperature is 0 so the output is repeatable.
- The model returns a
tool_useblock. The schema limits the shape of its arguments (additionalProperties: false, so no extra fields). - The harness checks
stop_reasonbefore it parses.tool_usemeans the output is complete. If the value weremax_tokens, the JSON would be truncated. The fix is to raisemax_tokensand retry, not to reword the prompt. - Next, your application validates the parsed object: field types and business rules. A result can match the schema and still break a business rule.
- An invoice larger than the context window is split at document boundaries. The model extracts each chunk. Then your code merges the results deterministically, with no model in the merge step.
- The volume path: 10,000 invoices go through the batch API at lower cost. Before you trust the run, you score accuracy per field against an eval set.
π― The pattern across all six: find where the deterministic boundary should be. Every scenario contains at least one question of this kind. The wrong answers move enforcement into the prompt. The right answer moves it into the harness (gates, hooks, schemas, allowlists, budgets).