Agent Teams

Quick Reference

Modules Covered

ModuleSourceVersion
Team Templatessrc/teams/templates.tsv1.4
GSD Templatessrc/teams/gsd-templates.tsv1.4
Team Validatorsrc/teams/team-validator.tsv1.4
Team Storesrc/teams/team-store.tsv1.4
Team Wizardsrc/teams/team-wizard.tsv1.4
Agent Generatorsrc/teams/team-agent-generator.tsv1.4
Cost Estimatorsrc/teams/cost-estimator.tsv1.4
Inter-Team Bridgesrc/teams/inter-team-bridge.tsv1.4

Prerequisites

Topologies at a Glance

leader-worker1 lead delegates to N parallel workers
pipelineSequential stages with blockedBy dependencies
swarmWorkers self-claim tasks from shared queue
router1 router classifies and directs to specialists
map-reduceOrchestrator splits work, workers process, results consolidated
customUser-defined topology

Storage Locations

Team configs:

.claude/teams/{team-name}/config.json   # project scope
~/.claude/teams/{team-name}/config.json  # user scope

Agent files:

.claude/agents/{agent-id}.md   # always project scope

Technical Specifications

Topologies6 (leader-worker, pipeline, swarm, router, map-reduce, custom)
Member Roles7 (leader, worker, reviewer, orchestrator, specialist, router, reducer)
Models3 (haiku, sonnet, opus)
Backends3 (in-process, tmux, iterm2)
Validation Checks7 (VALID-01 through VALID-07 + inter-team)
Max Workers per Template10
Name FormatLowercase alphanumeric + hyphens, max 64 chars

Related Capabilities

Getting Started: What Are Agent Teams?

An agent team is a group of Claude Code agents that coordinate on a shared task. Instead of a single agent doing everything, teams split work across specialized members — a coordinator delegates, workers execute in parallel, and results are synthesized into a unified output.

When to use teams:

  • Parallel research — multiple dimensions investigated simultaneously
  • Adversarial debugging — competing hypotheses explored by independent investigators
  • Pipeline processing — sequential stages where each transforms the output of the previous
  • Classification and routing — incoming work sorted and dispatched to domain specialists
  • Large-scale decomposition — a problem too big for one agent split into parallel chunks

When NOT to use teams:

  • Simple, self-contained tasks that one agent handles well
  • Tasks where coordination overhead exceeds the parallelism benefit
  • Exploratory work where the problem is not yet well-defined enough to decompose

For students: Multi-agent collaboration is a pattern from distributed systems. Think of it like a group project where each person has a defined role. The coordinator (lead agent) breaks the project into tasks. Workers pick up tasks, complete them, and report results. The key difference from a human group project: agents communicate through structured messages and task queues rather than chat, which makes coordination predictable and auditable.

Building Your First Team

The fastest way to create a team is the interactive wizard. Run it from the CLI:

skill-creator team create

The wizard walks you through five steps:

  1. Select a pattern — choose from leader-worker, pipeline, swarm, router, or map-reduce
  2. Name your team — lowercase alphanumeric with hyphens (e.g., my-research-team)
  3. Add a description — what the team does (optional, defaults provided per pattern)
  4. Set worker count — how many workers/stages/specialists (1–10, default: 3)
  5. Choose scope — project (.claude/teams/) or user (~/.claude/teams/)

The wizard generates two things:

  • A team config at .claude/teams/{name}/config.json — the team definition
  • Agent files at .claude/agents/{agent-id}.md — one per member, with role-aware prompts

Non-interactive creation for scripts and CI:

skill-creator team create \
  --name my-research-team \
  --pattern leader-worker \
  --members 4 \
  --scope project \
  --description "Parallel research across technology dimensions"

Both paths produce identical output. The non-interactive path throws on validation errors rather than prompting for correction.

Anatomy of a Team Config

Every team config is a JSON file with this structure:

