Study guides / CCAR-F / Domain 1

Agentic Architecture & Orchestration · Lesson 3 of 7

1.3 - Subagent Invocation and Context Passing

Configure subagent invocation using the Task tool (renamed Agent in current Claude Code), explicit context passing with structured metadata, parallel spawning, and fork_session.

Task Statement 1.3 is about the mechanics of how a coordinator actually invokes subagents and passes information between them. If 1.2 taught you the architecture, 1.3 teaches you the wiring.

The Task Tool

The Task tool is how a coordinator spawns subagents (the exam guide v0.2 uses this name). It's the actual API mechanism that makes multi-agent orchestration work in the Claude Agent SDK, not a naming convention you can skip past. Current Claude Code (v2.1.63, June 2026) renamed it to Agent; the name Task still works as an alias, and the Agent SDK emits Agent in tool-use blocks. Answer "Task tool" on the exam, and expect to see "Agent" in current code.

There is a critical configuration requirement: the coordinator's allowedTools must include "Task" (or "Agent", its current name in Claude Code). Without it, the coordinator physically can't spawn subagents. It's a binary gate, not a soft preference. If neither Task nor Agent is in allowedTools, the coordinator has no way to invoke subagents at all.

Each subagent is defined by an AgentDefinition that specifies three things:

  1. Description - what the subagent does (used by the coordinator to decide when to invoke it).
  2. System prompt - the instructions the subagent follows.
  3. Tool restrictions - which tools the subagent can access (scoped to its role).

Key Concept

The coordinator's allowedTools must include "Task" (or "Agent", its current name) to spawn subagents. This is a hard requirement. Without it, the coordinator cannot invoke any subagent regardless of how they are defined.

Context Passing: The Make-or-Break Detail

Context passing is where most multi-agent systems fall over. The principle from 1.2 carries straight across: subagents have isolated context. They get only what the coordinator writes into their prompt. Nothing else.

There are three rules for effective context passing:

Rule 1: Include complete findings from prior agents. If the synthesis subagent needs web search results and document analysis output, the coordinator must pass both - in full - in the synthesis subagent's prompt. Do not assume the synthesis agent can "look up" prior results. It cannot.

Rule 2: Use structured data formats that separate content from metadata. When passing research findings between agents, the data must include both the content (the claim, the fact, the analysis) and the metadata (source URL, document name, page number). If you pass content without metadata, the downstream agent cannot attribute claims to sources.

This is a specific exam pattern: a synthesis agent produces a report with unsourced claims. The web search and document analysis subagents are working correctly. The root cause is that the coordinator passed content without structured metadata - the synthesis agent literally had no source information to include.

Rule 3: Design coordinator prompts that specify goals, not procedures. The coordinator prompt should tell subagents what to achieve and what quality criteria to meet, not step-by-step instructions for how to do it. Goal-oriented prompts enable subagent adaptability. Procedural instructions constrain subagents and prevent them from adjusting their approach when they encounter unexpected situations.

Exam Trap

When a synthesis agent produces unsourced claims, the exam expects you to identify the context passing failure - specifically, missing structured metadata. Do not blame the synthesis agent's prompt or propose giving it direct tool access.

Structured Metadata Format

The structured data format for inter-agent context passing should separate content from metadata cleanly. A practical format looks like this:

{
  "findings": [
    {
      "claim": "Solar panel efficiency has increased 25% in the last decade",
      "source_url": "https://example.com/solar-report",
      "document_name": "Annual Solar Industry Report 2024",
      "page_number": 14,
      "confidence": "high",
      "retrieved_by": "web_search_agent"
    }
  ]
}

Each finding carries its source attribution as metadata. When the synthesis agent receives this structured data, it has everything it needs to produce a properly cited report.

Parallel Spawning

When a coordinator needs to invoke multiple subagents for independent tasks, it should emit multiple Task tool calls in a single response rather than invoking them one at a time across separate turns.

Sequential spawning - one subagent per coordinator turn - adds latency for nothing. If the web search agent and document analysis agent work independently, there's no reason to make one wait for the other.

The exam tests latency awareness. When presented with independent subagent tasks, the correct answer involves parallel spawning. Look for answer options that mention "in a single response" or "simultaneously" - these signal the parallel pattern.

Key Concept

Spawn independent subagents in parallel by emitting multiple Task tool calls in a single coordinator response. This reduces latency compared to sequential invocation across separate turns.

fork_session

fork_session creates independent branches from a shared analysis baseline. After a coordinator has completed an initial analysis (reading a codebase, understanding a problem), it can fork the session to explore divergent approaches.

Example: after analysing a codebase, the coordinator forks to compare two testing strategies. Each fork operates independently after the branching point - they do not see each other's results, and changes in one fork do not affect the other.

