SDD com agentes — coordinator, implementor, validator

TL;DR

SDD é onde multi-agent começa a fazer sentido. O padrão dominante em 2026 é o trio Coordinator/Implementor/Validator (CIV): coordinator transforma spec em DAG de subtasks; implementors trabalham em paralelo, cada um com contexto isolado focado na sua task; validators verificam saídas contra spec antes de aceitar. Pesquisa peer-reviewed (VeriMAP, EACL 2026) formalizou o padrão. Anthropic, Augment, AWS Kiro convergiram. Ganho real: paralelismo seguro + isolamento de contexto + drift detection automatizada.

Por que multi-agent só funciona com spec

Imagine uma montadora. Sem planta de engenharia, operários improvisa em cada posto de trabalho. O carro sai diferente a cada vez, e o inspetor de qualidade não tem como saber o que verificar. Com a planta, cada posto sabe exatamente o que recebe, o que faz, e o que entrega. O inspetor verifica contra especificação, não contra opinião.

SDD para multi-agent é a planta da montadora. Sem spec, agentes concorrentes produzem código incompatível, duplicam lógica, ou quebram contratos uns dos outros sem perceber. Com spec, cada agente tem contrato claro: o que recebe como input, o que deve produzir como output, e como saber se acertou.

O padrão CIV (Coordinator/Implementor/Validator) é a materialização dessa ideia. Em 2026, convergiu como o padrão de facto para SDD agentic — usado nativamente em Kiro, formalizado no paper VeriMAP (EACL 2026), e documentado como prática recomendada no Claude Agent SDK.

A arquitetura CIV

graph TB
    S["📐 Spec + Plan"] --> C["🧭 Coordinator\n(DAG planner)"]
    C --> I1["⚙️ Implementor 1\nTask A"]
    C --> I2["⚙️ Implementor 2\nTask B"]
    C --> I3["⚙️ Implementor 3\nTask C"]
    I1 --> V["🔍 Validator"]
    I2 --> V
    I3 --> V
    V -->|"❌ falha"| C
    V -->|"✅ ok"| M["✅ Merge"]

Cada papel tem contexto isolado — implementor 1 não vê o histórico do 2. A razão é context rot: contexto inflado dilui atenção. Um agente com 5K tokens focados em uma task resolve melhor do que um agente com 200K tokens carregando o projeto inteiro.

Os três papéis em detalhe

Coordinator — o planejador de DAG

VeriMAP (EACL 2026)

“The Coordinator is the central orchestrator of multi-agent task execution, following the task plan (represented as a DAG) to support reliable and adaptive execution.”

O Coordinator é o único agente que vê a spec completa e o plan completo. Sua função não é implementar — é transformar o plan em um grafo dirigido acíclico (DAG) de subtasks e gerenciar a execução.

Responsabilidades:

  • Transformar plan em DAG de subtasks com dependências explícitas
  • Identificar quais tasks podem rodar em paralelo
  • Disparar implementors — um por task — com contexto isolado e mínimo
  • Receber resultado de cada implementor via validation
  • Replanejar se task falha (até N tentativas, depois escala para humano)
  • Manter estado persistente do progresso

O que o Coordinator NÃO faz:

  • Escrever código (isso é papel do implementor)
  • Revisar código linha a linha (isso é o validator)
  • Tomar decisões arquiteturais (isso foi feito no Plan)

Modelo: Sonnet ou Opus — precisa raciocinar sobre interdependências e replanejar adaptivamente.

Contexto do coordinator:

CONTEXTO DO COORDINATOR
========================
spec.md (completa)
plan.md (completo)
tasks.yml (DAG, atualizado com status)
AGENTS.md (convenções do projeto)

Implementor — executor de contexto mínimo

O Implementor recebe uma task com input definido, critérios de aceitação, e lista de arquivos no escopo. Nada mais.

A analogia: um implementor é como um cirurgião especialista. Você não explica para ele a história médica completa do hospital — você dá o prontuário do paciente, a cirurgia a fazer, e os critérios de sucesso. O resto é ruído que prejudica o foco.

Responsabilidades:

  • Receber task (input + AC + arquivos de escopo)
  • Carregar o contexto relevante (spec da feature + arquivos da task)
  • Escrever código + testes que satisfaçam os ACs
  • Reportar resultado: { status: pass|fail, evidence: [...], files_changed: [...] }