{
  "name": "my-research-team",
  "description": "Parallel research across technology dimensions",
  "leadAgentId": "my-research-team-lead",
  "createdAt": "2026-02-24T10:00:00.000Z",
  "members": [
    {
      "agentId": "my-research-team-lead",
      "name": "Lead",
      "agentType": "coordinator",
      "tools": ["Read", "Write", "Bash", "Glob", "Grep",
               "TaskCreate", "TaskList", "TaskGet", "TaskUpdate",
               "SendMessage", "TeammateTool"]
    },
    {
      "agentId": "my-research-team-worker-1",
      "name": "Worker 1",
      "agentType": "worker",
      "tools": ["Read", "Write", "Edit", "Bash", "Glob", "Grep",
               "WebFetch", "WebSearch",
               "TaskGet", "TaskUpdate", "SendMessage"]
    }
  ],
  "version": 1,
  "topology": "leader-worker"
}

Key constraints enforced by the schema:

  • leadAgentId must match exactly one member's agentId
  • members must have at least one entry
  • All agentId values must be unique within the team
  • If topology is set, topology-specific rules are validated (e.g., leader-worker requires a coordinator/orchestrator lead)

Topology Selection Guide

Choosing the right topology is the most important design decision for a team. Each topology suits a different kind of work:

Leader-Worker

Pattern: 1 coordinator + N parallel workers
Best for: Independent tasks that can run in parallel with a single point of synthesis
Example: Research across four dimensions (stack, features, architecture, pitfalls) where each researcher works independently and a synthesizer combines findings

// Generates: 1 lead (coordinator) + N workers
const team = generateLeaderWorkerTemplate({
  name: 'my-team',
  workerCount: 4
});

Coordination tools: Lead gets TaskCreate, TaskList, TaskGet, TaskUpdate, SendMessage, TeammateTool. Workers get TaskGet, TaskUpdate, SendMessage plus file/web tools.

Pipeline

Pattern: 1 orchestrator + N sequential stages
Best for: Multi-step transformations where each stage depends on the output of the previous
Example: Code review pipeline — Stage 1: static analysis, Stage 2: security audit, Stage 3: performance review

// Generates: 1 lead (orchestrator) + N stages with blockedBy chains
const team = generatePipelineTemplate({
  name: 'review-pipeline',
  workerCount: 3  // 3 sequential stages
});
// Tasks: stage-1 -> stage-2 (blockedBy: stage-1) -> stage-3 (blockedBy: stage-2)

Key difference: Tasks have explicit blockedBy/blocks dependency chains. Stage 2 cannot start until Stage 1 completes.

Swarm

Pattern: 1 coordinator + N self-organizing workers
Best for: Large task backlogs where any worker can pick up any task
Example: Batch file processing — 50 files need formatting, any worker can grab the next unprocessed file

// Generates: 1 lead (coordinator) + N workers with TaskList for self-claiming
const team = generateSwarmTemplate({
  name: 'batch-processor',
  workerCount: 5
});

Key difference: Workers have TaskList so they can browse and self-claim tasks. No explicit assignment from the lead — workers pull work autonomously.

Router

Pattern: 1 router + N specialists
Best for: Heterogeneous work that needs classification before execution
Example: Support ticket triage — router classifies each ticket and sends it to the right specialist (billing, technical, account management)

// Generates: 1 router + N specialists
const team = generateRouterTemplate({
  name: 'support-triage',
  workerCount: 3  // 3 specialist domains
});

Key difference: Router has classification tools but no file-write capability. It analyzes and delegates; specialists execute.

Map-Reduce

Pattern: 1 orchestrator + N parallel workers with fan-out/fan-in
Best for: Problems that decompose into independent chunks requiring consolidation
Example: Codebase analysis — orchestrator splits the repo into N directories, each worker analyzes their directory, orchestrator consolidates findings

// Generates: 1 orchestrator + N workers
// Tasks: map-split -> worker-chunk-1..N (all blockedBy: map-split)
const team = generateMapReduceTemplate({
  name: 'code-analysis',
  workerCount: 4
});

Key difference: Two-phase task structure. The map task splits work; all worker tasks are blocked by the map task. Orchestrator has REDUCER_TOOLS for consolidation.

