Continuación de GSD + Agent Teams. La arquitectura multi-agente dispara el consumo de tokens en un orden de magnitud. Aquí está el análisis de por qué ocurre y la implementación concreta de cada optimización.
// 01 — Por qué explota el consumo
El spike no es un bug ni un caso edge — es estructural. Varias causas se acumulan:
- Multiplicación por N instancias. Cada teammate tiene su propio context window independiente. Con 3 workers + 1 lead ya tienes ×4 en el baseline antes de escribir una línea de código.
- Context loading duplicado. Cada worker arranca leyendo CLAUDE.md, PROJECT.md, REQUIREMENTS.md, STATE.md y los archivos de fase. El mismo contexto se carga N veces en paralelo. En proyectos con historial, STATE.md solo puede superar los 500 tokens fácilmente.
- Overhead de coordinación. TaskList(), lectura de inboxes, mensajes entre teammates, monitoring del lead — todo son llamadas independientes que suman tokens por separado.
- Idle context en workers bloqueados. Si lanzas toda la Wave 1 de golpe y hay tareas con dependencias, los workers bloqueados permanecen activos esperando señales y acumulando contexto pasivo sin hacer trabajo útil.
// 02 — Las optimizaciones
Seis cambios en capas distintas. Orden recomendado de implementación: primero el 1 y el 6 (impacto inmediato, 5 minutos), luego el 2 y el 5 (impacto alto, 15 minutos), el resto es mantenimiento continuo.
1 — Modelo por rol
El cambio con mejor ratio esfuerzo/ahorro. Haiku para workers, Sonnet para el lead.
// .claude/settings.json
{
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
"model": "claude-sonnet-4-6",
"agentModel": "claude-haiku-4-5-20251001"
}
model controla el lead. agentModel es el default global para todos los teammates. El lead mantiene razonamiento de calidad; los workers ejecutan tareas atómicas ya especificadas donde Haiku es suficiente.
Haiku falla más en tareas con contexto implícito, debugging autónomo o lógica de negocio compleja. Para esos casos, ver sección 03 (workers híbridos).
2 — Context quirúrgico en teammates
El worker no necesita el contexto global. El lead ya lo tiene. En el Skill, reemplaza el prompt de cada Task():
- prompt: "Claim #id → execute → verify → complete → notify lead",
+ prompt: |
+ Context (read ONLY these files):
+ - .planning/phase-$ARGUMENTS/$TASK_PLAN_FILE
+ - CLAUDE.md (project conventions only)
+
+ Task: Claim #$TASK_ID from team 'gsd-phase-$ARGUMENTS'.
+ Execute exactly what the PLAN specifies.
+ On complete: update task status → notify lead via inbox.
+ Do NOT read PROJECT.md, REQUIREMENTS.md or STATE.md.
Reducción estimada: 40–60% de input tokens por worker según el tamaño del proyecto.
3 — Comprimir STATE.md antes de ejecutar
STATE.md crece con cada fase. Antes de /execute-phase-teams N, añade este Step al Skill:
## Step 1.5 — Compress context files
Before spawning teammates, summarize STATE.md in-place:
- Keep: current blockers, active decisions, phase position
- Remove: resolved decisions, historical log older than 2 milestones
- Max length: 150 lines
Write compressed version back to STATE.md.
O manualmente antes de cada fase grande:
/gsd:quick compress STATE.md — keep only active decisions and current blockers, max 150 lines
4 — Eliminar broadcast
El propio artículo anterior lo marcaba como caro. broadcast envía a todos los teammates simultáneamente. En el prompt de cada worker, añade la restricción explícita:
Communication rules:
- NEVER use broadcast operation
- Use write({ to: "team-lead", ... }) for status updates
- Use write({ to: "worker-N", ... }) only when blocking dependency resolved
Y en el Step 6 (monitor), el lead usa TaskList() en lugar de polling por inbox broadcast.
5 — Wave strategy: no spawn masivo
Lanzar todos los workers simultáneamente sin respetar dependencias es la causa principal del idle context. Reemplaza el Step 5 del Skill:
## Step 5 — Spawn by wave (max 3 simultaneous)
Parse dependency graph from PLAN files.
Build waves:
wave_1 = tasks with no blockers
wave_N = tasks blocked by wave_N-1
Spawn Wave 1 ONLY (max 3 workers simultaneous).
Wait for Wave 1 completion via TaskList().
Spawn Wave 2 only after all Wave 1 tasks = "completed".
Continue until all waves done.
Never spawn a wave while the previous is incomplete.
6 — Gate check: cuándo NO usar Agent Teams
Agent Teams añade overhead de coordinación. Por debajo de cierto umbral, una sesión única es más barata. Añade este Step 0 al Skill:
## Step 0 — Gate check
Count <task> blocks in phase-$ARGUMENTS PLAN files.
If task_count <= 3:
STOP. Tell user: "Phase $ARGUMENTS has N tasks.
Use /gsd:execute-phase $ARGUMENTS instead (single session is cheaper)."
If all tasks are sequential (each blocked by previous):
STOP. Tell user: "Phase $ARGUMENTS is fully sequential.
Agent Teams adds overhead with no parallelism benefit."
Proceed only if: task_count >= 4 AND at least 2 independent task groups exist.
// 03 — Workers híbridos: dos tipos de modelo
agentModel en settings.json es el default global, pero Task() acepta un campo model que lo sobreescribe por worker. Esto permite tener Haiku como base y escalar a Sonnet solo donde hace falta, sin mantener dos Skills distintos.
Clasificar en Step 2
El lead lee cada <task> del PLAN file y le asigna un tipo antes de spawnar nada:
simple (→ hereda Haiku) si TODO:
- action es: create file, scaffold boilerplate, write config, add tests para lógica existente, rename, delete
- archivos afectados son nuevos o aislados
- descripción del PLAN no contiene markers de ambigüedad
complex (→ override a Sonnet) si CUALQUIERA:
- implementa lógica de negocio o algoritmos
- modifica módulos compartidos o core
- requiere leer múltiples archivos existentes para decidir el output
- descripción contiene: "refactor", "migrate", "integrate", "debug", "design", "resolve"
Spawn con o sin override
// Worker simple — sin model, hereda agentModel global = Haiku
Task({
team_name: "gsd-phase-1",
name: "create-config",
prompt: "...",
run_in_background: true
})
// Worker complejo — override explícito
Task({
team_name: "gsd-phase-1",
name: "refactor-auth",
model: "claude-sonnet-4-6", // ← única diferencia
prompt: "...",
run_in_background: true
})
En la práctica, el flujo de una fase con 6 tareas (4 simple, 2 complex) quedaría:
Lead (Sonnet):
→ lee PLAN files → clasifica 6 tareas
→ Wave 1: spawna #1 (Haiku), #3 (Haiku), #2 (Sonnet) en paralelo
→ espera Wave 1
→ Wave 2: spawna #4 (Haiku), #5 (Sonnet)
→ ...
// 04 — Settings.json completo
{
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
"CLAUDE_CODE_SPAWN_BACKEND": "tmux",
"model": "claude-sonnet-4-6",
"agentModel": "claude-haiku-4-5-20251001",
"permissions": {
"allow": [
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git status:*)",
"Bash(git log:*)",
"Bash(git diff:*)",
"Bash(mkdir:*)",
"Bash(cat:*)",
"Bash(ls:*)",
"Bash(find:*)",
"Bash(grep:*)"
],
"deny": []
}
}
CLAUDE_CODE_SPAWN_BACKEND: tmux es opcional — solo si quieres ver los workers en paneles separados. Sin él, corren en background silencioso.
// 05 — Skill completo actualizado
Guardar en ~/.claude/skills/execute-phase-teams/SKILL.md, reemplazando la versión anterior.
---
name: execute-phase-teams
description: Executes a GSD phase using Claude Code native Agent Teams
(TeammateTool) with token-optimized context loading, hybrid model
selection and wave spawning. Use when the user runs
/execute-phase-teams or asks to execute a GSD phase with agent teams.
disable-model-invocation: false
---
## Step 0 — Gate check
Count tasks. If <= 3 or fully sequential → abort, recommend /gsd:execute-phase.
## Step 1 — Read context (lead only)
.planning/PROJECT.md · REQUIREMENTS.md · STATE.md
.planning/phase-$ARGUMENTS/ (all files)
## Step 1.5 — Compress STATE.md
Summarize in-place: active decisions + current blockers only. Max 150 lines.
## Step 2 — Parse PLAN files + classify
Extract <task> blocks. Build dependency graph → waves.
Classify each task as simple (Haiku) or complex (Sonnet) per criteria above.
## Step 3 — Create team
Teammate({ operation: "spawnTeam", team_name: "gsd-phase-$ARGUMENTS" })
## Step 4 — Create tasks + dependencies
TaskCreate({ subject, description, activeForm })
TaskUpdate({ taskId: "B", addBlockedBy: ["A"] })
## Step 5 — Spawn by wave (max 3 simultaneous)
For each wave:
simple tasks → Task({ ..., prompt: "...", run_in_background: true })
complex tasks → Task({ ..., model: "claude-sonnet-4-6", prompt: "...", run_in_background: true })
Worker prompt template:
Context: read ONLY .planning/phase-$ARGUMENTS/$TASK_PLAN_FILE and CLAUDE.md.
Do NOT read PROJECT.md, REQUIREMENTS.md or STATE.md.
Claim #$TASK_ID → execute → verify → complete.
write({ to: "team-lead", message: "task #N complete: <summary>" })
Never use broadcast.
Wait for wave completion before spawning next wave.
## Step 6 — Monitor
TaskList() every 30s. Read inboxes/team-lead.json.
## Step 7 — Commit per task
git add -A && git commit -m 'feat(phase-N): <task>'
## Step 8 — Shutdown + cleanup
requestShutdown → wait approvals → cleanup
// 06 — Resumen de impacto esperado
| Cambio | Reducción estimada |
|---|---|
| Haiku para workers (default) | ~60–70% en coste por token de workers |
| Context quirúrgico por worker | ~40–60% menos input tokens por worker |
| Workers híbridos (Haiku/Sonnet) | Coste Sonnet solo donde es necesario |
| Comprimir STATE.md | ~10–20% según antigüedad del proyecto |
| Sin broadcast | ~5–15% en overhead de coordinación |
| Wave strategy | Elimina idle context en workers bloqueados |
| Gate check | Evita el coste entero en fases que no lo necesitan |
// Fuentes
Agent Teams — Orchestrate teams of Claude Code sessions, documentación oficial
Claude Code — Settings y variables de entorno · Skills
Modelos y precios — Anthropic API pricing · Configuración de modelo en Claude Code
Post anterior — GSD + Agent Teams