From sw
Orchestrates parallel multi-agent work across domains — brainstorm, plan, implement, review, research, or test. Auto-detects mode and spawns agents via Claude Code's native Agent Teams.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sw:team-leadThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Plan and launch parallel development agents across domains using Claude Code's native Agent Teams.**
agents/_protocol.mdagents/architect.mdagents/backend.mdagents/brainstorm-advocate.mdagents/brainstorm-critic.mdagents/brainstorm-pragmatist.mdagents/database.mdagents/frontend.mdagents/pm.mdagents/researcher.mdagents/reviewer-security.mdagents/security.mdagents/testing.mdreference/dynamic-workflows.mdPlan and launch parallel development agents across domains using Claude Code's native Agent Teams.
spec.md once for fan-out decisions and read agent prompt templates under plugins/specweave/skills/team-lead/agents/. During the active phase, prefer PLAN_READY summaries from agents over re-reading full plan files.specweave doctor, ls ~/.claude/teams/, grep metadata.json) and run CLI-only operations — never to implement code.reference/dynamic-workflows.md.You are an ORCHESTRATOR. You do NOT implement, review, or analyze code yourself.
TeamCreate and spawn agents via Task()Bash, Edit, Read, or Agent to do the actual work yourself--parallel flag is set. For 1-domain or <15-task work, execute directly without spawning.TeamCreate, Task, SendMessage, Workflow (for batch-class fan-out per §0.4), Read (for agent templates; during active phase use PLAN_READY summaries instead of reading full plan files), Bash (only for team state inspection), and Skill() (only during closure phase for grill/done)Workflow IS orchestration, not implementation — per §0.4 you MAY launch a Workflow() for batch-class work (migrations, repo-wide audits, high-stakes verification, deep research). Delegating to a Workflow does NOT violate this rule; writing the code yourself does.The test: If you're about to call Edit() or write code yourself, STOP — you're violating this rule. (Launching a Workflow() that spawns agents to do the work is fine.)
Before mode detection or any other step, clean up stale teams from previous runs in this session.
First team-lead invocation in this session: Nothing to clean. Proceed to Section 0.
Repeat invocation (you previously ran team-lead and remember the team name + agent names):
shutdown_request to each agent you previously spawned:
SendMessage({ type: "shutdown_request", recipient: "<previous-agent-name>" });
TeamDelete() with the previous team nameTeamDelete fails (agents still shutting down), wait 3 seconds, retry onceUse a unique team name for each invocation to avoid collisions:
impl-checkout-1, impl-checkout-2review-auth-{timestamp}Do NOT inspect the filesystem (ls, jq, reading config files). You either know the previous team name from this session, or there is nothing to clean.
sw:team-lead "<feature description>" [OPTIONS]
| Option | Description | Default |
|---|---|---|
--dry-run | Show proposed agent plan without launching | false |
--mode | Force operating mode: brainstorm, plan, implement, review, research, test | auto-detect |
--domains | Override domain detection (e.g., --domains frontend,backend,testing) | auto-detect |
--max-agents | Maximum number of concurrent agents | 6 |
--preset | Use a named agent configuration (e.g., --preset full-stack). Presets are shortcuts for common domain combinations. Available: full-stack, api-only, frontend-only, microservice. | — |
Presets expand into a pre-defined --domains set so you don't have to spell them out. A preset is applied before domain auto-detection and is overridden by an explicit --domains flag.
| Preset | Domains | Typical Use |
|---|---|---|
full-stack | frontend, backend, database, testing | Full web app increments that touch every layer |
api-only | backend, database, testing | Pure API work with no UI |
frontend-only | frontend, testing | UI-only increments (design, styling, components) |
microservice | backend, testing, devops | Single-service increments with deployment concerns |
Usage:
sw:team-lead --preset full-stack "Build checkout flow"
sw:team-lead --preset api-only --max-agents 4 "Add payments API"
--preset supersedes the deprecated sw:team-build skill — same preset names are honoured here.
Detect operating mode FIRST. This determines the entire workflow path.
--mode brainstorm|plan|implement|review|research|testreview-*, brainstorm-*, research-*, plan-*, test-*| Keywords | Mode | Go To |
|---|---|---|
| "brainstorm", "ideate", "explore ideas", "what if", "pros and cons" | BRAINSTORM | Section 0a |
| "plan", "spec", "design", "architect", "define requirements" | PLANNING | Section 0b |
| "implement", "build", "code", "develop" (or default) | IMPLEMENTATION | Section 1 |
| "review", "audit", "check code", "review PR", "code quality" | REVIEW | Section 0c |
| "research", "investigate", "analyze", "explore codebase" | RESEARCH | Section 0d |
| "test", "write tests", "test strategy", "test coverage" | TESTING | Section 0e |
| Mode | Increment? | Agent Templates | Coordination | Output |
|---|---|---|---|---|
| BRAINSTORM | No | brainstorm-advocate, brainstorm-critic, brainstorm-pragmatist | Parallel → synthesize | Decision matrix |
| PLANNING | Creates one | pm, architect (+ optional security reviewer) | PM + Architect parallel (Architect explores while PM specs) | spec.md, plan.md, tasks.md |
| IMPLEMENTATION | Required | backend, frontend, database, testing, security | Contract-first phases | Working code |
| REVIEW | Optional | Delegates to sw:code-reviewer | Parallel | Review report |
| RESEARCH | No | researcher (1-3 instances) | Parallel → merge | Research report |
| TESTING | Required | testing (split by layer) | Parallel | Test suites |
team_name: brainstorm-{topic-slug}
Engine (per §0.4): Agent Teams — brainstorm needs interactive steering + the idea tree, not a deterministic batch. Pattern: perspective-diverse verify (advocate / critic / pragmatist fan out → synthesize).
Skip increment pre-flight entirely. Brainstorm doesn't need a spec — it explores possibilities.
TeamCreate({ team_name: "brainstorm-{slug}", description: "Brainstorm: {topic}" })agents/brainstorm-advocate.md, agents/brainstorm-critic.md, agents/brainstorm-pragmatist.md[BRAINSTORM_QUESTION] with the user's question/topicteam_name so agents join the team (and get tmux panes):
Task({
team_name: "brainstorm-{slug}",
name: "brainstorm-advocate",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced brainstorm-advocate.md content>
})
Task({
team_name: "brainstorm-{slug}",
name: "brainstorm-critic",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced brainstorm-critic.md content>
})
Task({
team_name: "brainstorm-{slug}",
name: "brainstorm-pragmatist",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced brainstorm-pragmatist.md content>
})
STATUS: heartbeats (not task-granularity T-{N}/{total}).
Wait patiently for PERSPECTIVE_COMPLETE: messages — expected 2-5 minutes per agent.
Do NOT send STATUS_CHECK or shutdown_request while agents are working.
The only valid intervention is responding to BLOCKING_ISSUE: messages.PERSPECTIVE_COMPLETE: messages before proceeding. Do NOT start synthesis after receiving only 1 or 2.sw:increment to formalize the chosen approach."shutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesteam_name: plan-{feature-slug}
Planning mode runs PM and Architect agents in parallel for richer, faster spec creation.
Check for existing increment:
Spawn PM + Architect in parallel (TRUE parallelism):
agents/pm.md, replace [INCREMENT_ID], [MASTER_INCREMENT_PATH], [FEATURE_DESCRIPTION]agents/architect.md, replace [INCREMENT_ID], [MASTER_INCREMENT_PATH]team_name:
Task({
team_name: "plan-{feature-slug}",
name: "pm-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced pm.md content>
})
Task({
team_name: "plan-{feature-slug}",
name: "architect-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced architect.md content>
})
agents/reviewer-security.md, replace [REVIEW_TARGET] with the spec, spawn Security reviewer after PM signals PLAN_READY:COMPLETION: messagesWhy this works: Architect's workflow has two phases — exploration (no spec.md needed) and design (needs spec.md). By spawning both agents simultaneously, the Architect's exploration phase (~30s) overlaps with PM's spec writing, reducing total wall-clock time.
Post-planning:
specweave sync-living-docs {increment-id} to sync external toolssw:do, sw:auto, or sw:team-lead (implementation mode)Cleanup (ALL 3 phases from Step 9 — NEVER skip Phase 3):
shutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesSTOP — do not proceed to implementation sections
Delegates entirely to sw:code-reviewer.
Team-lead does NOT spawn its own reviewer agents for review mode. The code-reviewer skill handles its own orchestration with 6 specialized reviewers.
Skill({ skill: "sw:code-reviewer", args: "<user's review target or flags>" })
Pass through any arguments the user provided (--pr N, --changes, --cross-repo, path).
STOP after the skill completes — do not proceed to implementation sections.
team_name: research-{topic-slug}
Engine (per §0.4): prefer a Dynamic Workflow deep-research pipeline (fan-out searches → fetch → adversarially verify → synthesize a cited report, results held off-context) for multi-source / multi-subtopic research; use Agent Teams only for 2-3 steerable researchers. Falls back to Agent Teams when quality.workflows.enabled is off.
Skip increment pre-flight. Research is exploratory — no spec needed.
TeamCreate({ team_name: "research-{slug}", description: "Research: {topic}" })agents/researcher.md[RESEARCH_TOPIC] and [RESEARCH_SCOPE] in each agent promptteam_name:
Task({
team_name: "research-{slug}",
name: "researcher-{scope}",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced researcher.md content>
})
RESEARCH_COMPLETE: messagessw:increment (to act on findings) or sw:brainstorm (to explore approaches)shutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesteam_name: test-{increment-id}
Engine (per §0.4): route many independent same-shape tests to a Dynamic Workflow (generate → run → fix-loop until green); keep Agent Teams when test layers have setup dependencies. Falls back to Agent Teams when quality.workflows.enabled is off.
Testing mode requires an increment (it needs to know WHAT to test).
TeamCreate({ team_name: "test-{id}", description: "Testing: {increment}" })agents/testing.md, override scope to unit tests onlyagents/testing.md, override scope to E2E tests onlyteam_name:
Task({
team_name: "test-{id}",
name: "unit-test-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced testing.md content with unit-test scope>
})
Task({
team_name: "test-{id}",
name: "e2e-test-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced testing.md content with e2e scope>
})
COMPLETION: messagesnpx vitest run + npx playwright testshutdown_request to each agentTeamDelete() (retry once after 3s if it fails)SendMessage shutdown does NOT close tmux panes, this script is the ONLY thing that doesRun AFTER §0 Mode Detection, BEFORE §0.5 Increment Pre-Flight. Pick the engine from the shape of the work, not from the user's words. The user must NEVER have to say "use a workflow" — you infer it.
Three engines:
| Engine | What it is | Owns |
|---|---|---|
| Dynamic Workflow | Workflow() — deterministic JS scheduler, ≤16 concurrent / 1000 total subagents, results in script vars (off context), resumable, background | Large homogeneous fan-out: migrations, repo-wide audits, many-similar-tests, adversarial/judge verification |
| Agent Teams (default) | TeamCreate + Task + SendMessage + tmux — model-driven, domain-aware, SpecWeave-lifecycle owner | Feature work: 3+ domains or 15+ tasks with cross-domain contracts + closure + sync |
| Inline | This orchestrator, no spawn | <15 tasks, single domain, sequential |
| Signal in the work | Engine | Why |
|---|---|---|
| ≥~25 same-shape tasks, no cross-task deps (rename X→Y across N files, add header to N modules, port N tests) | Dynamic Workflow (top-level, bypass team-lead) | Pure fan-out under ONE budget + ONE scheduler — no glue needed |
| Codebase migration / repo-wide audit / lint-sweep / dependency-bump across many files | Dynamic Workflow (top-level) | Domain-blind batch; team-lead's lifecycle is dead weight here |
| High-stakes verification needing N independent checks (adversarial-verify, judge-panel, completeness-critic) | Dynamic Workflow (top-level) | Built-in reusable patterns; deterministic reduce |
| Deep research spanning many sources/subtopics | Dynamic Workflow (pipeline) | fan-out → fetch → verify → synthesize, results off-context |
| 3+ domains OR 15+ tasks with cross-domain contracts (frontend ⇐ OpenAPI ⇐ schema), needs increment activation + closure + GitHub/Jira/ADO sync | Agent Teams | Phased dependencies defeat fan-out; only team-lead owns the SpecWeave contract |
| A single Agent-Teams domain agent discovers its OWN task list is a ≥~25 same-shape batch | Agent Teams + inner Workflow ×1 (see agents/_protocol.md Workflow Mode) | Legal one-level borrow; team-lead stays outer coordinator |
| <15 tasks, 1 domain, sequential | Inline | Spawning overhead unjustified |
migrate, migration, port, rename across, repo-wide, codebase-wide, audit, sweep, bulk, every file, all <N> …, double-check, verify independently, judge, tournament, deep research, survey the literature, ultracode keyword / /effort ultracode.build <feature>, team, parallel agents, multi-domain, increment with 3+ domains, contracts (Prisma/OpenAPI/shared types) in scope, anything needing sw:done/sync.quality.workflows.enabled is absent or false, do NOT auto-fire a Workflow and do NOT honor the inner borrow; fall back to Agent Teams / inline (classic behavior, byte-for-byte). This is what keeps the enhancement non-destructive.quality.workflows.perRunTokenBudget + maxConcurrentWorkflows from config. If a route would exceed either, DOWNGRADE to inline/sequential and tell the user.Workflow() allows ONE nesting level and THROWS inside a leaf subagent. Legal chain: team-lead (orchestrator, not a Workflow) → Task member → Workflow ×1 → leaves (cannot nest). team-lead may fire a top-level Workflow OR delegate the borrow to a member — never both for the same work.Workflow with parallel() over the items (one budget, one scheduler) instead of N domain agents each launching their own.See reference/dynamic-workflows.md for primitives, quality patterns, and the full quality.workflows config schema.
This section applies only to IMPLEMENTATION mode (default) and TESTING mode. All other modes handle their own increment logic (or skip it entirely) in Section 0a-0e above.
The team-lead works best with an increment (spec.md, plan.md, tasks.md) but can also run without one in free-form mode.
Free-form mode (no increment needed) applies when:
SPECWEAVE_NO_INCREMENT=1 is set (via specweave team --no-increment)In free-form mode: skip the rest of Section 0.5 and proceed directly to Step 1. Agents will work from the natural language description instead of a spec. Note: without a spec, sw:done closure is not available — the team-lead simply coordinates agent completion.
# Single-repo
find .specweave/increments -maxdepth 2 -name "spec.md" 2>/dev/null | head -5
# Multi-repo (umbrella)
find repositories -path "*/.specweave/increments/*/spec.md" -maxdepth 6 2>/dev/null | head -5
Do NOT ask permission. Invoke the increment skill with the user's feature description:
Skill({ skill: "sw:increment", args: "the user's feature description" })
Wait for sw:increment to complete (spec.md, plan.md, tasks.md created and user exits plan mode). Then continue to Step 1.
If sw:increment fails (user rejects plan, skill errors, etc.): STOP. Do NOT proceed.
Report the failure to the user and ask them to run sw:increment manually.
Read the increment's spec.md. This is the source of truth for all agent work:
Store the increment path as MASTER_INCREMENT_PATH — you will reference it in agent prompts.
WHY THIS MATTERS: Without a spec, agents infer scope from natural language alone. This leads to uncoordinated implementation, scope creep, and missing acceptance criteria. The spec-first principle exists because specs are the contract between user intent and agent execution.
Before spawning ANY agents, transition the master increment to "active" status. The specweave complete command silently exits on increments with "planned" or "backlog" status — if you skip this step, closure will fail.
# Read current status
STATUS=$(jq -r '.status' [MASTER_INCREMENT_PATH]/metadata.json)
# If not already active, activate it
if [ "$STATUS" != "active" ] && [ "$STATUS" != "ready_for_review" ]; then
# Edit metadata.json: set status to "active" and update lastActivity
Edit metadata.json:
"status": "planned" → "status": "active"
"lastActivity": "<current ISO timestamp>"
fi
Why: Agents implement tasks but don't manage the increment lifecycle. The team-lead owns status transitions — activate before work begins, close after work completes.
| Action | Tool | Parameters |
|---|---|---|
| Create team | TeamCreate | team_name, description |
| Spawn agent | Task | team_name, name, subagent_type, prompt, mode: "bypassPermissions" |
| Send message | SendMessage | type, recipient, content, summary |
| Shutdown agent | SendMessage | type: "shutdown_request", recipient |
| Run batch fan-out | Workflow | script (a meta literal + agent()/parallel()/pipeline()) — for batch-class work per §0.4; see reference/dynamic-workflows.md |
Analyze the feature request and map affected domains to SpecWeave skills.
| Domain | Primary Skill | Additional Skills | When to Use |
|---|---|---|---|
| Frontend | sw:architect | — | UI components, pages, client-side state |
| Backend | sw:architect | infra:devops | API endpoints, services, business logic |
| Database | sw:architect | Schema design, migrations, seed data | |
| Shared/Types | sw:architect | sw:code-simplifier | TypeScript interfaces, shared constants, API contracts |
| Testing | sw:e2e | sw:tdd-red, sw:validate | Test strategy, E2E suites, integration tests |
| Security | sw:security | security:patterns | Auth, authorization, threat modeling, OWASP |
| DevOps | infra:devops | k8s:deployment-generate, infra:observability | CI/CD, Docker, K8s, monitoring |
| Mobile | mobile:react-native | mobile:screen-generate, mobile:expo | Native/cross-platform mobile apps |
| ML | ml:engineer | ml:pipeline, ml:deploy | Model training, inference pipelines, deployment |
The orchestrator infers domains from the feature description and codebase structure (e.g., src/components/ signals Frontend, prisma/ signals Database, src/api/ signals Backend, tests/ signals Testing, auth-related keywords signal Security, Docker/K8s/CI files signal DevOps, React Native/Flutter signal Mobile, model/pipeline keywords signal ML).
Agents are NOT all spawned simultaneously. The orchestrator follows a two-phase dependency protocol to prevent integration conflicts.
| Artifact | Location | Producer | Consumers |
|---|---|---|---|
| TypeScript interfaces | src/types/ or src/shared/types/ | Shared/Types agent | Frontend, Backend, Testing |
| Prisma schema | prisma/schema.prisma | Database agent | Backend, Testing |
| OpenAPI spec | openapi.yaml or src/api/openapi.yaml | Backend agent | Frontend, Testing |
| GraphQL schema | schema.graphql | Backend agent | Frontend, Mobile |
| API route types | src/api/types/ | Backend agent | Frontend |
The orchestrator MUST resolve the actual organization/owner name before spawning ANY agents.
All {ORG} placeholders below must be replaced with the real value.
Discovery chain (in order of priority):
repository.organization):ORG=$(jq -r '.repository.organization // empty' .specweave/config.json 2>/dev/null)
if [ -z "$ORG" ]; then
ORG=$(jq -r '[.sync.profiles[].config.owner // .sync.profiles[].config.organization] | map(select(. != null)) | first // empty' .specweave/config.json 2>/dev/null)
fi
if [ -z "$ORG" ]; then
ORG=$(jq -r '.umbrella.childRepos[0].path // empty' .specweave/config.json 2>/dev/null | sed 's|repositories/||' | cut -d/ -f1)
fi
if [ -z "$ORG" ]; then
ORG=$(ls -d repositories/*/ 2>/dev/null | head -1 | xargs basename 2>/dev/null)
fi
NEVER read org from .env files. Organization belongs in .specweave/config.json.
When umbrella.enabled: true in config.json, ALL increments go in the umbrella root .specweave/increments/ — NOT in child repos. Use the project field in metadata.json to route increments to the correct child repo context.
# CORRECT: All increments at umbrella root, tagged by project
umbrella-project/
├── .specweave/config.json
├── .specweave/increments/
│ ├── 0001-domain-models/ # metadata.json: "project": "sw-ecom-domain"
│ ├── 0002-shared-types/ # metadata.json: "project": "sw-ecom-shared"
│ └── 0003-api-endpoints/ # metadata.json: "project": "sw-ecom-api"
├── repositories/
│ ├── {ORG}sw-ecom-domain/ # NO .specweave/increments/ here
│ ├── {ORG}sw-ecom-shared/ # NO .specweave/increments/ here
│ └── {ORG}sw-ecom-api/ # NO .specweave/increments/ here
# WRONG: Increments inside child repos
umbrella-project/
├── repositories/{ORG}sw-ecom-domain/
│ └── .specweave/increments/0001-domain-models/ # WRONG!
Rules:
.specweave/increments/ inside child repos under repositories/specweave init in child repos — the umbrella root owns all incrementsrepositories/, but increments stay at umbrella root{ORG} with the actual organization discovered aboveContract chain order: shared/types -> database -> backend -> frontend (upstream before downstream).
Spawn agents that produce shared contracts. These MUST complete before downstream agents begin.
Upstream agents (spawn first, wait for completion):
Phase 1: Upstream
├── Shared/Types Agent -> produces interfaces, enums
└── Database Agent -> produces schema, migrations
[WAIT for Phase 1 completion via CONTRACT_READY messages]
Once upstream contracts are established, spawn downstream agents in parallel.
Downstream agents (spawn in parallel after Phase 1):
Phase 2: Downstream (parallel)
├── Backend Agent (reads types + schema)
├── Frontend Agent (reads types + API spec)
├── Testing Agent (reads all contracts)
├── Security Agent (reads all code)
└── DevOps Agent (reads all code)
If the feature has no cross-domain dependencies (e.g., purely frontend work with no new types), skip Phase 1 and spawn all agents in parallel immediately.
Analyze domains
│
├── Any upstream domains (shared/types, database)?
│ YES -> Phase 1: spawn upstream, wait for contracts
│ Phase 2: spawn downstream in parallel
│ NO -> Spawn all agents in parallel (no dependency)
│
└── Single domain?
YES -> Spawn single agent, no orchestration needed
The team lead reviews agent plans asynchronously. Agents do NOT wait for approval — they proceed to implementation immediately after creating plans and sending a notification.
The previous blocking handshake (where agents waited for explicit approval before implementing) caused sessions to freeze:
Async review eliminates the bottleneck: agents proceed immediately, and the team-lead only intervenes when something is wrong.
All agents MUST be spawned with mode: "bypassPermissions". This is required because:
bypassPermissions, agents get STUCK waiting for trust confirmation and never executeNEVER use mode: "plan" for agent spawns — it causes agents to block on the trust-folder prompt.
Agent side (built into every agent prompt template):
SendMessage({
type: "message",
recipient: "team-lead",
content: "PLAN_READY: Created .specweave/increments/[ID]/\nTasks: [count]\nACs covered: [list AC-IDs]\nKey decisions: [1-2 sentence summary]\nFiles to create/modify: [file list]\nArchitecture: [pattern/approach chosen]",
summary: "Plan ready — proceeding to implementation"
});
PLAN_CORRECTION during implementation:
STATUS: Applied PLAN_CORRECTION. Revised [what changed]. Continuing from T-{N}.Team-lead side:
PLAN_READY notification from agent// Correct a plan issue (agent is already implementing)
SendMessage({
type: "message",
recipient: "database-agent",
content: "PLAN_CORRECTION: 1) Add index on user_id for sessions. 2) You're missing AC-US1-03 — add a task for it. Pause current work and revise before continuing.",
summary: "Plan needs correction"
});
PLAN_CORRECTION (continues without revising after 2 turns):SendMessage({ type: "shutdown_request", recipient: "database-agent" });
// Report to user: "Agent ignored correction, shutting down. Manual intervention needed."
Not all plans need deep review. Prioritize:
For very large features, the team lead MAY split work into multiple increments per domain for better tracking and independent closure. Decide this during initial analysis (Step 1), before spawning agents.
Maximum 40 tasks per agent (TASK_CAP = 40). Raised in SpecWeave 1.1.0 from the previous cap: Opus 4.7's long-horizon coherence improvements mean agents can maintain coherent context across 40 tasks without degradation.
When distributing tasks from the master spec:
jira-agent-a, jira-agent-b) with non-overlapping task rangesDomain tasks analysis:
Frontend: 32 tasks -> 1 agent (OK)
Backend: 18 tasks -> 1 agent (OK)
JIRA: 55 tasks -> SPLIT into 2 agents (tasks 1-28, tasks 29-55)
Why: Each auto-mode iteration adds context (spec reads, edits, test outputs). Prior to 4.7, a 15-task cap was necessary because older models entered deep reasoning loops and effectively hung past ~20 tasks. Opus 4.7's long-horizon coherence holds across substantially more work, so the safe budget is now 40. Above 40, we still split to prevent edge-case context blowups.
Agent definitions live as reusable .md files in the agents/ subdirectory. When spawning a domain agent, Read the agent file and use its full content as the Task() prompt, with placeholders replaced.
| Agent | File | Domain | Phase | Primary Skills |
|---|---|---|---|---|
| Frontend | agents/frontend.md | UI, components, pages | 2 (downstream) | sw:architect |
| Backend | agents/backend.md | API, services, middleware | 2 (downstream) | sw:architect, infra:devops |
| Database | agents/database.md | Schema, migrations, seeds | 1 (upstream) | sw:architect |
| Testing | agents/testing.md | Unit, integration, E2E | 2 (downstream) | sw:e2e, sw:tdd-red |
| Security | agents/security.md | Auth, validation, audit | 2 (downstream) | sw:security |
For each domain agent to spawn:
Read("agents/{domain}.md")[INCREMENT_ID] → the increment ID (e.g., 0042-checkout-flow)[MASTER_INCREMENT_PATH] → full path to the master increment directory{ORG} → the discovered organization name{repo-name} → the assigned repository nameTask({
team_name: "<team-name>",
name: "<domain>-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <replaced agent content>
})
CRITICAL: Always use mode: "bypassPermissions" — agents cannot handle interactive trust-folder prompts.
Each agent has exclusive WRITE access to specific file patterns. This prevents merge conflicts.
| Domain | WRITE Patterns | Notes |
|---|---|---|
| Frontend | src/components/**, src/pages/**, src/hooks/**, src/styles/**, src/app/**, src/stores/**, public/** | UI layer |
| Backend | src/api/**, src/services/**, src/middleware/**, src/routes/**, src/controllers/** | API layer |
| Database | prisma/**, src/db/**, src/repositories/**, seeds/**, scripts/db/** | Data layer |
| Shared/Types | src/types/**, src/shared/**, src/constants/**, src/utils/shared/** | Contracts |
| Testing | tests/**, __tests__/**, e2e/**, **/*.test.ts, **/*.test.tsx, **/*.spec.ts, test-utils/**, fixtures/** | All test files |
| Security | src/auth/**, src/middleware/auth*, src/middleware/security*, src/utils/crypto/**, src/utils/validation/**, security/** | Auth and security |
| DevOps | .github/**, docker/**, Dockerfile*, docker-compose*, k8s/**, terraform/**, .gitlab-ci.yml, Makefile | Infrastructure |
| Mobile | src/screens/**, src/navigation/**, ios/**, android/**, src/native/** | Mobile app |
| ML | models/**, notebooks/**, src/ml/**, src/pipelines/**, data/** | Machine learning |
package.json), the orchestrator assigns a primary owner and others request changes via SendMessagerepositories/{ORG}/ directory conventionAgents communicate contract readiness, blocking issues, and completion status using SendMessage.
| Prefix | Purpose | Sender | Receiver |
|---|---|---|---|
CONTRACT_READY: | Upstream contract is published | Upstream agent | team-lead (broadcasts to downstream) |
PLAN_READY: | Plan created, agent proceeding to implementation | Any agent | team-lead (async review) |
STATUS: | Heartbeat — task progress update | Any agent | team-lead (stuck detection) |
BLOCKING_ISSUE: | Agent is stuck, needs help | Any agent | team-lead |
COMPLETION: | Agent finished all tasks | Any agent | team-lead |
PLAN_CORRECTION: | Plan needs revision (async) | team-lead | Specific agent |
// Upstream agent signals contract is ready
SendMessage({
type: "message",
recipient: "team-lead",
content: "CONTRACT_READY: TypeScript interfaces written to src/types/checkout.ts. Exports: CheckoutItem, CartSummary, PaymentIntent.",
summary: "Shared types contract ready"
});
// Agent notifies plan is ready (does NOT wait for response)
SendMessage({
type: "message",
recipient: "team-lead",
content: "PLAN_READY: Created .specweave/increments/0202-checkout-backend/\nTasks: 8\nACs covered: AC-US1-01, AC-US1-02, AC-US2-01\nKey decisions: REST API with Express, JWT auth middleware\nFiles: src/api/checkout.ts, src/services/payment.ts, src/middleware/auth.ts\nArchitecture: Controller-Service-Repository pattern",
summary: "Backend plan ready — proceeding to implementation"
});
// Agent heartbeat after each task completion
SendMessage({
type: "message",
recipient: "team-lead",
content: "STATUS: T-003/8 complete. Next: T-004 (implement payment service). Tests: 12/12 passing.",
summary: "Backend agent: task 3 of 8 done"
});
// Agent reports a blocking issue
SendMessage({
type: "message",
recipient: "team-lead",
content: "BLOCKING_ISSUE: Cannot implement payment webhook -- Stripe webhook secret not found in .env. Need STRIPE_WEBHOOK_SECRET to proceed.",
summary: "Blocked on missing Stripe secret"
});
// Agent signals completion
SendMessage({
type: "message",
recipient: "team-lead",
content: "COMPLETION: All 8 tasks done. Tests passing (24/24). Ready for team-lead closure.",
summary: "Frontend agent completed all tasks"
});
// Team-lead sends async plan correction (agent is already implementing)
SendMessage({
type: "message",
recipient: "database-agent",
content: "PLAN_CORRECTION: 1) Add index on user_id for sessions table. 2) Missing AC-US1-03 — add a migration task. Pause and revise.",
summary: "Plan correction for database agent"
});
TeamCreate({
team_name: "feature-checkout",
description: "Building checkout flow across frontend, backend, and database"
});
All agents are spawned with mode: "bypassPermissions" to prevent blocking on trust-folder prompts. Agents notify team-lead of their plans via PLAN_READY but proceed to implementation immediately (see Section 3b for async review protocol).
For each agent: Read the agent definition file (see Section 4 reference table), replace placeholders ([INCREMENT_ID], [MASTER_INCREMENT_PATH], {ORG}, {repo-name}), and use the full content as the Task() prompt.
// Read agents/database.md, replace placeholders, then:
Task({
team_name: "feature-checkout",
name: "database-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/database.md with placeholders replaced>,
});
Messages are delivered automatically via SendMessage from upstream agents.
// Read agents/backend.md, agents/frontend.md, agents/testing.md
// Replace placeholders, then spawn each:
Task({
team_name: "feature-checkout",
name: "backend-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/backend.md with placeholders replaced>,
});
Task({
team_name: "feature-checkout",
name: "frontend-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/frontend.md with placeholders replaced>,
});
Task({
team_name: "feature-checkout",
name: "testing-agent",
subagent_type: "general-purpose",
mode: "bypassPermissions",
prompt: <content of agents/testing.md with placeholders replaced>,
});
Quality gates are split: agents handle tests, team-lead handles closure (grill, done, judge-llm). This prevents context overflow in agents from loading 4+ additional skill definitions during closure.
Agent Workflow:
1. Execute all assigned tasks via sw:auto
2. Run all tests for owned code (unit + integration + E2E)
3. Run linter/type-check for owned code
4. If tests fail -> fix issues and repeat from step 2
5. Do NOT signal completion until all tests pass
6. Signal COMPLETION via SendMessage (include task count, test results summary)
7. Do NOT run sw:grill or sw:done — team-lead handles closure centrally
Why agents don't run sw:done: The sw:done skill invokes 4 sub-skills (grill, judge-llm, sync-docs, qa), each loading a full SKILL.md. After many tasks of auto-mode context, this pushes agents into deep reasoning loops (30+ min hangs). Closure is delegated to sw-closer subagents that run in a fresh context, avoiding overflow for both agents and the team-lead orchestrator.
During the active phase (between spawning agents and receiving ALL COMPLETION signals), the team-lead focuses on orchestration:
Closure operations (grill, done, judge-llm) are performed by sw-closer subagents spawned from the closure phase below, not by the orchestrator itself. The orchestrator avoids calling TeamDelete() while agents are still running — that kills every live agent.
Closure begins ONLY after ALL agents have signaled COMPLETION (or been declared stuck).
Do NOT manually run grill/done per increment — spawn sw-closer subagents instead.
AFTER ALL AGENTS COMPLETE:
1. Verify ALL agents signaled COMPLETION (no unresolved BLOCKING_ISSUE)
2. Determine closure order from team topology (shared → backend → frontend)
3. For each increment in dependency order, spawn sw-closer subagent:
Agent({
subagent_type: "sw:sw-closer",
prompt: "Close increment <ID>. Increment path: .specweave/increments/<ID>/",
description: "Close increment <ID>"
})
4. Wait for each sw-closer to complete before spawning the next (dependency order)
5. If an sw-closer fails, log the failure and continue to the next increment
6. Run Step 9 cleanup (TeamDelete + kill tmux panes)
CRITICAL: Do NOT attempt inline closure (grill → done → retry loops) yourself.
Spawn sw-closer subagents instead — each runs in a fresh context with only the sw:done skill loaded, avoiding the context overflow that caused the "stuck after first agent" bug.
If all sw-closer subagents fail, report the failures to the user with the error messages. Do NOT retry inline.
| Domain | Grill Checks |
|---|---|
| Frontend | Components render, no console errors, accessibility, responsive |
| Backend | API endpoints return correct status codes, validation works, error handling |
| Database | Migrations apply cleanly, seed data loads, rollback works |
| Testing | All tests pass, coverage threshold met, no flaky tests |
| Security | No exposed secrets, input validation, auth working |
| DevOps | Docker builds, CI passes, deployment config valid |
Agents send STATUS: T-{N}/{total} heartbeat messages after each task completion. The team-lead uses these to detect stuck agents proactively.
The team-lead maintains a mental log of the last STATUS received from each agent:
Agent Heartbeat Log (example):
backend-agent: STATUS: T-003/8 (last seen: 2 turns ago)
frontend-agent: STATUS: T-005/12 (last seen: this turn)
database-agent: COMPLETION (done)
testing-agent: STATUS T-001/6 (last seen: 4 turns ago) ← STUCK?
Note: Claude Code has no built-in timers. Heartbeats are tracked relative to team-lead turns (each time the orchestrator processes messages). Time thresholds below are approximate wall-clock estimates based on typical turn cadence.
| Condition | Wall-clock estimate | Action |
|---|---|---|
| Agent sent STATUS within the current no-progress window | ≤ 5 min | Healthy — no action needed |
| No STATUS / no progress from agent for the no-progress window | ~5 min | Send STATUS_CHECK message to agent |
| No STATUS / no response to STATUS_CHECK for the total-stuck window | ~20 min | Declare agent stuck |
| Agent sends STATUS but task number hasn't advanced for 3+ heartbeats | — | Stuck in loop — declare stuck |
| All agents stuck | — | STOP team, report to user |
Window rationale: Raised from 2min/10min to 5min/20min in SpecWeave 1.1.0 — Opus 4.7's long-horizon coherence means legitimate pauses (tool use, extended reasoning, long file writes) are longer, so the old 2min window produced false stuck-detection on otherwise-healthy agents. Override via quality.stuckDetection.{noProgressMin, totalStuckMin} in .specweave/config.json.
An agent may appear to send heartbeats but actually be looping on the same task (e.g., test fails → fix → test fails → fix → ...). To detect this:
When an agent is declared stuck:
A domain agent that borrows a Workflow (see agents/_protocol.md Workflow Mode) goes silent for minutes while the background run executes — the normal 5min/20min windows would false-kill a healthy agent. Additive handling:
DELEGATING … workflow_id=, mark it state=workflow-delegating and record the workflow_id. SUSPEND the normal 5/20 windows.quality.workflows.stuckDetection.{workflowNoProgressMin, workflowTotalStuckMin} (defaults 20min / 60min) instead. Silence here is expected, not stuck.STATUS: WORKFLOW_DONE (or a BLOCKING_ISSUE citing the same workflow_id) restores state=active and the normal 5/20 windows from the next heartbeat.workflowTotalStuckMin elapses with no WORKFLOW_DONE, send ONE STATUS_CHECK asking the agent to report the Workflow's own progress (it is resumable/background). Declare stuck only after a second unanswered probe; prefer leaving the increment open over killing mid-batch.Default-off: with no quality.workflows config, no agent ever enters state=workflow-delegating, so behavior is identical to today.
sw:team-lead "Build checkout flow"
│
├── Step 0: VERIFY INCREMENT EXISTS (BLOCKING)
│ ├── Found? → Read master spec.md as source of truth
│ └── Missing? → Auto-invoke sw:increment, wait for completion
├── Step 0b: ACTIVATE MASTER INCREMENT (MANDATORY)
│ └── Edit metadata.json: set status to "active" BEFORE spawning agents
├── Step 1: Analyze feature (from master spec) → identify domains → decide increment split
├── Step 2: Create team via TeamCreate
├── Step 3: Create per-domain increments (derived from master spec)
│
│ ── ACTIVE PHASE (agents implementing, team-lead monitoring) ──
│
├── Step 4: Contract-first spawning (all agents with mode: "bypassPermissions")
│ ├── Phase 1: Spawn shared + database
│ │ └── Agents send PLAN_READY notification → proceed immediately
│ │ └── Team-lead reviews async, sends PLAN_CORRECTION only if needed
│ │ └── Wait for CONTRACT_READY
│ └── Phase 2: Spawn backend + frontend + testing
│ └── Agents send PLAN_READY notification → proceed immediately
├── Step 5: Monitor progress via STATUS heartbeats
│ ├── Track per-agent: last STATUS task number and turn count
│ ├── No STATUS for 2 turns → send STATUS_CHECK
│ ├── No STATUS for 3 turns or same task 3+ times → declare stuck
│ └── DO NOT run grill/done/closure during this phase
├── Step 6: Collect all COMPLETION signals (or declare remaining agents stuck)
│
│ ── CLOSURE PHASE (all agents done) ──
│
├── Step 7: Spawn sw-closer subagents per increment (fresh context closure)
├── Step 8: Shutdown agents → TeamDelete() → orphaned pane safety net (Step 9 below)
└── Done.
IMPORTANT: The intended entry point is: sw:increment → sw:do (detects 3+ domains) → sw:team-lead.
Direct invocation of sw:team-lead without an existing increment will trigger the guard and auto-invoke sw:increment.
After delivering results OR after all sw-closer subagents complete, clean up the team.
Send shutdown_request to every agent you spawned. You know their names — you spawned them via Task().
// Replace with your actual agent names from this session
SendMessage({ type: "shutdown_request", recipient: "<agent-1-name>", content: "Team work complete" });
SendMessage({ type: "shutdown_request", recipient: "<agent-2-name>", content: "Team work complete" });
// ... for every agent you spawned
Harmless if agents already exited. NOTE: shutdown_request via SendMessage does NOT close the tmux pane — the agent's Claude process exits but the pane persists with "Resume this session". Phase 3 below is the ONLY mechanism that actually kills orphaned panes. NEVER skip Phase 3.
TeamDelete();
If TeamDelete fails (agents still shutting down), wait 3 seconds, retry once.
SendMessage shutdown does NOT close tmux panes. Agent processes exit but panes persist showing "Resume this session". This bash script is the ONLY cleanup mechanism. ALWAYS run it.
if command -v tmux >/dev/null 2>&1; then
CURRENT_PANE=$(tmux display-message -p '#{pane_id}' 2>/dev/null || echo "")
for pane_id in $(tmux list-panes -a -F '#{pane_id}' 2>/dev/null); do
[ -n "$CURRENT_PANE" ] && [ "$pane_id" = "$CURRENT_PANE" ] && continue
if tmux capture-pane -t "$pane_id" -p -S -50 2>/dev/null | grep -q "Resume this session"; then
tmux kill-pane -t "$pane_id" 2>/dev/null
fi
done
fi
Key: Removed $TMUX guard — even if the orchestrator isn't inside tmux itself, agent panes still exist in tmux and need cleanup. The tmux command can manage external sessions.
When --dry-run is specified, display the proposed plan without executing.
Do NOT call TeamCreate in dry-run mode — just show the formatted plan text.
Team Orchestration Plan (DRY RUN)
==================================================
Feature: Build checkout flow | Domains: 4
Phase 1 (upstream):
1. shared-types -> sw:architect, sw:code-simplifier | Increment: 0200-checkout-shared
2. database -> sw:architect | Increment: 0201-checkout-database
Phase 2 (downstream, parallel):
3. backend -> sw:architect, infra:devops | Increment: 0202-checkout-backend
4. frontend -> sw:architect | Increment: 0203-checkout-frontend
Max agents: 4 (2 sequential + 2 parallel)
To execute, run without --dry-run.
| Issue | Cause | Fix |
|---|---|---|
| TeamCreate blocked by guard | No increment with spec.md exists | Run sw:increment "feature" first, then retry sw:team-lead. The guard requires a substantive spec.md (>200 bytes, not a template) |
| Agent stuck on trust folder | Agent spawned without bypassPermissions | ALWAYS use mode: "bypassPermissions" — NEVER mode: "plan". Trust prompts require interactive input agents cannot provide |
| Session freezes after first agent completes | Closure ran during active phase (pre-v0528 bug) | Ensure §8 active-phase rules are followed: NO grill/done until ALL agents signal COMPLETION |
| Agent proceeds with wrong plan | Async model means agents don't wait for approval | Send PLAN_CORRECTION immediately; agent should pause and revise. If ignored, send shutdown_request |
| No heartbeat STATUS from agent | Agent didn't implement heartbeat or is stuck | Check if agent template includes heartbeat step. If yes, agent is stuck — send STATUS_CHECK, then declare stuck after 3 turns |
| Agent stuck in loop (same task repeated) | Test fail → fix → test fail cycle | Heartbeat shows same task number 3+ times. Send guidance message or declare stuck |
| Agents editing same files | Overlapping file ownership patterns | Review ownership map; reassign conflicting files to a single owner; use --dry-run to validate before launch |
| Token cost too high | Too many agents or overly large prompts | Reduce --max-agents; use --domains to limit scope; split feature into smaller increments |
| Agent stuck in long reasoning loop | Too many tasks causing context overflow | Enforce the per-agent task cap (TASK_CAP = 40 in 1.1.0); split large domains into 2 agents; agents use --simple-compat mode |
| Agent hung on sw:done | Closure loads 4+ skill definitions into already-full context | Agents should NOT run sw:done — team-lead spawns sw-closer subagents (fresh context) for closure |
| Contract agent takes too long | Large schema or complex type system | Set a timeout in the agent prompt; if stuck >15 min, check agent output and consider splitting the contract work |
| Phase 2 starts before Phase 1 finishes | CONTRACT_READY not received yet | Ensure upstream agents send CONTRACT_READY via SendMessage before team-lead spawns downstream |
| Agent fails mid-task | Build error, test failure, or dependency issue | Send message to agent to fix; restart the agent with sw:auto on its increment |
specweave complete exits silently | metadata.json status is "planned" (not "active") | Agents don't manage lifecycle status. Team-lead MUST activate the increment before spawning agents (see Step 0). Fix: edit metadata.json to set "status": "active" before running specweave complete |
| Closure fails on multiple increments | Quality gates fail (grill, desync, missing reports) | Each sw-closer subagent retries once automatically. If still failing, use /sw:close-all for batch retry |
User: sw:team-lead "Build user authentication with login, signup, password reset, and OAuth"
Orchestrator detects domains: shared/types, database, backend, frontend, testing, security
Creates 6 increments.
Phase 1:
- shared-types agent: Auth types (User, Session, AuthToken interfaces)
- database agent: User table, Session table, Prisma migrations
Phase 2 (after contracts ready):
- backend agent: /api/auth/login, /api/auth/signup, /api/auth/reset, OAuth flow
- frontend agent: LoginForm, SignupForm, ResetPasswordForm, OAuthButton
- testing agent: Unit tests, E2E login flow, E2E signup flow
- security agent: Password hashing, JWT validation, rate limiting, CSRF
User: sw:team-lead "Redesign dashboard" --domains frontend,testing
-> No upstream dependencies. Both agents spawn in parallel immediately.
User: sw:team-lead "Add payment processing" --dry-run
-> Shows plan with domains, phases, file ownership. No agents spawned.
| Skill | Purpose |
|---|---|
sw:team-status | Show progress of all agents in the current team session |
sw:team-merge | Merge completed agent work in dependency order |
sw:auto | Autonomous execution (single-agent mode) |
sw:architect | System architecture and ADRs |
sw:grill | Quality validation gate |
npx claudepluginhub anton-abyzov/specweave --plugin swSets up multi-agent teams for complex projects with file-based planning, per-agent directories, and teammate spawning. Triggers on team/swarm/start-project requests.
Enforces a strict TDD pipeline for AI agent teams, coordinating feature development through spec, test, implementation, review, and security gates. Activates when spawning parallel agent teams for project work.
Guides composing agent teams for complex tasks with predefined roles: Orchestrator, Explorer, Frontend (React), Backend (Rails), iOS/Swift, Android/Kotlin, Database.