fork_session is not the same as --resume. Resume continues a specific named session. Fork creates a new independent branch. The exam tests this distinction. Use fork when you need divergent exploration from a shared starting point. Use resume when you want to continue the same line of investigation.

Practical Example: Attribution Failure

A multi-agent research system has three agents: web search, document analysis, and synthesis. The web search agent returns well-sourced results with URLs and titles. The document analysis agent returns detailed analysis with page references.

The coordinator passes the content from both agents to the synthesis agent but strips the metadata - it sends the claims and analysis text without source URLs, document names, or page numbers. The synthesis agent produces an excellent summary with no source attribution.

The fix is not to modify the synthesis agent's prompt (it cannot cite sources it does not have). The fix is to require the coordinator to pass structured metadata alongside content, preserving the source URL, document name, and page number for every finding.

Exam traps

Practice question

A synthesis agent produces a report where several claims have no source attribution. The web search subagent correctly returns results with URLs, titles, and snippets. The document analysis subagent correctly returns analysis with page references. Both subagents are verified to be working properly. What is the most likely root cause?

  • A The synthesis agent system prompt lacks explicit instructions to cite sources, so it summarises the research without carrying any attribution into the report

    Even with citation instructions, the synthesis agent cannot cite sources it was never given. If the coordinator strips metadata before passing content, no prompt instruction can recover the missing information.

  • B The coordinator passes content to the synthesis agent without structured metadata - source URLs, document names, and page numbers are not included Correct

    Context passing must include structured data that separates content from metadata. Without source URLs and document names in the data passed to the synthesis agent, it has no attribution information to include regardless of its instructions.

  • C The web search subagent returns its results in a format the synthesis agent cannot parse, so the source URLs and document titles are dropped during synthesis

    The web search subagent is returning well-structured results. The issue is not the source format - it is that the coordinator does not pass the metadata through to the synthesis agent.

  • D The synthesis agent should be given direct access to the web search tool so it can re-run the queries and verify sources itself

    Giving the synthesis agent web search tools violates the principle of scoped tool access and breaks the hub-and-spoke architecture. The fix is proper context passing, not giving agents tools outside their role.

Build exercise: Implement Context Passing with Structured Metadata

Intermediate · 50 minutes