Decision Matrix

FactorLeader-WorkerPipelineSwarmRouterMap-Reduce
Task independenceHighLow (sequential)HighHighHigh
Needs classification?NoNoNoYesNo
Needs consolidation?OptionalLast stageOptionalOptionalYes (critical)
Order matters?NoYesNoNoNo
Worker autonomyMediumLowHighLowMedium
Best member count2–62–53–102–53–8

For professionals: These topologies map directly to distributed systems patterns. Leader-worker is the classic coordinator pattern (ZooKeeper, Kubernetes controller). Pipeline is a staged processing chain (Unix pipes, Apache Kafka Streams). Swarm is work-stealing (Go scheduler, Java ForkJoinPool). Router is content-based routing (RabbitMQ topic exchanges, nginx upstream routing). Map-reduce is the canonical Hadoop/Spark pattern. The key architectural insight: topology is a first-class configuration choice, not an emergent property — you declare the communication pattern and the framework enforces it through tool assignment and task dependency structures.

GSD Workflow Integration

Teams integrate with GSD at three points: research phases, execution phases, and debugging sessions.

Research Teams

The built-in generateGsdResearchTeam() creates a 5-member team (1 synthesizer + 4 researchers) pre-configured for parallel ecosystem investigation:

  • Stack researcher — languages, frameworks, libraries, runtime environments
  • Features researcher — API surface, extensibility points, integration options
  • Architecture researcher — scalability, modularity, data flow, deployment topology
  • Pitfalls researcher — known limitations, failure modes, security concerns, migration risks
  • Synthesizer — combines all four dimensions into a unified research report

Used during /gsd:research-phase to parallelize what would otherwise be a serial investigation.

Debugging Teams

