~ / tutoriais /sistemas-multiagentes-orquestracao-assincrona $ _

Sistemas multiagentes: arquitetura e orquestração assíncrona na prática

Lucas Souza Lucas Souza 10 min de leitura Tutoriais
Sistemas multiagentes: arquitetura e orquestração assíncrona na prática

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.

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.

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.

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.

Lucas Souza
Lucas Souza

{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.

Você também pode gostar

Multi-agent em Laravel: 3 padrões testados em produção (Orchestrator, Hierarchical, Swarm)
Tutoriais

Multi-agent em Laravel: 3 padrões testados em produção (Orchestrator, Hierarchical, Swarm)

Três arquiteturas multi-agent que sobreviveram a um projeto Laravel em produção: Orchestrator-Worker, Hierarchical e Swarm. Tem código real (Prism PHP, PrismAgents, Bus::batch, State Machine), o anti-padrão dos "4 prompts em paralelo" e o custo medido (hierarchical 30% mais barato).

· 12 min
30 perguntas de entrevista para AI engineer (e como eu respondo cada uma)
Tutoriais

30 perguntas de entrevista para AI engineer (e como eu respondo cada uma)

30 perguntas reais (10 técnicas, 10 de arquitetura, 10 comportamentais) de entrevistas para AI engineer em maio de 2026. Pra cada uma: resposta curta de 30s, resposta de senior de 2min, e o red flag que entrega o junior. Mais 5 perguntas reversas pra filtrar empresa sem maturidade de IA.

· 14 min
Multi-agent com Claude: separando search, judge e writer (e quando isso é overengineering)
Tutoriais

Multi-agent com Claude: separando search, judge e writer (e quando isso é overengineering)

Quando vale a pena quebrar o agente único em sub-agentes especializados (search, judge, writer) e quando isso vira complexidade desnecessária. Padrão de orquestração com Claude, custo real em tokens e quando voltar para single-agent.

· 11 min
Arquitetura de agentes de IA: o blueprint de ponta a ponta
Notícias

Arquitetura de agentes de IA: o blueprint de ponta a ponta

A semana inteira em um diagrama só — as seis camadas de uma arquitetura de agentes de IA (modelo, contexto, tools/MCP, RAG, guardrails, observabilidade), como se encaixam e um checklist de produção pra defender o agente numa code review.

· 14 min

VirguIA

beer & code assistant

conectando…

Não foi possível iniciar o chat agora.

tocando