O que o Implementor NÃO recebe:

  • Plan completo (só a parte da sua task)
  • Output de outros implementors rodando em paralelo
  • Histórico de conversas do coordinator

Modelo: Sonnet ou Haiku — tarefa estreita, contexto mínimo, modelo barato resolve bem.

Contexto do implementor para uma task:

CONTEXTO DO IMPLEMENTOR
========================
task.yml (descrição, ACs, escopo)
spec/feature.md (só a feature desta task)
arquivos listados em task.scope
AGENTS.md (convenções)

A matemática do isolamento

10 implementors com 5K tokens cada = 50K tokens totais. Um agente monolítico lidando com 10 tasks = 150K+ tokens (contexto cresce com histórico). Além de mais barato, os implementors isolados têm atenção 30x mais focada por task.

Validator — verificador independente

O Validator é o gate entre “implementado” e “aceito”. Recebe o output do implementor, a spec da feature, e verifica de forma independente se os critérios de aceitação foram atendidos.

A palavra-chave é “independente”. Validator deliberadamente não vê o raciocínio do implementor — só o resultado. O motivo: se validator e implementor compartilham prompt ou contexto, o validator tende a aceitar qualquer coisa que o implementor produziu. Independência arquitetural (modelo diferente, prompt diferente, contexto diferente) é o que torna o gate efetivo.

Responsabilidades:

  • Executar os ACs como assertions (não como inspeção visual)
  • Rodar gates de coverage, drift, NFR (ver 07 - Fase Validate — spec como contrato executável)
  • Produzir veredicto estruturado: { pass: bool, failures: [...], evidence: [...] }
  • NÃO sugerir como corrigir — isso é papel do implementor/coordinator

O que o Validator NÃO faz:

  • Implementar correções
  • Decidir se “quase passou” é suficiente (isso é humano ou coordinator)
  • Avaliar qualidade de código além dos ACs

Modelo: Sonnet — diferente do implementor para evitar viés de confirmação idêntico.

Contexto do validator:

CONTEXTO DO VALIDATOR
======================
task.yml (ACs explícitos)
spec/feature.md (contratos)
output do implementor (código + testes)
resultado dos gates (coverage report, drift report)
[NÃO inclui]: reasoning do implementor

Anti-pattern crítico

Validator com prompt genérico (“is this code good?”) é inútil. Validator efetivo tem prompt específico: “Verify that each acceptance criterion in task.yml is satisfied by the evidence in implementor output. Report pass/fail per AC with line-level evidence.”

Coordinator não deve receber a transcrição completa dos implementors

Um erro comum ao implementar CIV é o coordinator “espiar” o raciocínio completo de cada implementor — todo o histórico de tool calls, tentativas e erros intermediários — em vez de só o resultado final estruturado ({ status, evidence, files_changed }). Isso reintroduz o problema que o isolamento de contexto existe para resolver: o coordinator infla com conteúdo que não precisa para decidir “próxima task” ou “replanejar”, e o overhead de coordenação (que deveria ficar <20% do tempo total, ver métricas abaixo) dispara. O Claude Agent SDK é explícito nisso: um subagente roda em conversa própria e só a mensagem final retorna ao pai — resultados intermediários ficam isolados dentro do subagente (ver 10 - Sub-agentes especializados, sobre por que esse isolamento também é o que barateia o padrão).

DAG: a estrutura que habilita paralelismo

O coordinator não inventa o DAG do nada — ele deriva do plan produzido na Fase Plan. A diferença: o plan descreve decisões; o DAG é uma estrutura de execução.