The built-in generateGsdDebuggingTeam() creates a 4-member adversarial team (1 coordinator + 3 investigators):

  • Alpha — primary hypothesis investigator (most likely explanation)
  • Beta — adversarial investigator (challenges Alpha's hypothesis, explores alternatives)
  • Gamma — environmental investigator (infrastructure, dependencies, configuration)
  • Coordinator — forms hypotheses, dispatches investigators, synthesizes root cause analysis

Used during /gsd:debug to investigate bugs from multiple angles simultaneously.

Execution Phase Teams

For /gsd:execute-phase, you can create custom teams to parallelize phase work. If a phase plan has independent tasks, a leader-worker team lets multiple workers execute tasks concurrently while the lead tracks progress and resolves conflicts.

Member Configuration

Each team member is defined by these fields:

FieldTypeRequiredDescription
agentIdstringYesUnique identifier within the team, maps to .claude/agents/{agentId}.md
namestringYesDisplay name
agentTypestringNoRole: coordinator, worker, orchestrator, specialist, router, reducer
modelstringNoModel alias: haiku (fast), sonnet (balanced, default), opus (highest capability)
toolsstring[]NoAssigned tools (auto-populated from templates)
promptstringNoInitial instructions for this member
backendTypestringNoProcess backend: in-process, tmux, or iterm2
cwdstringNoWorking directory for this member
planModeRequiredbooleanNoWhether this member must run in plan mode

Tool Assignment by Role

Templates automatically assign tools based on member role. Here is the complete mapping:

RoleTools
Leader/CoordinatorRead, Write, Bash, Glob, Grep, TaskCreate, TaskList, TaskGet, TaskUpdate, SendMessage, TeammateTool
Worker (leader-worker)Read, Write, Edit, Bash, Glob, Grep, WebFetch, WebSearch, TaskGet, TaskUpdate, SendMessage
Pipeline StageRead, Write, Edit, Bash, Glob, Grep, TaskGet, TaskUpdate, SendMessage
Swarm WorkerRead, Write, Edit, Bash, Glob, Grep, TaskList, TaskGet, TaskUpdate, SendMessage
RouterRead, Bash, Glob, Grep, TaskCreate, TaskList, TaskGet, TaskUpdate, SendMessage, TeammateTool
Reducer/OrchestratorRead, Write, Bash, Glob, Grep, TaskCreate, TaskList, TaskGet, TaskUpdate, SendMessage, TeammateTool

Notice the key differences: workers get Edit and web tools but not TaskCreate; leaders get task management tools (TaskCreate, TeammateTool) but not Edit or web tools; routers cannot Write files (they classify and delegate, not execute); swarm workers uniquely get TaskList for self-claiming.

Model Selection and Cost

The cost estimator provides per-member and total estimates based on model pricing and topology heuristics:

ModelInput (per 1M tokens)Output (per 1M tokens)Best For
haiku$0.25$1.25Simple classification, routing, status checks
sonnet$3.00$15.00Balanced work — coordination, synthesis, standard coding
opus$15.00$75.00Complex reasoning, deep research, adversarial debugging

Coordinator roles receive a 1.5x token multiplier in cost estimates because they handle delegation and synthesis in addition to their own work. Typical cost per invocation for a 4-member leader-worker team with sonnet workers: $0.15–$0.60.

Team Validation

The validateTeamFull() orchestrator runs seven checks in sequence:

CheckIDTypeWhat It Catches
Schema validationVALID-01ErrorMissing required fields, invalid types, empty members array
Member resolutionVALID-02InfoAgent files missing from .claude/agents/ (with fuzzy name suggestions)
Skill conflictsVALID-03WarningCross-member skill overlap detected via semantic similarity (≥0.85)
Role coherenceVALID-04WarningDifferent-role members with near-duplicate descriptions
Task cyclesVALID-05ErrorCircular blockedBy dependencies (Kahn's algorithm, O(n+m))
Tool overlapVALID-06WarningMultiple members sharing write-capable tools (Write, Edit, MultiEdit)
Topology rulesVALID-07ErrorTopology-specific violations (e.g., leader-worker without a coordinator lead)

Errors are blocking — the team config is invalid and must be fixed. Warnings are informational — the team will work but you may want to address potential issues.

# Validate a specific team
skill-creator team validate my-team

# Validate all teams
skill-creator team validate --all

Missing agent suggestions: When VALID-02 finds a missing agent file, it searches for similar names using Levenshtein distance (≤2) and shared prefixes (≥4 characters). If your team references my-team-woker-1, it will suggest my-team-worker-1.

Inter-team validation: When multiple teams declare outputTo/inputFrom links, the validator checks that all referenced team names exist, flags consistency mismatches, and runs cycle detection to prevent deadlocks between teams.

For sysadmins: Team files live in .claude/teams/{name}/config.json (project scope) or ~/.claude/teams/{name}/config.json (user scope). Agent files always go to .claude/agents/ at project scope due to a Claude Code discovery limitation (bug #11205). For monitoring, watch validation output — warnings about tool overlap and skill conflicts are early indicators that a team's responsibilities are not cleanly separated. The TeamStore enforces path safety via validateSafeName() and assertSafePath(), preventing path traversal attacks through crafted team names.

Communication Patterns

Agents coordinate through a structured message and task system. Here are the primary communication tools:

ToolPurposeWho Uses It
TaskCreateCreate a new task in the team's task queueLeaders, orchestrators, routers
TaskListBrowse available tasks (for self-claiming or monitoring)Leaders, swarm workers, routers
TaskGetRead details of a specific taskAll members
TaskUpdateChange task status, claim a task, report completionAll members
SendMessageSend a message to another agent's inboxAll members
TeammateToolDirect coordination with a specific teammateLeaders, orchestrators, routers

Message Types

The team system supports structured message types for specific coordination events:

  • shutdown_request / shutdown_response — graceful team shutdown protocol
  • task_completed — notification that a task has finished
  • plan_approval_request / plan_approval_response — plan-mode approval flow
  • join_request — dynamic member joining

The message type system is extensible — the type is a union of known types with string, so custom message types work without schema changes.

Task Lifecycle

Tasks move through three statuses: pending → in_progress → completed. Tasks can have:

  • owner — the agent ID that claimed the task
  • blockedBy — task IDs that must complete first
  • blocks — task IDs that depend on this task
  • activeForm — present-continuous description for spinner display (e.g., "Investigating root cause")

Scaling Considerations

When to Add More Workers

  • Task queue backlog growing — if pending tasks consistently outnumber in-progress tasks, add workers
  • Wall-clock time matters more than cost — more workers means faster parallel completion at higher token cost
  • Task independence is high — adding workers only helps when tasks can run concurrently

When to Switch Topology

  • Leader-worker → Pipeline: When you realize tasks have natural ordering dependencies
  • Leader-worker → Swarm: When task assignment by the leader becomes a bottleneck
  • Router → Leader-worker: When classification is not needed — all tasks go to the same type of worker
  • Swarm → Map-reduce: When you need a consolidation step after parallel processing

Cost vs. Capability Trade-offs

  • Use haiku for workers on simple, well-defined tasks (formatting, data extraction)
  • Use opus for specialists on tasks requiring deep reasoning (research, debugging)
  • Use sonnet for coordinators — they need to understand context and delegate, not perform deep analysis
  • Coordination multiplier: Leaders, routers, and orchestrators use ~1.5x the tokens of a worker due to delegation overhead

Inter-Team Communication

When multiple teams need to coordinate, use outputTo/inputFrom declarations in the team config. The inter-team bridge validates that:

  • All referenced team names exist
  • outputTo/inputFrom declarations are consistent (team A outputs to B, team B declares input from A)
  • No circular dependencies exist between teams (detected via Kahn's algorithm)

For professionals: The inter-team cycle detection uses the same Kahn's algorithm as intra-team task cycle detection, applied at the team granularity instead of the task granularity. This is a config-time validator, not a runtime message broker — it catches architectural deadlocks before agents start executing. The validation is O(n+m) where n is team count and m is link count, so it scales to arbitrarily large team networks without performance concern.


Team Configuration

Teams are stored as JSON files in .claude/teams/:

{
  "name": "research-team",
  "description": "Parallel research across multiple dimensions",
  "leadAgentId": "research-synthesizer",
  "members": [
    { "agentId": "research-synthesizer", "name": "Synthesizer", "agentType": "coordinator", "model": "sonnet" },
    { "agentId": "researcher-alpha", "name": "Alpha", "agentType": "specialist", "model": "opus" }
  ],
  "createdAt": "2026-01-15T10:00:00Z"
}

Each member references an agent file in .claude/agents/. The leadAgentId must match one member's agentId.

Team Validation

Team validation checks schema compliance, topology rules, tool overlap, skill conflicts, and role coherence:

skill-creator team validate my-team   # Validate specific team
skill-creator team validate --all     # Validate all teams

Errors are blocking (invalid schema, missing lead, duplicate IDs, topology violations, dependency cycles). Warnings are informational (tool overlap, skill conflicts, role coherence).

GSD Workflow Templates

Two built-in templates for GSD workflows:

Template Members Pattern Use Case
Research Team 5 (1 synthesizer + 4 researchers) leader-worker Parallel ecosystem research
Debugging Team 4 (1 coordinator + 3 investigators) leader-worker Adversarial debugging
import { generateGsdResearchTeam, generateGsdDebuggingTeam } from 'gsd-skill-creator';

const research = generateGsdResearchTeam();
const debugging = generateGsdDebuggingTeam();

See GSD-TEAMS.md for detailed workflow analysis and COMPARISON.md for choosing the right abstraction.


Calibrating Activation Thresholds: Source Code Reference

The threshold optimizer (src/calibration/threshold-optimizer.ts) uses F1 score optimization via grid search to find thresholds that maximize balanced accuracy between precision and recall.

ThresholdOptimizer Grid Search

The optimizer evaluates 46 candidate thresholds from 0.50 to 0.95 in 0.01 increments, computing F1, precision, recall, and accuracy for each one against calibration events with known outcomes.

export class ThresholdOptimizer {
  private static readonly GRID_MIN = 0.5;
  private static readonly GRID_MAX = 0.95;
  private static readonly GRID_STEP = 0.01;

  findOptimalThreshold(
    events: CalibrationEvent[],
    currentThreshold: number
  ): OptimizationResult {
    const candidates: ThresholdCandidate[] = [];

    for (
      let threshold = ThresholdOptimizer.GRID_MIN;
      threshold <= ThresholdOptimizer.GRID_MAX;
      threshold = Math.round((threshold + ThresholdOptimizer.GRID_STEP) * 100) / 100
    ) {
      candidates.push(this.evaluateThreshold(events, threshold));
    }

    // Sort by F1 descending to find optimal
    const sortedCandidates = [...candidates].sort((a, b) => b.f1 - a.f1);
    const optimal = sortedCandidates[0];
    const current = this.evaluateThreshold(events, currentThreshold);

    return {
      optimalThreshold: optimal?.threshold ?? currentThreshold,
      optimalF1: optimal?.f1 ?? 0,
      currentThreshold,
      currentF1: current.f1,
      improvement: (optimal?.f1 ?? 0) - current.f1,
      dataPoints: events.length,
      allCandidates: candidates,
    };
  }
}

Confusion Matrix Evaluation

Each threshold candidate is evaluated by classifying calibration events into true/false positives and negatives, then computing standard metrics with safe division.

evaluateThreshold(
  events: CalibrationEvent[],
  threshold: number
): ThresholdCandidate {
  let tp = 0; // True Positive: predicted activate, actually accepted
  let fp = 0; // False Positive: predicted activate, actually rejected
  let tn = 0; // True Negative: predicted no activate, actually would reject
  let fn = 0; // False Negative: predicted no activate, actually would accept

  for (const event of events) {
    const bestScore = this.getBestScore(event);
    const predicted = bestScore >= threshold;
    const actual = event.outcome === 'continued';

    if (predicted && actual) tp++;
    else if (predicted && !actual) fp++;
    else if (!predicted && !actual) tn++;
    else if (!predicted && actual) fn++;
  }

  const precision = tp + fp > 0 ? tp / (tp + fp) : 0;
  const recall = tp + fn > 0 ? tp / (tp + fn) : 0;
  const f1 = precision + recall > 0
    ? (2 * precision * recall) / (precision + recall) : 0;
  const total = tp + fp + tn + fn;
  const accuracy = total > 0 ? (tp + tn) / total : 0;

  return { threshold, f1, precision, recall, accuracy };
}

CalibrationStore: JSONL Persistence

Calibration events are stored in an append-only JSONL file at ~/.gsd-skill/calibration/events.jsonl. The store uses a write queue to serialize concurrent writes and prevent JSON interleaving.

export class CalibrationStore {
  private eventsPath: string;
  private writeQueue: Promise<void> = Promise.resolve();

  constructor(basePath?: string) {
    const baseDir = basePath ?? join(homedir(), '.gsd-skill', 'calibration');
    this.eventsPath = join(baseDir, 'events.jsonl');
  }

  async record(input: CalibrationEventInput): Promise<CalibrationEvent> {
    const event: CalibrationEvent = {
      ...input,
      id: randomUUID(),
      timestamp: new Date().toISOString(),
    };
    await this.appendLine(event);
    return event;
  }

  async getKnownOutcomes(): Promise<CalibrationEvent[]> {
    const events = await this.readAll();
    return events.filter(e => e.outcome !== 'unknown');
  }

  private async appendLine(event: CalibrationEvent): Promise<void> {
    await this.ensureDir();
    this.writeQueue = this.writeQueue.then(async () => {
      const line = JSON.stringify(event) + '\n';
      await appendFile(this.eventsPath, line, 'utf-8');
    });
    await this.writeQueue;
  }
}

Calibration Data Types

Type Description
ThresholdCandidate Metrics for a single threshold: f1, precision, recall, accuracy
OptimizationResult Optimal vs current threshold comparison with improvement delta
CalibrationEvent Recorded skill activation decision with outcome (continued/corrected/unknown)
CalibrationEventInput Event data before id/timestamp are added