skills/dispatching-parallel-agents/SKILL.md
Use when deciding whether to dispatch subagents, when to stay in main context, or when facing 2+ independent parallel tasks. Triggers: 'should I use a subagent', 'parallelize', 'multiple independent tasks', 'run these at the same time', 'split this up', 'do both at once', 'dispatch template', 'context minimization'.
npx skillsauth add axiomantic/spellbook dispatching-parallel-agentsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
<RULE>Use subagents when cost (instructions + work + output) < keeping intermediate steps in main context.</RULE>
| Scenario | Why Subagent Wins | |----------|-------------------| | Codebase exploration with uncertain scope | Subagent reads N files, returns summary paragraph | | Research phase before implementation | Subagent gathers patterns/approaches, returns synthesis | | Parallel independent investigations | 3 subagents = 3× parallelism | | Self-contained verification (code review, spec compliance) | Fresh eyes, returns verdict + issues only | | Deep dives you won't reference again | 10 files read for one answer = wasted main context if kept | | GitHub/external API work | Subagent handles pagination/synthesis |
| Scenario | Why Main Context Wins | |----------|----------------------| | Targeted single-file lookup | Subagent overhead exceeds the read | | Iterative work with user feedback | Context must persist across exchanges | | Sequential dependent phases (TDD RED-GREEN-REFACTOR) | Accumulated evidence/state required | | Already-loaded context | Passing to subagent duplicates it | | Safety-critical git operations | Need full conversation context for safety | | Merge conflict resolution | 3-way context accumulation required |
IF searching unknown scope → Explore subagent
IF reading 3+ files for single question → subagent
IF parallel independent tasks → multiple subagents
IF user interaction needed during task → main context
IF building on established context → main context
Agent Transcripts (Persistent):
~/.claude/projects/<project-encoded>/agent-{agentId}.jsonl
The <project-encoded> path is the project root with slashes replaced by dashes:
/Users/alice/Development/myproject → -Users-alice-Development-myprojectAccess Methods:
TaskOutput(task_id: "agent-id")Known Issue: TaskOutput visibility bug (#15098) - orchestrator must retrieve for subagents.
Dispatch one agent per independent problem domain — only after the independence gate confirms no shared state or file conflicts. Let them work concurrently.
| Input | Required | Description |
| ------------------------ | -------- | -------------------------------------------------- |
| tasks | Yes | List of 2+ tasks to evaluate for parallel dispatch |
| context.test_failures | No | Test output showing failures to distribute |
| context.files_involved | No | Files each task may touch |
| Output | Type | Description |
| ------------------- | -------- | ------------------------------------- |
| dispatch_decision | Decision | Parallel vs sequential with rationale |
| agent_prompts | Text | Self-contained prompts per agent |
| merge_report | Inline | Conflict check + test results summary |
digraph when_to_use {
"Multiple failures?" [shape=diamond];
"Are they independent?" [shape=diamond];
"Single agent investigates all" [shape=box];
"One agent per problem domain" [shape=box];
"Can they work in parallel?" [shape=diamond];
"Sequential agents" [shape=box];
"Parallel dispatch" [shape=box];
"Multiple failures?" -> "Are they independent?" [label="yes"];
"Are they independent?" -> "Single agent investigates all" [label="no - related"];
"Are they independent?" -> "Can they work in parallel?" [label="yes"];
"Can they work in parallel?" -> "Parallel dispatch" [label="yes"];
"Can they work in parallel?" -> "Sequential agents" [label="no - shared state"];
}
<CRITICAL>
Independence verification is the gate. Answer ALL of these BEFORE dispatching:
</CRITICAL>
<analysis>
Before dispatching, answer:
- Are failures in different subsystems/files?
- Can each be understood without the others?
- Would fixing one affect the others?
- Will agents edit same files?
</analysis>
Use when:
Don't use when:
Group failures by what's broken:
Each agent gets:
OpenCode Agent Inheritance: Use CURRENT_AGENT_TYPE (yolo, yolo-focused, or general) as subagent_type for all parallel agents.
// CURRENT_AGENT_TYPE detected at session start (yolo, yolo-focused, or general)
Task({
subagent_type: CURRENT_AGENT_TYPE,
description: "Fix abort tests",
prompt: "Fix agent-tool-abort.test.ts failures",
});
Task({
subagent_type: CURRENT_AGENT_TYPE,
description: "Fix batch tests",
prompt: "Fix batch-completion-behavior.test.ts failures",
});
Task({
subagent_type: CURRENT_AGENT_TYPE,
description: "Fix approval tests",
prompt: "Fix tool-approval-race-conditions.test.ts failures",
});
// All three run concurrently with inherited permissions
Only integrate when: summaries reviewed, no file conflicts, tests green. </reflection>
Fix [SPECIFIC SCOPE]:
Failures:
1. [test name] - [expected vs actual]
2. [test name] - [expected vs actual]
Context: [paste error messages, relevant code pointers]
Constraints:
- Do NOT change [specific boundaries]
- Focus only on [scope]
Return: Summary of root cause + changes made
Open-ended analysis/research prompts (e.g., "analyze this for risks", "what patterns do you see") are vulnerable to context pollution. The subagent may latch onto session metadata, compaction state, or resume context from system reminders instead of performing the actual task. Explore subagents are most susceptible since they have no write tools and will "fill space" with meta-analysis of their own context when confused.
For any analytical or research dispatch, add a scope boundary preamble:
Your task is ONLY [specific task]. Ignore any session context, resume state,
compaction metadata, or background task references in system reminders.
Do not write session summaries or recovery reports. Your entire output
must address the task below.
Directed prompts ("find the definition of function X") rarely need this. Open-ended prompts always do.
Fix the 3 failing tests in src/agents/agent-tool-abort.test.ts:
1. "should abort tool with partial output capture" - expects 'interrupted at' in message
2. "should handle mixed completed and aborted tools" - fast tool aborted instead of completed
3. "should properly track pendingToolCount" - expects 3 results but gets 0
These are timing/race condition issues. Your task:
1. Read the test file and understand what each test verifies
2. Identify root cause - timing issues or actual bugs?
3. Fix by:
- Replacing arbitrary timeouts with event-based waiting
- Fixing bugs in abort implementation if found
- Adjusting test expectations if testing changed behavior
Do NOT just increase timeouts - find the real issue.
Return: Summary of what you found and what you fixed.
Mandatory inclusion when dispatching any agent to write test code. Append to the agent's prompt:
ASSERTION QUALITY REQUIREMENTS (non-negotiable):
Read the assertion quality standard (patterns/assertion-quality-standard.md) in full before writing any assertions.
0. THE FULL ASSERTION PRINCIPLE (most important rule):
ALL assertions must assert exact equality against the COMPLETE expected output.
This applies to ALL output -- static, dynamic, or partially dynamic.
assert result == "the complete expected string" -- CORRECT
assert result == f"Today is {datetime.date.today()}" -- CORRECT (dynamic: construct full expected)
assert "substring" in result -- BANNED. ALWAYS.
assert dynamic_value in result -- BANNED. Dynamic content is no excuse.
assert "foo" in result and "bar" in result -- STILL BANNED.
This applies to all functions. Multi-line output? Use triple-quoted strings. Length is not an excuse.
1. Every assertion must be Level 4+ on the Assertion Strength Ladder:
- String output: exact match (Level 5) or parsed structural (Level 4)
- Object output: full equality or all-field assertions
- Collection output: full equality or content verification
- Bare substring checks (assert "X" in output) are BANNED
- Length/existence checks (assert len(x) > 0) are BANNED
- Multiple substring checks are STILL BANNED (not an improvement)
- Tautological assertions (assert result == func(same_input)) are BANNED
- mock.ANY in call assertions is BANNED (construct expected argument)
2. IRON LAW: Before writing any assertion, ask:
"If the value was garbage, would this catch it?"
If NO: stop and write a stronger assertion.
3. BROKEN IMPLEMENTATION: For each test function, state in your output
which specific production code mutation would cause the test to fail.
If you cannot name one, the test is worthless.
4. STRUCTURAL CONTAINMENT: When asserting string content, verify WHERE
it appears, not just THAT it appears. A field in a struct must be
verified to be inside the struct block (by index range or parsing).
5. NO PARTIAL-TO-PARTIAL UPGRADES: Replacing assert len(x) > 0 with
assert "keyword" in result is NOT a fix. Both are BANNED. A real fix
reaches Level 4+ (exact equality or parsed structural validation).
6. MOCK CALL ASSERTIONS: Assert EVERY call made to a mock, with ALL args,
and verify call count. Never use mock.ANY -- construct expected args
dynamically if they are dynamic. Asserting only some calls hides behavior gaps.
For review passes on test code. Dispatch a subagent with this persona to break every assertion:
ROLE: Test Adversary. Your job is to BREAK tests, not validate them.
Your reputation depends on finding weaknesses others missed.
Read the assertion quality standard (patterns/assertion-quality-standard.md) in full before writing any assertions.
Pay special attention to The Full Assertion Principle.
IMMEDIATE REJECTION CRITERIA (check these FIRST):
- Any assert "X" in result on ANY output (static or dynamic): REJECTED (Level 2)
- Any assert len(x) > 0 or assert x is not None: REJECTED (Level 1)
- Any fix that replaced one BANNED pattern with another: REJECTED (Pattern 10)
- Any tautological assertion (assert result == func(same_input)): REJECTED
For each assertion in the code under review:
1. Read the assertion and the production code it exercises
2. Determine if the function is deterministic (same input = same output)
3. If deterministic: ONLY Level 5 (exact equality) is acceptable
4. Classify the assertion on the Assertion Strength Ladder
5. Construct a SPECIFIC, PLAUSIBLE broken production implementation
that would still pass this assertion
6. Report your verdict:
SURVIVED: [the broken implementation that passes]
LADDER: Level [N] - [name] - [BANNED/ACCEPTABLE/PREFERRED/GOLD]
DETERMINISTIC: [Yes/No - is the function under test deterministic?]
FIX: [what the assertion should be instead]
-- or --
KILLED: [why no plausible broken implementation survives]
LADDER: Level [N] - [name] - [BANNED/ACCEPTABLE/PREFERRED/GOLD]
DETERMINISTIC: [Yes/No]
A "plausible" broken implementation is one that could result from a
real bug (off-by-one, wrong variable, missing field, swapped arguments,
dropped output section) -- not adversarial construction (return the
exact expected string).
Summary format:
- Total assertions reviewed: N
- KILLED: N (with ladder levels)
- SURVIVED: N (with required fixes)
- BANNED (Level 1-2): N (immediate rejection)
- Pattern 10 violations (partial-to-partial): N
When dispatching a subagent to review a branch's changes (not a GitHub PR, but a local branch diff), the subagent MUST receive the actual diff, not just file paths.
Why: A file path points to the entire file. The subagent cannot distinguish code this branch changed from pre-existing code. It will flag pre-existing gaps as branch regressions, producing confidently wrong findings.
Step 1: Compute the diff before dispatch:
cd <worktree-or-repo-path> && git diff origin/master...HEAD
Step 2: Include in subagent prompt:
## Branch Review Context (MANDATORY)
- Branch: <branch-name>
- Working directory: <absolute-path>
- Merge base: origin/master
SCOPE CONSTRAINT: Only analyze code that appears in the diff below. Functions in
changed files that were NOT modified by this branch are OUT OF SCOPE. Do not flag
pre-existing issues as branch regressions.
VERIFICATION PREAMBLE: Before any other work, run:
cd <working-directory> && pwd && git branch --show-current
Verify you are in the correct directory on the correct branch. If not, stop and report the mismatch.
## Diff
<paste diff output here, or for large diffs, paste the --stat and
provide per-file diffs as separate sections>
If the diff is too large to inline, pre-compute the list of changed functions:
git diff origin/master...HEAD | grep -E '^\+.*def |^\+.*class |^@@' | head -50
Pass this as an explicit allow-list: "The following functions were added or modified. Only these are in scope."
REQUIRED when dispatching any subagent to review a PR (target is a PR number or URL, not a local branch).
Step 1 — Resolve review mode before dispatch:
# Get the PR HEAD SHA
PR_HEAD_SHA=$(gh pr view <PR_NUMBER> --json headRefOid --jq '.headRefOid')
# Check if a worktree exists for the PR branch
PR_BRANCH=$(gh pr view <PR_NUMBER> --json headRefName --jq '.headRefName')
WORKTREE_PATH=$(git worktree list --porcelain | grep -A2 "branch refs/heads/$PR_BRANCH" | grep "worktree" | awk '{print $2}')
| Condition | Review Mode | Agent Working Directory |
|-----------|-------------|------------------------|
| Worktree exists for PR branch | LOCAL_FILES | $WORKTREE_PATH |
| No worktree, local HEAD = PR HEAD SHA | LOCAL_FILES | Current repo root |
| No worktree, local HEAD ≠ PR HEAD SHA | DIFF_ONLY | N/A — use diff only |
Step 2 — Inject into subagent prompt:
## PR Review Context (MANDATORY — read before touching any file)
- PR: #<NUMBER>
- PR HEAD SHA: <SHA>
- Review mode: LOCAL_FILES | DIFF_ONLY
- Working directory: <WORKTREE_PATH or "use diff only">
- Changed files: <LIST>
REVIEW MODE INSTRUCTIONS:
- LOCAL_FILES: Safe to read files in <working_directory>. DO NOT read files outside this directory.
- DIFF_ONLY: DO NOT read any local files in the changed file set. The diff is the ONLY
authoritative source. Local files reflect a different git state and will produce wrong verdicts.
Any "not present" finding based on a local file read is WRONG in this mode.
<FORBIDDEN>
- Dispatching a PR review subagent without injecting PR HEAD SHA and review mode
- Dispatching in LOCAL_FILES mode without specifying the exact working directory (repo root or worktree path)
- Dispatching in DIFF_ONLY mode while pointing the agent at the local filesystem for review work
</FORBIDDEN>
| Anti-pattern | Problem | Fix | | ------------------- | --------------------------- | ------------------------------------------ | | "Fix all the tests" | Agent gets lost | Specify exact file/tests | | No error context | Agent guesses wrong | Paste actual error messages and test names | | No constraints | Agent refactors everything | Add "do NOT change X" | | "Fix it" output | You don't know what changed | Require cause+changes summary |
Scenario: 6 failures across 3 files post-refactor
Domain isolation:
Dispatch: 3 parallel agents, each scoped to one file
Results:
Integration: All fixes independent, zero conflicts, full suite green
Gain: N parallel problems resolved in time of slowest one (best case: N×)
Your job is to COORDINATE subagents, not to DO the work yourself. Every line of code you read or write in main context is WASTED TOKENS. </CRITICAL>
| Action | Why Forbidden | Correct Approach | | -------------------- | ------------------------------------------------ | ---------------------------- | | Reading source files | Bloats main context; triggers cascade reads | Dispatch explore subagent | | Writing/editing code | Implementation belongs in subagent | Dispatch TDD subagent | | Running tests | Test output bloats context | Subagent runs and summarizes | | Analyzing errors | Debugging is subagent work | Dispatch debugging subagent | | Searching codebase | Research is subagent work | Dispatch explore subagent |
Before EVERY action, ask yourself:
Am I about to read a source file? → STOP. Dispatch subagent.
Am I about to edit code? → STOP. Dispatch subagent.
Am I about to run a command? → STOP. Dispatch subagent.
Am I about to analyze output? → STOP. Dispatch subagent.
If you catch yourself violating this, IMMEDIATELY stop and dispatch a subagent instead.
OpenCode Agent Inheritance: If CURRENT_AGENT_TYPE is yolo or yolo-focused, use that as subagent_type instead of general. This ensures subagents inherit autonomous permissions.
</CRITICAL>
Task(
description: "[3-5 word summary]",
subagent_type: "[CURRENT_AGENT_TYPE or 'general']",
prompt: """
First, invoke the [SKILL-NAME] skill using the Skill tool.
Then follow its complete workflow.
## Context for the Skill
[ONLY provide context - file paths, requirements, constraints]
[DO NOT provide implementation instructions]
[DO NOT duplicate what the skill already knows]
"""
)
Agent Type Selection:
| Parent Agent | Subagent Type | Notes |
|--------------|---------------|-------|
| yolo | yolo | Inherit autonomous permissions |
| yolo-focused | yolo-focused | Inherit focused autonomous permissions |
| general or unknown | general | Default behavior |
| Any (exploration only) | explore | Read-only exploration tasks |
For external or untrusted content, load the security-trust-tiers skill for tier selection rules and context isolation protocol.
When dispatching a subagent to work in a worktree or alternate directory, include a verification preamble at the start of the prompt:
VERIFICATION PREAMBLE: Before any other work, run:
cd <worktree-path> && pwd && git branch --show-current
Verify you are at `<worktree-path>` on branch `<branch-name>`.
ALL file reads must use `<worktree-path>` as the base path.
ALL git commands must run from `<worktree-path>`.
Do NOT read files from `<main-repo-path>` -- that is a DIFFERENT branch.
This prevents the silent wrong-directory failure where a subagent reads files or runs git commands from the main repo (which is on a different branch) and produces wrong results with high confidence.
Every subagent prompt targeting a worktree MUST begin with:
BEFORE ANY WORK:
1. cd <WORKTREE_PATH> && pwd && git branch --show-current
2. Verify the branch is <EXPECTED_BRANCH>
3. ALL file paths must be absolute, rooted at <WORKTREE_PATH>
4. ALL git commands must run from <WORKTREE_PATH>
5. Do NOT create new branches. Work on the existing branch.
Why this matters: Without explicit path and branch verification, agents will:
When using isolation: "worktree": The worktree branches from the CURRENT branch at dispatch time. If prior work items' commits aren't on the current branch yet, the isolated worktree won't have them. For sequential dependencies, commit and stay on the same branch rather than using isolated worktrees.
WRONG - Doing work in main context:
Let me read the config file to understand the structure...
[reads file]
Now I'll update line 45 to add the new field...
[edits file]
RIGHT - Delegating to subagent:
Task(description: "Implement config field", prompt: "Invoke test-driven-development skill. Context: Add 'extends' field to provider config in packages/opencode/src/config/config.ts")
[waits for subagent result]
Subagent completed successfully. Proceeding to next task.
WRONG - Instructions in subagent prompt:
prompt: "Use TDD skill. First write a test that checks the extends field exists. Then implement by adding a z.string().optional() field after line 865. Make sure to update the description..."
RIGHT - Context only in subagent prompt:
prompt: "Invoke test-driven-development skill. Context: Add 'extends' field to Config.Provider schema. Location: packages/opencode/src/config/config.ts around line 865."
Before dispatching ANY subagent:
lines * 7Before completing:
<FINAL_EMPHASIS> Parallel dispatch is a force multiplier when used correctly, and a merge disaster when used carelessly. The independence gate is non-negotiable. Verify before dispatch, verify before integration. Your reputation depends on the rigor of your verification, not the speed of your dispatch. </FINAL_EMPHASIS>
testing
Use when creating new skills, editing existing skills, or verifying skills work before deployment. Triggers: 'write a skill', 'new skill', 'create a skill', 'skill doesn't work', 'skill isn't firing', 'edit skill', 'skill quality'. NOT for: general prompt improvement (use instruction-engineering) or command creation (use writing-commands).
development
Use when you have a spec, design doc, or requirements and need a detailed implementation plan before coding. Triggers: 'write a plan', 'create implementation plan', 'plan this out', 'break this down into steps', 'convert design to tasks', 'implementation order'. Also invoked by develop during planning. NOT for: reviewing existing plans (use reviewing-impl-plans).
testing
Use when creating new commands, editing existing commands, or reviewing command quality. Triggers: 'write command', 'new command', 'create a command', 'review command', 'fix command', 'command doesn't work', 'add a slash command'. NOT for: skill creation (use writing-skills).
development
Use when about to claim discovery during debugging. Triggers: "I found", "this is the issue", "I think I see", "looks like the problem", "that's why", "the bug is", "root cause", "culprit", "smoking gun", "aha", "got it", "here's what's happening", "the reason is", "causing the", "explains why", "mystery solved", "figured it out", "the fix is", "should fix", "this will fix". Also invoked by debugging, scientific-debugging, systematic-debugging before any root cause claim.