# tasks.yml — DAG gerado pelo coordinator
tasks:
  T1:
    name: "Schema refund_request"
    description: "Criar migration da tabela refund_request"
    inputs:
      - spec/payments.md#refunds
      - plan/architecture.md#data-model
    outputs:
      - migrations/004_add_refund_request.sql
      - src/models/refund_request.py
    acceptance:
      - "migration aplica sem erro em DB vazio"
      - "migration aplica sem erro em DB com dados de prod fixture"
      - "model tem campos: id, order_id, amount, status, created_at"
    depends_on: []
    parallel_safe: true
    status: pending
 
  T2:
    name: "RefundRepository"
    description: "Repositório de acesso a dados para refunds"
    inputs:
      - spec/payments.md#refunds
      - T1.outputs
    outputs:
      - src/repositories/refund_repository.py
      - tests/unit/test_refund_repository.py
    acceptance:
      - "create_refund persiste e retorna com id gerado"
      - "find_by_order_id retorna lista correta"
      - "update_status lança ValueError se status inválido"
    depends_on: [T1]
    parallel_safe: true   # paralelo com T3 quando T1 aprovado
    status: blocked
 
  T3:
    name: "RefundService"
    depends_on: [T2]
    parallel_safe: false  # depende de decisão arquitetural em T2
    status: blocked
 
  T4:
    name: "POST /api/refunds endpoint"
    depends_on: [T3]
    status: blocked
 
  T5:
    name: "GET /api/refunds/{id} endpoint"
    depends_on: [T3]
    parallel_safe: true   # paralelo com T4
    status: blocked

O coordinator dispara T2 e T5 em paralelo assim que seus depends_on são aprovados. Tasks parallel_safe: false esperam na fila.

parallel_safe: true não é garantia automática — arquivos compartilhados quebram o paralelismo

depends_on resolvido não basta para marcar uma task como paralelizável. Se T2 e T5 declaram parallel_safe: true mas ambas escrevem no mesmo arquivo (ex: as duas tocam src/api/router.py para registrar rotas diferentes), rodá-las em paralelo produz condição de corrida: o segundo implementor a terminar sobrescreve o trabalho do primeiro, ou o merge gera conflito silencioso que nenhum validator pega sozinho (cada um valida sua task isoladamente, não a interseção). O coordinator precisa cruzar o outputs/escopo de arquivos de cada task antes de liberar paralelismo — duas tasks só são de fato parallel_safe se seus conjuntos de arquivos tocados forem disjuntos.

Exemplo end-to-end: feature de reembolso

Para tornar concreto, aqui está um ciclo completo com três implementors paralelos e um validator:

Iteração 1: T1 (apenas)
  coordinator → implementor-1(T1: migration + model)
  implementor-1 → validator
  validator: ✅ migration aplicou, model correto

Iteração 2: T2 e T5 em paralelo (desbloqueados por T1)
  coordinator → implementor-2(T2: repository)
  coordinator → implementor-3(T5: GET endpoint)
  [paralelo]
  implementor-2 → validator → ✅ 3/3 ACs pass
  implementor-3 → validator → ❌ 1 AC falhou (404 para id inválido)

Iteração 3: retry de T5
  coordinator → implementor-4(T5: retry com feedback do validator)
  implementor-4 → validator → ✅ 3/3 ACs pass

Iteração 4: T3 (desbloqueado por T2 aprovado)
  coordinator → implementor-5(T3: service layer)
  implementor-5 → validator → ✅

Iteração 5: T4 (desbloqueado por T3)
  coordinator → implementor-6(T4: POST endpoint)
  ...

O humano observa o grafo de progresso em tasks.yml. Só intervém quando coordinator sinaliza “task falhou 3x, escalando”.

VeriMAP — a formalização peer-reviewed

VeriMAP (EACL 2026) é o paper que trouxe o CIV para o domínio científico. O sistema:

  1. Verification-aware planning: o coordinator codifica constraints de verificação antes de disparar implementors — cada task tem veredicto binário formalmente definido.
  2. DAG com prova de contrato: antes de liberar T_n, sistema prova mecanicamente que T_{n-1} atendeu todos os ACs.
  3. Rollback parcial: se T_n falha após aprovação de T_{n-1}, sistema pode reverter apenas T_n sem tocar T_{n-1}.

Aplicação principal: domínios regulados (financeiro, saúde) onde rastreabilidade de decisões é exigência de compliance.

Implementações práticas em 2026

StackComo fazer CIV
Claude Code (nativo)Task tool com subagent_type; coordinator no main thread via Agent tool
LangGraphStateGraph com nodes coordinator/implementor/validator; edges condicionais por veredicto
KiroSpecs + steering + custom subagents; CIV é a arquitetura default
GitHub Spec Kitspecify implement faz coordinator interno com loop de validation
Python + Anthropic SDKLoop manual: coordinator_loop() chama run_implementor() + run_validator()

