🧠FFVAcademy
🕸️

Multi-Agent Systems: orchestrator-worker, swarms e handoffs

17 min de leitura·+85 XP
Pré-requisitos (0/1)0%

Recomendamos completar os pré-requisitos antes de seguir, mas nada te impede de continuar.

Multi-agent soa maduro, vende bem em slide — e quebra mais vezes do que os artigos contam. Este módulo é o mapa dos padrões reais: orchestrator-worker, swarm com handoffs, hierarquias, panel of experts. E, mais importante, os critérios honestos para decidir se multi-agent vale a pena — ou se single-agent + tools é o certo.

A pergunta antes da topologia

⚠️
Regra-base (Anthropic, 2024): a maioria das "aplicações de IA" são single-agent com tools. Multi-agent entra quando paralelismo real ou especialização distinta justificam o custo de handoff. Se sua tarefa é sequencial e cabe no contexto de um agent, multi-agent só adiciona latência.
SinalSingle-agentMulti-agent
Sub-tarefas paralelizáveisPouco ganhoGanho real em latência
Contextos distintos (research vs coding)Contexto poluiEspecialização ajuda
Tarefa sequencial curtaIdealOverhead desnecessário
Necessidade de auditoria por etapaDifícil rastrearCada agent tem trace claro
Custo é críticoMenorHandoffs dobram/triplicam tokens
Debug por suporteSimplesRastrear handoffs vira projeto

Orchestrator-Worker: o padrão mais comum em produção

Um agent central (orchestrator) decompõe a tarefa, delega sub-tarefas a workers em paralelo, agrega os resultados. Workers não se comunicam entre si. Topologia simples, auditável, boa para pesquisa, análise multi-fonte e geração multi-secção.

🗺️ Orchestrator-Worker

                ┌─────────────────┐
                │  Orchestrator   │
                │  (plan + merge) │
                └────────┬────────┘
                         │ delega sub-tasks em paralelo
          ┌──────────────┼───────────────┐
          ▼              ▼               ▼
    ┌──────────┐   ┌──────────┐    ┌──────────┐
    │ Worker 1 │   │ Worker 2 │    │ Worker 3 │
    │ research │   │ research │    │ summariz │
    └────┬─────┘   └────┬─────┘    └────┬─────┘
         │              │                │
         └──────────────┼────────────────┘
                        │ retornos
                        ▼
                 Orchestrator agrega
                        │
                        ▼
                   Resposta final
python
# Orchestrator-worker — versão minimal em Python
import asyncio
from anthropic import AsyncAnthropic
client = AsyncAnthropic()

async def worker(role: str, task: str) -> str:
    r = await client.messages.create(
        model="claude-haiku-4-5-20251001",        # workers no modelo barato
        max_tokens=800,
        system=f"Você é um {role}. Responda objetivo, máx 400 palavras.",
        messages=[{"role": "user", "content": task}],
    )
    return r.content[0].text

async def orchestrate(user_query: str) -> str:
    # 1) Planner decide sub-tarefas (modelo forte para planejar)
    plan = await client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=500,
        system=(
            "Decomponha a pergunta em 2-4 sub-tarefas independentes em JSON: "
            "[{role, task}]. Cada sub-tarefa deve ser executável em paralelo."
        ),
        messages=[{"role": "user", "content": user_query}],
    )
    import json
    sub_tasks = json.loads(plan.content[0].text)

    # 2) Workers em paralelo
    results = await asyncio.gather(*[
        worker(st["role"], st["task"]) for st in sub_tasks
    ])

    # 3) Orchestrator agrega
    synthesis = await client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1200,
        messages=[{
            "role": "user",
            "content": (
                f"Pergunta original: {user_query}\n\n"
                f"Resultados dos workers:\n\n" +
                "\n\n---\n\n".join(results) +
                "\n\nSintetize uma resposta coerente, citando resultados quando útil."
            ),
        }],
    )
    return synthesis.content[0].text
Planejador (modelo forte) + workers (modelo barato) é o combo econômico. Paralelismo real com asyncio corta latência de N×T para max(T). Em pesquisa multi-fonte, isso pode ser 3-5× mais rápido que single-agent sequencial.

Swarm / Handoffs: o padrão de conversa que muda de papel

