Sistema multiagente: quando vale dividir e quando é overhead
Um agente que faz tudo é fácil de demonstrar. Você cola um prompt, dá dez ferramentas pro modelo, grava o vídeo bonito e parece mágica. Aí vai pra produção. O agente começa a confundir ferramenta, esquece o que fez três passos atrás e despeja 8 mil tokens de contexto irrelevante em cima de uma subtarefa simples. A demo era fácil. Manter isso de pé é que é o problema.
A saída, em muitos casos, é parar de pedir que um único agente faça tudo. Dividir o trabalho entre vários agentes especializados e coordená-los. É disso que tratam os sistemas multiagentes: vários agentes de LLM, cada um com seu contexto e seu conjunto de ferramentas, trabalhando juntos sob alguma forma de orquestração.
Neste post a gente vai ver o que é um sistema multiagente, quando vale a pena dividir (e quando não vale), como funciona a arquitetura orquestrador-worker que a Anthropic usa em produção e como orquestrar isso de forma assíncrona — com código rodando, não slide.
TL;DR
- O que é: arquitetura onde vários agentes de LLM, cada um com contexto e ferramentas próprios, dividem um problema e são coordenados por um orquestrador.
- Stack/Modelos: Claude Agent SDK, Python,
asyncio. Padrão orquestrador-worker (lead em Opus, subagentes em Sonnet). - Custo/Acesso: multi-agente usa de 3 a 10× mais tokens que single-agent. Só vale quando a tarefa paga essa conta.
- Link útil: Async multi-agent orchestration — Anthropic Cookbook.
O que é um sistema multiagente (e por que não é "vários prompts")
Um sistema multiagente não é você chamar a API três vezes em sequência. É um conjunto de agentes — cada um com seu próprio loop de raciocínio, sua própria janela de contexto e suas próprias ferramentas — coordenados para resolver um problema que um agente sozinho resolveria mal.
A palavra que importa aqui é contexto. Cada subagente opera numa janela limpa, focada na tarefa dele. Isso resolve um problema concreto: poluição de contexto. Quando um único agente acumula histórico de pedido, log de erro, resultado de busca e mais um punhado de tool calls, a qualidade das respostas seguintes cai. A Anthropic descreve exatamente esse cenário: um agente de suporte que carrega 2 mil tokens de histórico enquanto tenta diagnosticar um problema técnico. Um subagente de busca processa o dado completo e devolve só um resumo de 50 a 100 tokens — o agente principal nunca vê o lixo.
Isso é o conceito. Na aplicação prática, vira três motivos para dividir:
- Isolamento de contexto. Cada agente enxerga só o que precisa. Menos ruído, menos alucinação por excesso de informação irrelevante.
- Paralelização. Agentes independentes rodam ao mesmo tempo e exploram um espaço de busca maior do que um agente serial cobriria.
- Especialização. Em vez de um agente com 20 ferramentas se confundindo, vários agentes com toolsets enxutos, cada um bom no que faz.
O impacto no produto é direto: um sistema mais confiável, que aguenta tarefa complexa sem desmontar quando o contexto cresce. Esse jogo de dividir contexto entre vários Claudes para não estourar o token budget eu já mostrei com números em Subagentes na prática.
A arquitetura orquestrador-worker
O padrão mais usado em produção é o orquestrador-worker. Um agente líder (lead) recebe o problema, planeja, decompõe em subtarefas independentes e dispara subagentes especializados — cada um numa faceta do problema. Depois sintetiza tudo numa resposta final.
A Anthropic usa exatamente isso no sistema de Research do Claude. O lead roda em Opus, analisa a query e monta a estratégia; os subagentes rodam em Sonnet e exploram aspectos específicos em paralelo. O número de agentes escala com a dificuldade da tarefa, segundo o post de engenharia deles:
Simple fact-finding requires just 1 agent with 3-10 tool calls, direct comparisons might need 2-4 subagents with 10-15 calls each, and complex research might use more than 10 subagents.
E o resultado não é marketing: o sistema multiagente com Opus 4 como lead e subagentes Sonnet 4 superou o Claude Opus 4 sozinho em 90,2% no eval interno de pesquisa deles.
Repare numa peça fácil de esquecer: o passo de síntese e citação. No Research, depois que os subagentes terminam, um CitationAgent dedicado recebe todos os achados e o relatório e identifica onde cada citação entra. Ou seja: dividir não termina no fan-out. Alguém precisa juntar — e juntar bem é metade do trabalho.
A forma de decompor também tem nome. A recomendação é decompor por contexto (o que cada agente precisa enxergar), não por tipo de trabalho. Dividir em "agente de planejar → agente de implementar → agente de testar" parece organizado, mas cada handoff perde contexto e gera overhead de coordenação. Isolamento bom é por escopo de informação, não por etapa de processo.
Se você quer ver esse mesmo padrão aterrissado em PHP — com Prism, Bus::batch e custo medido —, é o que destrinchei em Multi-agent em Laravel: 3 padrões testados em produção.
Um mapa rápido, para você saber onde está: este post é o hub do assunto — o conceito de sistema multiagente e o critério de decisão, agnóstico de stack. O satélite é o caso concreto, com um pipeline de três subagentes tipados rodando em Claude, handoff por artefato e a conta de tokens da implementação real: Multi-agent com Claude: separando search, judge e writer (e quando isso é overengineering). Se você ainda está decidindo se divide, fica aqui. Se já decidiu que divide e quer o código na mesa, vá pra lá.
Orquestração assíncrona na prática
Decompor em subagentes só compensa se eles rodarem ao mesmo tempo. Se o orquestrador dispara um subagente, espera, dispara o próximo, espera de novo, você jogou fora o principal ganho: paralelismo. É aqui que entra asyncio.
O cookbook de async multi-agent orchestration da Anthropic reduz isso a dois padrões essenciais, ambos sobre o Claude Agent SDK.
Padrão 1: fan-out paralelo com asyncio
O caso mais comum. O orquestrador decompõe a query, dispara N subagentes de uma vez e espera todos terminarem com asyncio.gather. Cada subagente roda no seu contexto, sem saber dos outros.
import asyncio
from anthropic import AsyncAnthropic
client = AsyncAnthropic()
async def subagente(faceta: str) -> str:
"""Roda um subagente focado numa faceta do problema."""
resp = await client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": f"Pesquise a fundo: {faceta}"}],
)
return resp.content[0].text
async def orquestrador(facetas: list[str]) -> list[str]:
# dispara todos os subagentes ao mesmo tempo
tarefas = [subagente(f) for f in facetas]
return await asyncio.gather(*tarefas)
facetas = [
"histórico de receita da empresa",
"composição do conselho",
"litígios em aberto",
]
achados = asyncio.run(orquestrador(facetas))
Três subagentes, três contextos limpos, tempo de parede de um subagente — não da soma dos três. O lead recebe os achados e parte pra síntese.
Padrão 2: time fixo de N agentes via hub de mensagens
Quando os agentes precisam trocar informação durante a execução — e não só no fim — o cookbook usa um hub compartilhado: um message bus / mailbox por onde os agentes publicam e leem mensagens. Cada agente tem seu loop assíncrono, lê o que chegou na caixa dele, processa e responde. O hub centraliza a comunicação e gerencia o ciclo de vida (quem está vivo, quem terminou).
import asyncio
class Hub:
"""Mailbox central: cada agente tem uma fila assíncrona."""
def __init__(self, nomes: list[str]):
self.caixas = {nome: asyncio.Queue() for nome in nomes}
async def enviar(self, destino: str, msg: dict):
await self.caixas[destino].put(msg)
async def receber(self, nome: str) -> dict:
return await self.caixas[nome].get()
async def agente(nome: str, hub: Hub):
while True:
msg = await hub.receber(nome)
if msg.get("tipo") == "encerrar":
break
# processa e, se precisar, responde a outro agente pelo hub
await hub.enviar(msg["responder_para"], {"de": nome, "ok": True})
A diferença prática entre os dois: o padrão 1 é para subtarefas independentes (a maioria dos casos de research). O padrão 2 é para quando os agentes têm que conversar ao longo do caminho. Comece pelo 1. Só vá pro 2 quando tiver evidência de que a coordenação em tempo real é necessária — porque ela é mais cara e mais difícil de depurar.
E aqui um detalhe que morde em produção: async espalha pontos de falha. Um subagente pode estourar rate limit, outro pode devolver lixo, um terceiro pode travar. A recomendação da Anthropic é pragmática — avisar o agente quando uma ferramenta falha e deixar ele se adaptar funciona surpreendentemente bem, combinado com retry e checkpoints regulares. Não trate o gather como se nunca fosse levantar exceção.
Tutorial te mostra o caminho — no Clã você constrói junto. Aula ao vivo toda semana, projetos reais de Engenharia de IA, ao lado de quem já está em produção.
Entrar no ClãQuando NÃO dividir
Aqui é onde a maioria dos posts mente por omissão. Multiagente não é default. É uma escolha com custo.
O custo literal: multi-agente usa de 3 a 10× mais tokens que single-agent para tarefa equivalente — e no sistema de Research, agentes usam ~4× mais tokens que um chat, e o multiagente chega a ~15× mais que um chat. Inclusive, o uso de tokens sozinho explica 80% da variância de performance no benchmark deles. Tradução: parte do ganho do multiagente vem só de gastar muito mais token. Se a sua tarefa não justifica essa conta, você está pagando caro por nada.
Não divida quando:
- A tarefa é sequencial e acoplada. Planejar → implementar → testar → revisar o mesmo projeto. Cada handoff perde contexto. É o caso clássico de overhead de coordenação maior que o ganho.
- Os agentes precisam de estado compartilhado o tempo todo. A própria Anthropic é direta: domínios "que exigem que todos os agentes compartilhem o mesmo contexto ou envolvem muitas dependências entre agentes não são um bom fit hoje". Modelos ainda não são ótimos em coordenar e delegar entre si em tempo real.
- A tarefa tem pouco valor. Overhead de coordenação não se paga em tarefa trivial.
Por isso a maior parte de coding ainda é território de single-agent: tem menos subtarefas genuinamente paralelizáveis do que research. A regra de ouro fecha o assunto: comece com a abordagem mais simples que funciona, e adicione complexidade só quando a evidência sustentar.
A conta do handoff: chamadas, tokens e latência
"3 a 10× mais tokens" é o resultado, não a explicação. A explicação é o handoff, e ele tem uma conta que dá pra fazer no guardanapo antes de escrever a primeira linha de código. Faça a sua com os seus números — em 2026 os preços por token continuam caindo, mas a estrutura da conta não mudou, e é ela que decide.
Chamadas extras. Um single-agent que resolve a tarefa em k turnos de ferramenta faz k + 1 requisições. O mesmo trabalho num fan-out de N subagentes faz:
requisições = 1 (plano do lead)
+ N × (k_sub + 1) (cada subagente e seus turnos)
+ 1 (síntese final)
Com N = 4 subagentes de k_sub = 5 turnos cada, são 26 requisições contra as 6 do single-agent equivalente. Repare que não é "4× mais chamadas porque são 4 agentes": é o fan-out mais duas chamadas serializadas — plano e síntese — que quase ninguém coloca na planilha.
Contexto duplicado. Aqui mora o dinheiro. Toda requisição a um LLM reenvia o prefixo inteiro: system prompt, schemas das ferramentas e o histórico acumulado até ali. Chame de S o prefixo fixo de um subagente (system prompt + definições de tools). O input cobrado não é S, é:
input_subagente ≈ Σ (S + histórico_i) para i em 1..k_sub
≈ k_sub × S + acúmulo dos resultados de ferramenta
Ou seja: S é pago k_sub vezes dentro de cada subagente, e N × k_sub vezes no sistema inteiro. Um toolset gordo de 2 mil tokens de schema, com 4 subagentes de 5 turnos, vira 40 mil tokens de input só para reapresentar as ferramentas — antes de qualquer conteúdo útil trafegar. É por isso que enxugar o toolset por agente não é higiene estética: é a maior alavanca de custo de um fan-out. Cortar S pela metade corta 20 mil tokens da execução.
Prompt caching é a primeira coisa a ligar contra isso. Cachear o prefixo estável (system + tools) faz a leitura sair por uma fração do preço de input, com um prêmio cobrado só na escrita da primeira vez. Como multiplicadores e TTL de cache mudam de tempos em tempos, pegue os valores atuais na tabela de preços da Anthropic e jogue na fórmula em vez de decorar: compare N × k_sub × S × preço_cache_read com N × k_sub × S × preço_input. A diferença entre os dois é, na prática, a diferença entre multi-agente viável e multi-agente que você desliga no fim do mês.
Latência. O erro comum é achar que paralelizar zera o custo de tempo. Não zera, porque duas etapas do handoff são inerentemente seriais:
T_total ≈ T_plano + max(T_subagente_i) + T_síntese
E T_plano não é time-to-first-token: o lead precisa do plano completo antes de despachar qualquer subagente, então você paga a geração inteira dele — TTFT + tokens_de_plano / throughput_de_saída. A síntese é igual, e só começa depois que o subagente mais lento entrega. Meça o throughput do seu modelo e da sua região em vez de chutar tokens por segundo, mas guarde a forma: o handoff cobra duas gerações completas de texto que o single-agent não paga, e o meio do sanduíche é max, não média. Com N subagentes, sua latência de parede é o p95 de um deles — quanto mais agentes, maior a chance de um deles ser o lento do dia.
Retry amplifica tudo. Se um subagente falha no quarto turno e você o reexecuta do zero, repaga o prefixo e os três turnos anteriores. Sem checkpoint por subagente e retry granular, uma falha em 1 de 4 subagentes pode custar mais que os outros 3 somados — e é exatamente esse cenário que aparece na fatura sem aparecer no eval.
Rode a conta antes de dividir. Se o veredito for "26 chamadas, 40 mil tokens de prefixo e duas gerações seriais a mais para ganhar uma qualidade que eu ainda não medi", a resposta é não dividir. Decidir dividir ou não é módulo do Lab: nos dias 19 e 20/09 a gente faz essa conta ao vivo, com tracing e custo na tela, no AI Engineering Lab, 3ª edição.
FAQ rápido
Quantos subagentes eu disparo? Escala com a tarefa. Fact-finding simples: 1 agente, 3–10 tool calls. Comparação direta: 2–4 subagentes. Research complexa: 10 ou mais. Não chute alto "por garantia" — cada subagente é token a mais.
Preciso de um framework de orquestração?
Não para começar. asyncio.gather resolve o fan-out paralelo da maioria dos casos. Frameworks (LangGraph e afins) ajudam em grafos de dependência complexos e estado compartilhado — mas adote quando a dor aparecer, não antes.
Lead e subagentes têm que ser o mesmo modelo? Não, e geralmente não devem ser. O padrão da Anthropic é lead mais forte (Opus) para planejar e sintetizar, subagentes mais baratos (Sonnet) para executar em paralelo. Você paga o modelo caro só onde ele faz diferença.
Como eu lido com um subagente que falha?
Não deixe a exceção derrubar o gather. Capture por subagente, avise o orquestrador que aquela ferramenta/faceta falhou e deixe ele decidir — repetir, seguir sem aquele pedaço ou degradar a resposta. Retry e checkpoint regular são o mínimo.
Conclusão
Sistema multiagente não é sofisticação por sofisticação. É uma resposta a um problema específico: um agente sozinho não dá conta de contexto que estoura a janela, de tarefas paralelizáveis ou de ferramentas demais para um loop só. Quando esse é o problema, dividir em orquestrador + workers, rodar assíncrono com asyncio e cuidar do passo de síntese resolve. Quando não é — quando a tarefa é sequencial, acoplada ou barata — dividir só multiplica o custo de token e o overhead de coordenação.
O próximo passo é parar de tratar "agente" como prompt e começar a tratar como arquitetura: contexto, orquestração, falha, custo. Esse salto — do prompt para o harness que sustenta o agente em produção — é o que a gente vai construir ao vivo no Do Prompt ao Harness: construindo um agente de vendas, um workshop prático que sai do prompt e vai até o harness de um agente rodando de verdade. Se este post te deu o mapa, o workshop é o código na mesa.
Porque agente bom em produção não é prompt bonito. É arquitetura, orquestração e a coragem de não dividir quando dividir não paga.
{AI Engineer} — apaixonado por Laravel, arquitetura de software e construir produtos com impacto. Compartilho aqui tutoriais, descobertas e reflexões sobre o dia a dia de engenharia.
Conteúdo é o que não falta. Falta quem desembaralhe: o que importa agora é como implementar do jeito certo. No Clã você tem isso ao vivo, toda semana, com quem já filtrou o ruído.
Entrar no Clã