Esqueleto em Python (Anthropic SDK)

import anthropic
 
client = anthropic.Anthropic()
 
def run_coordinator(spec, plan, tasks):
    dag = parse_dag(tasks)
    while not dag.complete():
        ready = dag.ready_tasks()           # tasks sem dependências pendentes
        parallel = [t for t in ready if t.parallel_safe]
        # Dispatcher: implementors em paralelo
        results = run_parallel_implementors(parallel, spec)
        for task, output in results.items():
            verdict = run_validator(task, output, spec)
            if verdict.pass_:
                dag.mark_done(task)
            else:
                dag.mark_retry(task, verdict.failures)
                if dag.retry_count(task) >= 3:
                    escalate_to_human(task, verdict)
 
def run_implementor(task, spec):
    # Contexto mínimo: só spec da feature + arquivos do escopo
    context = build_minimal_context(task, spec)
    return client.messages.create(
        model="claude-sonnet-4-6",
        messages=[{"role": "user", "content": context}]
    )
 
def run_validator(task, implementor_output, spec):
    # Contexto independente: NÃO inclui reasoning do implementor
    context = build_validator_context(task, implementor_output, spec)
    response = client.messages.create(
        model="claude-sonnet-4-6",          # modelo diferente do implementor
        messages=[{"role": "user", "content": context}]
    )
    return parse_verdict(response)

Custo de tokens: CIV vs single-agent

Uma questão legítima: CIV usa N agentes — não fica mais caro?

xychart-beta
    title "Tokens por feature (feature com 6 tasks)"
    x-axis ["Single agent", "CIV (paralelo)"]
    y-axis "Tokens (K)" 0 --> 300
    bar [280, 120]

O paradoxo: CIV pode ser mais barato. A razão:

  • Single agent carrega contexto completo desde o início. Cada task adiciona ao histórico. Task 6 processa contexto de tasks 1-5, gerando context rot e tokens desperdiçados em atenção dispersa.
  • CIV: cada implementor começa com contexto fresco (5-15K). Coordinator vê DAG de estado, não transcrições completas.

O overhead de CIV (coordinator + validators) costuma ser 20-40% do total — compensado pela ausência de context rot nos implementors.

Variantes avançadas

Hierarchical (multi-level coordinator)

Para features muito grandes, coordinator pode delegar a sub-coordinators por área:

Coordinator principal
├── Sub-coordinator A (camada de dados)
│   ├── Implementor A1 (schema)
│   └── Implementor A2 (repositories)
└── Sub-coordinator B (camada de API)
    ├── Implementor B1 (endpoints)
    └── Implementor B2 (serializers)

Sub-coordinators resolvem suas dependências internas. Coordinator principal orquestra entre as áreas.

Specialist subagents (padrão Kiro)

Em vez de implementors genéricos, subagents especializados por domínio:

# .kiro/agents/db-migration-writer.yml
name: DB Migration Writer
instructions: You write SQL migrations following the conventions in...
 
# .kiro/agents/security-reviewer.yml
name: Security Reviewer
instructions: Review implementation against OWASP Top 10 and spec security requirements...

Coordinator escolhe o specialist por tipo de task. Resultado: migrations são escritas por um agente que só faz migrations, com prompt otimizado para isso.

LLM critic como validator extra

Pipeline com validators encadeados, cada um com foco diferente:

Implementor → Test validator → Security validator → Style validator → Approve

Cada validator é independente. Security validator verifica vulnerabilidades OWASP. Style validator verifica convenções do AGENTS.md. Test validator verifica cobertura de AC.

Métricas de saúde do CIV

MétricaAlvo saudávelSinal de alerta
Speedup vs single-agent2-4x em features com tasks paralelizáveis<1.5x: DAG não está paralelizando
% tasks aprovadas em first-pass>75%<60%: spec mal escrita ou tasks grandes demais
% drift detectado por validator>90%<70%: validator prompt muito vago
Retry rate por task<20%>40%: ACs ambíguos no plan
Overhead de coordenação<20% do tempo total>35%: coordinator está fazendo trabalho de implementor
Escalações para humano<5% das tasks>15%: tasks mal decompostas ou ACs irrealizáveis