Em vez de um central delegar, cada agent pode transferir o controle para outro agent quando detecta que a próxima ação está fora do seu escopo. É o padrão de atendimento: triage → specialist → billing → escalation.

🗺️ Swarm com handoffs

  User
   │
   ▼
 ┌──────────────┐   handoff:
 │  Triage      │──► "é billing"
 │  agent       │
 └──────┬───────┘
        │ (usuário claramente pergunta conta)
        ▼
 ┌──────────────┐   handoff:
 │  Billing     │──► "precisa de human"
 │  agent       │
 └──────┬───────┘
        │
        ▼
 ┌──────────────┐
 │  Human       │
 │  agent (HITL)│
 └──────────────┘
python
# OpenAI Agents SDK — handoffs nativos
from agents import Agent, Runner, handoff

triage_agent = Agent(
    name="Triage",
    instructions=(
        "Identifique a intenção do usuário e transfira para o agent certo. "
        "Se não tem certeza, peça esclarecimento."
    ),
)

billing_agent = Agent(
    name="Billing",
    instructions=(
        "Você cuida de cobrança, fatura e plano. Tem acesso a tools "
        "get_invoice, update_payment. Se o usuário precisar de refund "
        "acima de US$50, transfira para Human."
    ),
    tools=[get_invoice, update_payment],
)

human_agent = Agent(
    name="Human",
    instructions="Abra ticket crítico para um humano resolver.",
    tools=[open_ticket],
)

# Wire handoffs
triage_agent.handoffs = [billing_agent]
billing_agent.handoffs = [human_agent]

# Run
result = await Runner.run(triage_agent, "Meu cartão não passou na renovação")
# Triage → Billing → (resolve ou) → Human

📋 Chatbot de atendimento com áreas distintas (vendas, suporte, billing)

Swarm / handoffs

Modelo mental natural: a conversa muda de 'especialista' conforme a intenção. Cada agent tem instruções, tools e policies próprias — mais limpo que um super-prompt misturando tudo.

Alt: Single-agent com router + system promptsmais simples, mas perde isolamento de tools e instruções

Alt: Orchestrator-workeroverkill — não há paralelismo real, é conversação sequencial

Hierarquias: orchestrator que delega a outros orchestrators

Em tarefas grandes (escrever relatório de 50 páginas, auditar codebase inteiro), uma camada só de workers não basta. Orchestrator delega a sub-orchestrators, cada um coordenando workers em seu domínio.

🗺️ Hierarquia de 3 níveis

                    ┌──────────────────┐
                    │  Top orchestrator│
                    │  (plano macro)   │
                    └────────┬─────────┘
                             │
               ┌─────────────┼─────────────┐
               ▼             ▼             ▼
        ┌──────────┐  ┌──────────┐  ┌──────────┐
        │ Research │  │ Analysis │  │ Writing  │
        │  coord.  │  │  coord.  │  │  coord.  │
        └────┬─────┘  └────┬─────┘  └────┬─────┘
             │             │             │
        [W][W][W]      [W][W][W]    [W][W][W]
⚠️
Hierarquia > 2 níveis multiplica custo de handoff e erros de compressão. Em 95% dos produtos, 2 níveis (orchestrator → workers) é suficiente. Hierarquias profundas são território de deep-research agents e pesquisa autônoma.

Panel of experts: agents paralelos + judge

Em decisões onde qualidade > custo (ex: resposta médica, revisão de código crítico), rode N agents independentes, cada um com persona/abordagem diferente, e um judge agrega ou escolhe.

python
# Panel of 3 experts + LLM judge escolhendo
import asyncio

PERSONAS = [
    "Você é um engenheiro sênior focado em segurança.",
    "Você é um engenheiro sênior focado em performance.",
    "Você é um engenheiro sênior focado em legibilidade.",
]

async def expert_review(persona: str, code: str) -> str:
    r = await client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=600,
        system=persona,
        messages=[{"role": "user", "content": f"Revise:\n\n{code}"}],
    )
    return r.content[0].text