You'll practice:

  1. Create a coordinator agent with Task (or Agent) in its allowedTools

    Task is the hard gate for subagent spawning (renamed Agent in current Claude Code v2.1.63; Task still works as an alias). Without it in allowedTools, the coordinator cannot invoke any subagent. The exam tests this as a binary requirement - it is not optional or configurable at runtime.

    You should see: A query() call whose options include allowedTools explicitly containing Agent (or Task) alongside any other tools the coordinator needs directly, plus the subagent definitions under options.agents.

    Hints
    1. What happens if you omit Task (or Agent) from allowedTools? The coordinator simply cannot spawn subagents - there is no fallback.
    2. There is no Agent class to instantiate. The coordinator is a query() call from @anthropic-ai/claude-agent-sdk: put Agent (or Task) in options.allowedTools and define the subagents under options.agents.
    3. import { query } from "@anthropic-ai/claude-agent-sdk";
      
      const result = query({
        prompt: "Research the topic and produce a fully cited report.",
        options: {
          systemPrompt: "You coordinate research by delegating to specialist subagents and synthesising their findings.",
          // "Task" in the exam guide; renamed "Agent" in Claude Code v2.1.63
          allowedTools: ["Agent", "Read"],
          agents: {
            "web-search": webSearchAgent,
            "doc-analysis": docAnalysisAgent,
            "synthesis": synthesisAgent
          }
        }
      });
  2. Define two subagents: a web search agent that returns results with source URLs and titles, and a document analysis agent that returns analysis with page references

    Each subagent needs scoped tool access matching its role. The exam tests whether you define subagents with proper AgentDefinition fields: description, system prompt, and tool restrictions.

    You should see: Two AgentDefinition objects, each with a description, system prompt, and restricted tool set. The web search agent has search tools only; the document analysis agent has file reading tools only.

    Hints
    1. What three things does an AgentDefinition specify? Think about how the coordinator uses each field.
    2. Each AgentDefinition needs: description (used by the coordinator for selection), prompt (the subagent system prompt - the SDK field is prompt, not systemPrompt), and tools (scoped to the subagent role). The agent name is its key in options.agents, not a field.
    3. // Keyed into options.agents as "web-search" and "doc-analysis"
      const webSearchAgent = {
        description: "Searches the web for current information and returns results with source URLs and titles",
        prompt: "Search for information on the given topic. Return each finding as JSON with fields: claim, source_url, source_title, retrieved_date.",
        tools: ["WebSearch"]
      };
      const docAnalysisAgent = {
        description: "Analyses documents and returns findings with page references",
        prompt: "Analyse the provided documents. Return each finding as JSON with fields: claim, document_name, page_number, section.",
        tools: ["Read", "Grep"]
      };
  3. Design a structured output format that separates content from metadata: each finding includes claim, source_url, document_name, page_number, and confidence

    The exam specifically tests the attribution failure pattern: when a synthesis agent produces unsourced claims, the root cause is that the coordinator passed content without structured metadata. Separating content from metadata is the fix.

    You should see: A TypeScript interface or JSON schema defining the Finding type with both content fields (claim, analysis) and metadata fields (source_url, document_name, page_number, confidence, retrieved_by).

    Hints
    1. What fields does the synthesis agent need to produce a properly cited report? Think about what is required for full attribution.
    2. The finding must carry enough metadata for any downstream agent to produce a citation. At minimum: source_url, document_name, page_number, confidence, and retrieved_by (which agent produced it).
    3. interface Finding {
        claim: string;
        source_url: string;
        document_name: string;
        page_number: number | null;
        confidence: "high" | "medium" | "low";
        retrieved_by: string;
      }
      
      interface ResearchOutput {
        findings: Finding[];
        query: string;
        timestamp: string;
      }
  4. Pass complete structured results from both subagents to a synthesis subagent, preserving all metadata

    This is the critical step the exam targets. Stripping metadata before passing to the synthesis agent is the root cause of attribution failures. The coordinator must pass the full structured output, not just the claim text.

    You should see: The coordinator passes the complete findings array (with all metadata intact) to the synthesis agent prompt. No metadata fields are stripped or summarised away.

    Hints
    1. Check that you are passing the entire structured object, not extracting just the claim strings. What would happen if you only passed the claims?
    2. The synthesis agent prompt must include the full JSON of all findings from both subagents. Include them verbatim - do not summarise or extract subsets of fields.
    3. // The prompt the coordinator embeds when it invokes the synthesis subagent;
      // webSearchResults / docAnalysisResults are the structured findings the research subagents returned
      const synthesisPrompt = `Synthesise the following research findings into a coherent report. Every claim MUST include a citation with source URL and page number.
      
      Web search findings:
      ${JSON.stringify(webSearchResults.findings, null, 2)}
      
      Document analysis findings:
      ${JSON.stringify(docAnalysisResults.findings, null, 2)}
      
      Output a report where every factual claim links to its source.`;
  5. Verify that the synthesis agent can attribute every claim in its output to a specific source with URL and page number

    This verification step confirms the context passing worked. If any claim lacks attribution, trace back to whether the metadata was actually passed - do not blame the synthesis agent prompt.

    You should see: A synthesis report where every factual claim includes a citation with source URL and page number. No orphaned claims without attribution.

    Hints
    1. How can you programmatically verify that every claim has a citation? Look for a pattern in the output.
    2. Parse the synthesis output and check that each section or claim references at least one source_url. Flag any claims that lack attribution and trace back to whether the metadata was present in the input.
    3. function verifyCitations(report: string, findings: Finding[]): string[] {
        const uncited: string[] = [];
        const claims = extractClaims(report);
        for (const claim of claims) {
          const hasCitation = findings.some(f =>
            report.includes(f.source_url) && report.includes(claim)
          );
          if (!hasCitation) uncited.push(claim);
        }
        return uncited;
      }
  6. Refactor the coordinator to spawn both research subagents in parallel using multiple Task tool calls in a single response

    The exam tests latency awareness. Sequential spawning of independent subagents wastes time. Parallel spawning via multiple Task tool calls in a single coordinator response is the correct pattern for independent tasks.

    You should see: Both the web search and document analysis subagents invoked simultaneously via parallel Task tool calls, with the coordinator waiting for both to complete before proceeding to synthesis.

    Hints
    1. What makes these two tasks suitable for parallel execution? They are independent - neither needs the other result.
    2. Emit both Agent (Task) tool calls in a single coordinator response rather than waiting for one to finish before starting the other. The parallelism happens within a single model turn - the SDK runs the calls concurrently. There is no Promise.all over subagents in your code; steer the coordinator through its prompt.
    3. const result = query({
        prompt: "Research the topic. Invoke the web-search and doc-analysis subagents in parallel - emit both Agent tool calls in a single response - then pass their complete structured findings to the synthesis subagent.",
        options: {
          allowedTools: ["Agent"],
          agents: { "web-search": webSearchAgent, "doc-analysis": docAnalysisAgent, "synthesis": synthesisAgent }
        }
      });
      
      for await (const message of result) {
        // Both Agent tool_use blocks arrive in one assistant message;
        // the SDK executes the two subagents concurrently
      }

Sources