Quando NÃO usar CIV

CIV adiciona overhead real — coordinator + validator + comunicação inter-agente. O overhead só vale quando compensa:

  • Feature com 1-2 tasks: sem paralelismo possível, CIV é apenas burocracia
  • Time sem expertise em orquestração: aprender CIV enquanto entrega feature é problema duplo
  • Plan vago: DAG fraco → coordinator produz tasks mal definidas → validators rejeitam tudo
  • Domínio criativo: validation mecânica funciona mal quando “correto” é subjetivo
  • Prototipagem inicial: spec still evolving → paralelismo seria retrabalho

Regra de bolso: CIV compensa com ≥4 tasks paralelizáveis e spec estável.

Anti-patterns CIV

Anti-patternConsequência
Coordinator sem paralelismoVira sequência com overhead extra
Implementors recebendo plan completoPerde isolamento, context rot volta
Validator com prompt genéricoAprova qualquer output, gate inútil
DAG sem revisão humanaCoordinator pode criar dependência circular ou ignorar constraint
Sem fallback após 3 falhasLoop infinito, custo de tokens explode
Custos não monitoradosN agentes × tokens = surpresa no billing
Validator = mesmo modelo + prompt do implementorViés de confirmação, gate ilusório

O que vem a seguir

CIV resolve quem faz o quê e como isolar contexto entre papéis — mas o coordinator, os implementors e os validators ainda precisam de contexto bem curado para funcionar (o spec.md, o plan.md, o tasks.yml da seção anterior não aparecem magicamente na janela certa). A próxima nota, 10 - Integração com context engineering — specs como contexto persistente, fecha esse ciclo: trata a spec e o plan como camadas de contexto persistente que alimentam cada agente do CIV, e mostra como isso se conecta às técnicas gerais de context engineering.

Veja também

Referências

  • VeriMAPEACL 2026 paper, verification-aware multi-agent planning. Formaliza CIV com prova de contratos por task.
  • Augment CodeCoordinator-Implementor-Verifier Pattern for Dev Teams (2026).
  • AnthropicSubagents in the SDK (2026). Documenta context isolation, paralelização e restrição de tools em subagentes do Claude Agent SDK. code.claude.com/docs/en/agent-sdk/subagents
  • arxiv:2512.08769A Practical Guide for Designing, Developing, and Deploying Production-Grade Agentic AI Workflows (2025). arxiv.org/abs/2512.08769
  • KiroCustom subagents (2026). Specialist subagents como especialização do padrão CIV. kiro.dev/docs/chat/subagents
  • LangGraphMulti-agent coordination patterns (2026). StateGraph para CIV.
  • GitHub Spec KitMulti-agent workflow documentation (2026). Implement loop com validation nativa.

Como explicar em inglês

Em entrevistas e discussões técnicas em inglês, o padrão CIV tem vocabulário próprio que vai além de “multi-agent system” genérico. A ideia central para comunicar: “I don’t run one agent through the whole feature — a coordinator breaks the plan into a dependency graph, isolated implementors work each task with minimal context, and an independent validator checks the output against the spec before anything merges.”

PT-BRENNota de uso
coordenadorcoordinatorÚnico agente que vê spec e plan completos; não escreve código
implementadorimplementorExecuta uma task com contexto mínimo; “context-isolated by design”
validadorvalidatorVerifica ACs de forma independente; “independent” é a palavra-chave — não deve reusar contexto do implementor
grafo acíclico dirigidodirected acyclic graph (DAG)Estrutura de tasks com dependências explícitas; “the DAG is what enables safe parallelism”
isolamento de contextocontext isolationCada papel só recebe o que precisa; evita context rot e viés de confirmação
tarefataskUnidade que o implementor recebe: input, arquivos de escopo, ACs
critério de aceitaçãoacceptance criteria (AC)Verificado pelo validator como assertion, não como “parece bom”
paralelismoparallelismTasks com depends_on resolvido e sem arquivos compartilhados podem rodar ao mesmo tempo
replanejamentoreplanningCoordinator ajusta o DAG quando uma task falha, antes de escalar para humano
escalonamentoescalationQuando uma task falha N vezes (tipicamente 3), o coordinator para e chama um humano