| name | skill-team-research |
| description | Orchestrate multi-agent research with wave-based parallel execution. Spawns 2-4 teammates for diverse investigation angles and synthesizes findings. |
| allowed-tools | Agent, Bash, Edit, Read, Write |
Team Research Skill
Multi-agent research with wave-based parallelization. Spawns 2-4 teammates to investigate complementary angles, then synthesizes findings into a unified report.
Task-Type-Aware Routing: Teammates are spawned with task-type-appropriate prompts and tools. Meta tasks focus on .claude/ system patterns; general tasks use web search and codebase exploration.
IMPORTANT: This skill requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 environment variable. If team creation fails, gracefully degrades to single-agent research via skill-researcher.
Context References
Reference (load as needed during synthesis):
- Path:
.claude/context/patterns/team-orchestration.md - Wave coordination patterns
- Path:
.claude/context/formats/team-metadata-extension.md - Team result schema
- Path:
.claude/context/formats/return-metadata-file.md - Base metadata schema
- Path:
.claude/context/reference/team-wave-helpers.md - Reusable wave patterns
Trigger Conditions
This skill activates when:
/research N --team is invoked
- Task exists and status allows research
- Team mode is requested via --team flag
Input Parameters
| Parameter | Type | Required | Description |
|---|
task_number | integer | Yes | Task to research |
focus_prompt | string | No | Optional focus for research |
team_size | integer | No | Number of teammates (2-4, default 2) |
session_id | string | Yes | Session ID for tracking |
model_flag | string | No | Model override (haiku, sonnet, opus, fable). If set, use instead of default |
effort_flag | string | No | Effort level (fast, hard). Passed as prompt context |
Execution Flow
Stage 1: Input Validation
Validate required inputs:
task_number - Must exist in state.json
team_size - Clamp to range [2, 4], default 2
task_data=$(jq -r --argjson num "$task_number" \
'.active_projects[] | select(.project_number == $num)' \
specs/state.json)
if [ -z "$task_data" ]; then
return error "Task $task_number not found"
fi
task_type=$(echo "$task_data" | jq -r '.task_type // "general"')
status=$(echo "$task_data" | jq -r '.status')
project_name=$(echo "$task_data" | jq -r '.project_name')
description=$(echo "$task_data" | jq -r '.description // ""')
team_size=4
Stage 2 + Stage 3: Preflight Status Update and Postflight Marker
Source skill-base.sh once, then follow @.claude/context/patterns/skill-preflight-flow.md in
full for Stage 2 (preflight status update) and Stage 3 (marker creation):
source .claude/scripts/skill-base.sh
padded_num=$(printf "%03d" "$task_number")
skill_name="skill-team-research"
operation="research"
Routing fix: this call replaces a hand-rolled state-write.sh status write with
update-task-status.sh preflight (via skill_preflight_update), which regenerates TODO.md
internally — TODO.md's Task Order block is therefore no longer stale for the whole duration of a
team run, since it is now refreshed at preflight, not only at postflight.
operation="research" (not "team-research") is required here: update-task-status.sh's
target_status vocabulary is research/plan/implement/pr_ready/partial/blocked — there
is no team-research value, so this skill maps onto the plain research operation, same as
skill-researcher.
Marker unification note: this skill's marker previously carried "Shape D" — a team_size
field and no created/stop_hook_active. skill_create_postflight_marker's fixture test asserts
an EXACT Shape A key set, so team_size is dropped here rather than carried as an extra field;
the marker's operation field now reads "research" (matching $operation above) rather than
"team-research".
Stage 4: Check Team Mode Availability
Verify Agent Teams feature is available:
if [ "$CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS" != "1" ]; then
echo "Warning: Team mode unavailable, falling back to single agent"
fi
Stage 4a: Fallback to Single Agent
If team mode is unavailable:
- Log warning about degradation.
- Invoke the underlying single-agent subagent directly via the Agent tool
(
subagent_type: "general-research-agent", the same subagent skill-researcher's own Stage 5
invokes) — passing the same task_context/delegation_context/format-specification this skill
would otherwise have assembled per-teammate. Do NOT invoke the whole skill-researcher
skill (via Skill tool or otherwise): that would re-run its own full preflight/postflight
lifecycle on top of this skill's, double-writing status and markers. Invoking the subagent
directly is the fix for the defect this stage previously carried — a wholesale re-delegation
to skill-researcher produced no return metadata of this skill's own, since skill-researcher
consumed and cleaned up its own copy before this skill's postflight ever ran.
- Add
degraded_to_single: true to the metadata the subagent writes is not possible (the
subagent's .return-meta.json schema does not carry this field) — instead, record the
degradation via a distinct marker this skill controls: append a JSON line to
specs/${padded_num}_${project_name}/.degraded-fallback-note.json before invoking the
subagent ({"degraded_to_single": true, "reason": "team mode unavailable"}), and merge that
flag into Stage 11's metadata-write content when composing the final team execution summary.
- Follow
@.claude/context/patterns/skill-self-execution-fallback.md's write obligation as
Stage 4c below describes: the directly-invoked subagent already writes .return-meta.json
(satisfying the obligation), so Stage 4c is a no-op in the direct-subagent case — it exists as
the actual write path only for the rarer case where this skill performs work inline without
invoking any subagent at all.
- Continue with postflight — the resulting
.return-meta.json is read exactly like the normal
team-synthesis path (Stage 10 onward).
Stage 4c: Self-Execution Fallback
Heading-collision note: this skill's existing Stage 5b is "Task Type Routing Decision", an
unrelated concept — the self-execution fallback is placed here at Stage 4c instead, immediately
after Stage 4a/Stage 4 (degraded-path detection), to avoid reusing that number.
Follow @.claude/context/patterns/skill-self-execution-fallback.md in full. This skill's success
status value for that block's write obligation is "researched". As Stage 4a Step 4 notes, this
stage is reached in its "real write" capacity only when this skill performed work inline without
invoking any subagent at all — the normal team-wave path (Stage 5 onward) and the degraded direct-
subagent path (Stage 4a) both already produce their own .return-meta.json.
Stage 5a: Calculate Artifact Number
Read next_artifact_number from state.json (or fall back to directory scanning for legacy tasks):
artifact_number=$(jq -r --argjson num "$task_number" \
'.active_projects[] | select(.project_number == $num) | .next_artifact_number // 1' \
specs/state.json)
if [ "$artifact_number" = "null" ] || [ -z "$artifact_number" ]; then
padded_num=$(printf "%03d" "$task_number")
count=$(ls "specs/${padded_num}_${project_name}/reports/"*[0-9][0-9]*.md 2>/dev/null | wc -l)
artifact_number=$((count + 1))
fi
padded_num=$(printf "%03d" "$task_number")
max_on_disk=$(find "specs/${padded_num}_${project_name}" -name "[0-9][0-9]_*.md" 2>/dev/null \
| sed 's|.*/\([0-9][0-9]\)_.*|\1|' | sort -n | tail -1)
max_on_disk=${max_on_disk:-0}
max_on_disk=$((10#$max_on_disk))
if [ "$artifact_number" -le "$max_on_disk" ]; then
artifact_number=$((max_on_disk + 1))
bash .claude/scripts/state-write.sh \
'(.active_projects[] | select(.project_number == $num)).next_artifact_number = $new_num' \
--session-id "$session_id" \
--argjson num "$task_number" --argjson new_num "$artifact_number"
fi
run_padded=$(printf "%02d" "$artifact_number")
while ls "specs/${padded_num}_${project_name}/reports/${run_padded}_"*.md 2>/dev/null | grep -q .; do
artifact_number=$((artifact_number + 1))
run_padded=$(printf "%02d" "$artifact_number")
done
Note: Team research uses the same artifact number for all teammates and synthesis. The artifact number advances after all teammates and synthesis complete.
Stage 5b: Task Type Routing Decision
Determine task-type-specific configuration for teammate prompts:
case "$task_type" in
"meta")
context_refs="@.claude/CLAUDE.md, @.claude/context/index.json"
available_tools="Read, Grep, Glob"
;;
*)
context_refs=""
available_tools="WebSearch, WebFetch, Read, Grep, Glob"
;;
esac
teammate_model="${model_flag:-sonnet}"
model_preference_line="Model preference: Use Claude ${teammate_model^} for this analysis."
Stage 5: Spawn Research Wave
Create teammate prompts and spawn wave. Pass artifact_number and teammate_letter to each teammate.
Delegation context for teammates:
{
"artifact_number": "{run_padded}",
"teammate_letter": "a",
"artifact_pattern": "{NN}_teammate-{letter}-findings.md",
"roadmap_path": "specs/ROADMAP.md"
}
Teammate A - Primary Angle:
Research task {task_number}: {description}
{model_preference_line}
Artifact number: {run_padded}
Teammate letter: a
Focus on implementation approaches and patterns.
Challenge assumptions and provide specific examples.
Consider {focus_prompt} if provided.
Output your findings to:
specs/{NNN}_{SLUG}/reports/{run_padded}_teammate-a-findings.md
Format: Markdown with clear sections for:
- Key Findings
- Recommended Approach
- Evidence/Examples
- Confidence Level (high/medium/low)
Teammate B - Alternative Approaches:
Research task {task_number}: {description}
{model_preference_line}
Artifact number: {run_padded}
Teammate letter: b
Focus on alternative patterns and prior art.
Look for existing solutions we could adapt.
Do NOT duplicate Teammate A's focus on primary approaches.
Output your findings to:
specs/{NNN}_{SLUG}/reports/{run_padded}_teammate-b-findings.md
Format: Same as Teammate A
Teammate C - Critic (always present):
Research task {task_number}: {description}
{model_preference_line}
Artifact number: {run_padded}
Teammate letter: c
You are the Critic. Your job is to identify gaps, shortcomings, and blind spots in the research.
Focus on:
- What assumptions haven't been validated?
- What could the other researchers be missing or getting wrong?
- Are there known limitations in the proposed approaches?
- Is the task scope complete, or are there important aspects being overlooked?
- What questions should be asked but aren't being asked?
Do NOT duplicate risk analysis (implementation risks). Focus on research quality and completeness.
Output your findings to:
specs/{NNN}_{SLUG}/reports/{run_padded}_teammate-c-findings.md
Format: Same as Teammate A
Teammate D - Horizons (always present):
Research task {task_number}: {description}
{model_preference_line}
Artifact number: {run_padded}
Teammate letter: d
You are the Horizons researcher. Your job is to think about long-term alignment and strategic direction.
Read the project roadmap at {roadmap_path} (from delegation context) if it exists.
If the roadmap file does not exist, contribute general strategic thinking about project direction.
Focus on:
- Does the proposed approach align with the project's long-term goals and priorities?
- Are there opportunities to advance adjacent roadmap items simultaneously?
- Could the task be scoped differently to better serve the project trajectory?
- What creative or unconventional approaches might better serve the long-term vision?
- What strategic challenges remain that this task could help address?
Think outside the box. Challenge conventional approaches where a better path exists.
Output your findings to:
specs/{NNN}_{SLUG}/reports/{run_padded}_teammate-d-findings.md
Format: Same as Teammate A
Spawn teammates using Agent tool.
IMPORTANT: Pass the model parameter to enforce model selection:
- Use
model: "${teammate_model}" (from Stage 5b: model_flag if provided, otherwise "sonnet" as default)