async def panel_review(code: str) -> str:
    reviews = await asyncio.gather(*[expert_review(p, code) for p in PERSONAS])
    judge = await client.messages.create(
        model="claude-sonnet-4-6",
        max_tokens=1000,
        messages=[{
            "role": "user",
            "content": (
                "Três revisões de código. Consolide em uma revisão única, "
                "resolvendo conflitos e priorizando severidade:\n\n" +
                "\n\n---\n\n".join(reviews)
            ),
        }],
    )
    return judge.content[0].text

Frameworks: quando cada um vale em 2026

FrameworkForte emFraco em
Anthropic subagents (Task tool)Delegação dentro do Claude Code; integração MCPNão é lib standalone
OpenAI Agents SDKHandoffs, guardrails, tracing built-inAmarrado ao ecossistema OpenAI
CrewAIPrototipagem rápida de crews com role/goal/backstoryAbstrações escondem custos; menos controle em prod
LangGraphState-machine explícita, fluxos complexos e ciclosVerboso; curva de aprendizado alta
AutoGen (Microsoft)Conversational multi-agent, coding especializadoOutput menos determinístico; menos usado em 2026
Roll your own (SDK + asyncio)Controle total, zero dependênciaVocê reimplementa retry, tracing, handoff etc.

📋 Primeira versão de multi-agent em produto existente

SDK nativo do seu modelo + asyncio

Você entende exatamente o que acontece. Debugging é ler seu código. Adicione framework quando a complexidade (5+ agents, state machine com ciclos, múltiplos providers) justificar.

Alt: OpenAI Agents SDKse já estiver 100% no ecossistema OpenAI

Alt: LangGraphquando o fluxo vira state-machine complexa com reentrância

Reliability em multi-agent: o que realmente quebra

ProblemaCausa raizMitigação
Contexto explodindoCada handoff copia histórico crescenteCompressão/summary explícito a cada handoff
Custo 10× do esperadoLoops de handoff (A→B→A→B)max_handoffs, trace de topologia
Resposta final perde infoWorker relatou, orchestrator resumiu malSchemas estruturados (JSON) em vez de prosa livre
Deadlock (tudo aguardando)Handoff circular sem terminalSempre ter agent terminal que responde ao user
Debug impossívelTrace de conversação em N agentsTracing estruturado (Langfuse, LangSmith, OTel)
Erro de guardrailWorker viola policy definida no orchestratorGuardrails por agent, validação no judge

Perguntas típicas

Multi-agent é sempre pior em latência?

Não. Orchestrator-worker com workers paralelos pode ser muito mais rápido que single-agent sequencial — N requests em paralelo = max(T) em vez de sum(T). O que costuma ser pior é swarm sequencial, onde a conversa passa por vários agents em série.

Posso misturar modelos diferentes em um sistema multi-agent?

Pode e costuma ser ótimo. Planner em Opus/GPT-5 (qualidade), workers em Haiku/gpt-4o-mini (custo), judge em modelo de família diferente do gerador (reduzir viés). O único cuidado é validar que tools funcionam em todos (tool_use tem sutilezas entre providers).

Como faço trace/observability em multi-agent?

OpenTelemetry com semantic conventions de LLM (spans para cada chamada, atributos de modelo/tokens), ou ferramentas prontas (Langfuse, LangSmith, Phoenix). Estruture trace hierárquico: run → agent → chamada. Sem isso, debug em prod é pesadelo.

Quando devo fugir de multi-agent e voltar para workflow?

Quando você observa: (a) erros recorrentes em handoff (info perdida), (b) custo 3×+ do esperado, (c) latência p95 estourando SLO, (d) time gasta mais debugando agents que entregando features. Workflow com 2-3 LLM calls costuma resolver 80% dos casos sem essas dores.
Take-aways.Multi-agent não é upgrade automático — é trade-off. Orchestrator-worker para paralelismo real; swarm/handoffs para conversas que mudam de papel; hierarquia só quando 2 níveis não bastam; panel-of-experts para qualidade > custo. Handoff design (o que passa, em que schema) é onde multi-agent quebra. Frameworks ajudam mas escondem — comece no SDK nativo. Próximo: context engineering — como extrair máximo de cada janela e agent sem pagar preço absurdo.
🧩

Quiz rápido

4 perguntas · Acerte tudo e ganhe o badge 🎯 Gabarito

Continue lendo