Not all complex tasks should be decomposed the same way. Prompt chaining works when you know the steps in advance โ a fixed pipeline where each stage feeds the next. Dynamic adaptive decomposition works when you don't โ where each step's output determines what comes next. The exam tests your ability to choose the right pattern for the scenario, and to apply the code-review-specific technique of per-file local passes + cross-file integration pass to avoid attention dilution.
The Architect receives a blueprint before groundbreaking. They know: pour foundation โ frame walls โ install plumbing โ electrical โ drywall โ finish. Every step is defined before the first shovel breaks ground. This is prompt chaining โ you know the decomposition upfront, each stage feeds the next in a fixed order, and the plan doesn't change based on what you find inside the walls.
The Explorer enters an unmapped cave. They don't know what's inside. They map the entrance chamber first โ discover a passage leading left โ explore that passage โ find a branching junction โ decide to send a scout right โ based on the scout's report, decide to focus on the left tunnel. Each step's result determines the next plan. This is dynamic adaptive decomposition โ the workflow shape emerges from what is discovered.
Code reviews are the Architect. You always need to check security, performance, correctness, and style โ the four categories don't change based on the code. Adding tests to an unfamiliar legacy codebase is the Explorer โ you must first understand what's there before you can plan what to build.
| Dimension | Prompt Chaining (Fixed Pipeline) | Dynamic Adaptive Decomposition |
|---|---|---|
| When steps are known | Yes โ before execution starts | No โ determined by intermediate findings |
| Workflow shape | Linear or parallel, pre-defined | Tree-shaped, emergent |
| Typical use case | Code reviews, document processing, multi-aspect analysis | Open-ended investigation, legacy codebase exploration, research |
| AI Fluency 4D Parallel | Heavy emphasis on Diligence (executing fixed steps perfectly) | Heavy emphasis on Description (understanding the unknown before acting) |
| Subtask generation | Hardcoded in pipeline definition | Generated dynamically from findings at each step |
| Exam scenario | Code review tool (Scenario 4) | Add comprehensive tests to legacy codebase (Scenario 4) |
| Failure mode | Rigidity โ can't adapt if something unexpected found | Loss of control โ may spiral into unbounded exploration |
When an exam question asks you to choose a decomposition strategy, the key signal is: "Is the structure of the task known before execution begins?" If yes โ prompt chaining. If the structure only becomes clear as you investigate โ dynamic adaptive decomposition. A code review is always prompt chaining (same aspects every time). "Explore this codebase and find all security vulnerabilities" is dynamic (you don't know what you'll find).
Prompt chaining breaks a complex task into a predetermined sequence of focused stages. Each stage produces output that becomes the input for the next. Claude sees a smaller, well-scoped problem at each step rather than the full complexity at once.
A multi-file code review is the canonical prompt chaining example. The structure is always the same: analyze each file individually (local passes), then run a cross-file integration analysis (global pass). This structure is defined before any code is seen.
import anthropic import asyncio client = anthropic.Anthropic() async def review_single_file(filename: str, content: str) -> dict: """PHASE 1: Per-file local analysis pass.""" response = client.messages.create( model="claude-opus-4-5", max_tokens=4096, messages=[{ "role": "user", "content": f"""Review this file for LOCAL issues only. Do NOT attempt cross-file analysis โ focus strictly on this file. File: {filename} ```python {content} ``` Return JSON with: - security_issues: list of {{issue, severity, line}} - logic_errors: list of {{issue, description, line}} - performance_issues: list of {{issue, impact, line}} - summary: one-paragraph overview""" }] ) return {"file": filename, "findings": response.content[0].text} async def run_integration_pass(per_file_results: list[dict]) -> str: """PHASE 2: Cross-file integration analysis.""" findings_text = "\n\n".join([ f"=== {r['file']} ===\n{r['findings']}" for r in per_file_results ]) response = client.messages.create( model="claude-opus-4-5", max_tokens=4096, messages=[{ "role": "user", "content": f"""You are given per-file analysis results for a codebase. Identify CROSS-FILE issues that individual analysis missed: {findings_text} Identify: 1. Data flow issues (data from File A passed unsafely to File B) 2. Inconsistent error handling conventions across files 3. Dependency conflicts (circular imports, version mismatches) 4. Cross-file security vulnerabilities (e.g. auth bypass via APIโDB path) 5. Contradictory findings (File A says X is safe; File B shows it isn't) Return structured JSON with cross_file_issues[] and synthesis_summary.""" }] ) return response.content[0].text async def code_review_pipeline(files: dict[str, str]) -> dict: """Full prompt-chaining code review: local passes โ integration pass.""" # PHASE 1: Run all per-file analyses in PARALLEL per_file_tasks = [ review_single_file(fname, content) for fname, content in files.items() ] per_file_results = await asyncio.gather(*per_file_tasks) # PHASE 2: Integration pass uses per-file results as input integration_findings = await run_integration_pass(per_file_results) return { "per_file_findings": per_file_results, "integration_findings": integration_findings }
Attention dilution occurs when a model reviews many files simultaneously in a single large prompt. The model reliably processes content at the beginning and end of a long input โ but findings from middle sections are systematically under-represented or missed entirely. This is the "lost in the middle" effect applied to code review.
Sending 8 files in a single 40,000-token prompt. Claude reviews auth.py well (start), db.py well (end), but api.py (middle) gets shallow analysis. The model's "attention" โ its ability to focus on specific content โ is diluted across too many concerns simultaneously.
Each file gets its own dedicated API call with focused instructions: "Analyze THIS file for local issues only." The model's full attention goes to one file at a time. Then a separate integration pass synthesizes cross-file findings from the per-file results.
Per-file passes only catch local bugs โ issues within a single file. Critical cross-file vulnerabilities are invisible to local-only analysis: an authentication bypass requires seeing both auth.py AND api.py's call patterns together; a data flow security issue requires tracing data from ingestion through processing to storage across multiple files. The integration pass is not optional for production code review.
Add explicit instructions in per-file passes: "Do NOT attempt cross-file analysis. Focus strictly on this file." Without this, Claude may try to reason about imports, dependencies, or callers it can't see โ producing speculative findings that aren't grounded in actual code. Scope restriction focuses each pass and prevents hallucinated cross-file guesses.
Dynamic adaptive decomposition lets the workflow shape emerge from what is discovered at each step. Instead of a fixed pipeline, the agent generates the next set of subtasks based on intermediate findings. This is the correct pattern for open-ended investigation tasks where the problem structure is unknown before exploration begins.
First, understand the structure of the problem space. For a codebase: read directory trees, list modules, identify entry points. Produce a structural map before planning what to investigate.
Based on the map, rank areas by impact. For test coverage: find modules with no tests, highest cyclomatic complexity, or most dependencies. This drives prioritization.
Create a prioritized plan from step 2. Crucially: this plan may change as you execute it. Discovering an unexpected dependency in module A may reprioritize or introduce module B into the plan.
Execute subtasks. At each step, check if findings change the remaining plan. A discovered circular dependency might require rerouting the testing strategy for multiple modules.
The exam guide's specific open-ended example is: "add comprehensive tests to a legacy codebase." This is a three-phase adaptive process where each phase's output determines the next phase's plan.
The exam guide states: "Decomposing open-ended tasks (e.g., 'add comprehensive tests to a legacy codebase') by first mapping structure, identifying high-impact areas, then creating a prioritized plan that adapts as dependencies are discovered."
These three bolded concepts โ map structure, identify high-impact, prioritized plan adapts โ are the exact language you need to match in answers.
import anthropic import json client = anthropic.Anthropic() def add_tests_to_legacy_codebase(repo_path: str): """Dynamic adaptive decomposition for open-ended test generation task.""" # โโโ PHASE 1: MAP STRUCTURE โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ # Don't plan yet โ discover first. The structure is unknown. mapping_response = client.messages.create( model="claude-opus-4-5", max_tokens=4096, messages=[{ "role": "user", "content": f"""Map the structure of this codebase at: {repo_path} Use the file system tools to explore. Produce a structural map containing: - Complete module list with file counts - Modules with ZERO test coverage (critical) - Modules with partial coverage - Dependency relationships between modules - Entry points and critical paths Return as JSON. Do NOT write any tests yet โ mapping only.""" }], tools=[/* file system tools */] ) codebase_map = json.loads(mapping_response.content[0].text) # โโโ PHASE 2: IDENTIFY HIGH-IMPACT AREAS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ # Based on map, rank modules by impact before planning any tests. prioritization_response = client.messages.create( model="claude-opus-4-5", max_tokens=2048, messages=[{ "role": "user", "content": f"""Given this codebase structure: {json.dumps(codebase_map, indent=2)} Identify and rank the TOP 5 modules to test first, based on: 1. Zero current coverage (highest priority) 2. Critical path modules (payment, auth, data processing) 3. High dependency count (testing these blocks others) 4. Complexity (harder to test = more value in doing it right) Return prioritized list with rationale for each. Do NOT write tests yet.""" }] ) priority_modules = json.loads(prioritization_response.content[0].text) # โโโ PHASE 3: ADAPTIVE EXECUTION โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ # Generate tests for each priority module โ plan adapts as dependencies found. generated_tests = [] discovered_dependencies = [] # Grows as we explore for module in priority_modules["ranked_modules"]: test_response = client.messages.create( model="claude-opus-4-5", max_tokens=8096, messages=[{ "role": "user", "content": f"""Generate comprehensive tests for: {module['name']} Previously discovered dependencies (must mock these): {json.dumps(discovered_dependencies, indent=2)} If you discover NEW dependencies during test generation, report them in a 'new_dependencies' field โ they will be added to the remaining testing plan. Write pytest tests covering: happy path, edge cases, error conditions.""" }], tools=[/* file read tools */] ) result = json.loads(test_response.content[0].text) generated_tests.append(result["tests"]) # KEY: Plan adapts as new dependencies are discovered if result.get("new_dependencies"): discovered_dependencies.extend(result["new_dependencies"]) # These may be added to priority_modules for subsequent iterations return generated_tests
When generating tests for payment.py, the agent discovers it calls legacy_db.py which has its own untested logic. A fixed pipeline would miss this โ it only tests what was planned upfront. The adaptive plan adds legacy_db.py to the test queue because it was discovered, not because it was pre-planned. This is the core value of adaptive decomposition: it handles unknown unknowns.
| Signal in the Task Description | Pattern to Use | Reasoning |
|---|---|---|
| "Review this code for security, performance, and correctness" | Prompt Chaining | Review aspects are known upfront. Same 3 categories regardless of code content. |
| "Add comprehensive tests to this legacy codebase" | Dynamic Adaptive | Test targets determined by what's discovered in the codebase structure. |
| "Analyze each file in this PR for quality issues" | Prompt Chaining | Per-file passes are well-defined; integration pass is predictable. |
| "Investigate why this production system is slow" | Dynamic Adaptive | Investigation path depends entirely on what profiling and logs reveal. |
| "Generate a report covering legal, financial, and technical risk" | Prompt Chaining | Three defined dimensions. Sequential pipeline: legal โ financial โ technical โ synthesis. |
| "Refactor this deprecated API to use the new authentication system" | Dynamic Adaptive | Must first map what uses the old API before knowing what to change. |
| "Extract structured data from these 1,000 invoices" | Prompt Chaining | Same extraction schema for each document. Batch processing pipeline. |
If you can draw the complete workflow diagram before seeing any data โ Prompt Chaining.
If the workflow diagram changes based on what you find โ Dynamic Adaptive Decomposition.
Sending a 10-file PR as one 60,000-token prompt. Middle files get attention dilution. Per-file passes with a separate integration step is always correct for multi-file review.
Using a hardcoded 5-step pipeline to "add tests to a legacy codebase" without ever mapping what exists. Steps 2-5 are planned blind โ they'll be wrong when the codebase structure is unexpected.
Not telling Claude "focus on this file only." Claude will try to reason about imports and callers it can't see, producing speculative cross-file findings that pollute the per-file analysis.
Running per-file passes and delivering those as the final review. Cross-file vulnerabilities โ data flow issues, auth bypass paths โ will be entirely absent from the report.
Run all per-file analysis passes simultaneously using asyncio.gather() or parallel subagent spawning. This reduces code review latency from O(n) sequential to O(1) parallel โ time equals the slowest single file.
For open-ended tasks, always invest one API call in mapping structure before committing to a plan. A mapping step is cheap; re-planning mid-execution after discovering a wrong assumption is expensive.
Cap adaptive plans (max 3 rounds of adaptation, max 20 subtasks generated). Unbounded adaptive decomposition can spiral โ each discovered dependency adds more items, which add more items.
In adaptive decomposition, maintain a running discovered_dependencies list and include it in each subsequent subtask prompt. Each step builds on what previous steps discovered.
The primary exam scenario: "You are building developer productivity tools using the Claude Agent SDK. The agent helps engineers explore unfamiliar codebases, understand legacy systems, generate boilerplate code, and automate repetitive tasks. It uses built-in tools (Read, Write, Bash, Grep, Glob) and integrates with MCP servers."
Questions test: (1) selecting the correct decomposition pattern for a given task description, (2) recognizing that multi-file code reviews require per-file passes + integration pass to avoid attention dilution, and (3) identifying the three phases of open-ended task decomposition: map structure โ identify high-impact areas โ create prioritized plan that adapts as dependencies are discovered.