Skip to main content

Command Palette

Search for a command to run...

Sistemas Multi-Agentes com AI: Do Conceito à Produção

Agentes, orquestração, frameworks e as armadilhas que ninguém te conta

Updated
17 min read
Sistemas Multi-Agentes com AI: Do Conceito à Produção

Todo mundo tá falando de "agentes de AI". Metade não sabe o que é. A outra metade tá construindo coisas que não precisavam ser multi-agent. Vou explicar do zero, passar pelos padrões de orquestração, mostrar código real com três frameworks diferentes e fechar com as armadilhas que vão te custar dinheiro e sanidade se você não prestar atenção.

O que é um agente de AI (e o que NÃO é)

Um chatbot recebe input, gera output. Fim. Um agente é diferente: ele tem um loop de decisão. Ele recebe um objetivo, decide o que fazer, executa uma ação, observa o resultado e decide de novo. Repete até resolver ou desistir.

A diferença fundamental:

  • Chatbot: input → output

  • Agente: objetivo → (pensar → agir → observar) → repetir até concluir

Na prática, um agente é um LLM com acesso a tools (funções que ele pode chamar) e capacidade de decidir sozinho qual tool usar e quando parar. Quando você dá pro Claude ou GPT acesso a busca na web, execução de código e leitura de arquivos, e ele decide sozinho qual usar pra responder sua pergunta, isso é um agente.

O que não é um agente:

  • Um prompt elaborado com chain-of-thought. Isso é prompting.

  • Um pipeline fixo onde o LLM é chamado em etapas predefinidas. Isso é um workflow.

  • Um RAG que busca documentos e gera resposta. Isso é retrieval + generation.

Agente precisa de autonomia na decisão. Se o fluxo tá hardcoded, não é agente. É automação com LLM.

De um agente solo pra vários: por que multi-agent?

Um agente solo funciona bem pra tarefas focadas. Tipo: "pesquise sobre X e me dê um resumo". Mas quando a tarefa fica complexa, um agente sozinho começa a sofrer.

Três problemas concretos:

1. Context window explode. Um agente que pesquisa, analisa dados, escreve código e faz review tá acumulando contexto de tudo numa janela só. Chega uma hora que a qualidade degrada porque o modelo perde informação no meio do contexto gigante.

2. Especialização importa. Um prompt que tenta fazer o LLM ser pesquisador, analista, programador e revisor ao mesmo tempo vai ser medíocre em tudo. Prompts focados geram resultados melhores.

3. Paralelismo. Se você precisa pesquisar três fontes diferentes, por que fazer sequencial se pode fazer em paralelo?

Aí entra multi-agent: você divide a tarefa em agentes especializados, cada um com seu prompt, suas tools e seu pedaço do contexto. Um orquestra os outros.

Pensa num time de desenvolvimento. Você não coloca um dev fullstack sozinho pra fazer frontend, backend, banco, infra e QA num projeto grande. Você monta uma squad. Cada pessoa com seu papel, seu contexto e sua especialidade. Com agentes é a mesma coisa. Separar responsabilidades evita que o contexto vire uma sopa e cada agente fica afiado no que faz.

A complexidade aumenta? Sim. Mas a qualidade do resultado também. E o ganho em manutenibilidade compensa: quando o agente escritor tá gerando texto ruim, você mexe no prompt dele sem afetar o pesquisador ou o revisor. Isolamento de contexto é um superpoder.

Padrões de orquestração

Existem padrões bem definidos pra organizar como múltiplos agentes trabalham juntos. Cada um resolve um tipo de problema.

Sequential (Pipeline)

O mais simples. Agente A termina, passa o resultado pro Agente B, que passa pro C.

    A[Pesquisador] --> B[Escritor] --> C[Revisor]

Usa quando: a tarefa tem etapas claras e cada etapa depende da anterior. Tipo pesquisar → escrever → revisar.

Trade-off: é lento (sem paralelismo) mas previsível e fácil de debugar. Se o Agente B deu resultado ruim, você sabe exatamente o que o Agente A passou pra ele.

Parallel (Fan-out / Fan-in)

Vários agentes rodam ao mesmo tempo, cada um fazendo sua parte. Os resultados são agregados no final.

    O[Orquestrador] --> A[Pesquisador Web]
    O --> B[Pesquisador DB]
    O --> C[Pesquisador Docs]
    A --> R[Agregador]
    B --> R
    C --> R

Usa quando: tarefas independentes que podem rodar em paralelo. Tipo buscar informações de fontes diferentes, ou analisar múltiplos arquivos.

Trade-off: rápido, mas a agregação dos resultados é onde mora o diabo. Os agentes podem retornar informações conflitantes e aí alguém precisa decidir o que vale.

Loop (Iterativo)

Um ou mais agentes rodam em loop até uma condição ser satisfeita.

    A[Gerador] --> B[Avaliador]
    B -->|Não aprovado| A
    B -->|Aprovado| C[Output]

Usa quando: a tarefa precisa de refinamento iterativo. Tipo gerar código → rodar testes → se falhou, corrigir → rodar de novo.

Trade-off: perigoso. Se a condição de saída nunca for satisfeita, você tem um loop infinito queimando tokens. Sempre coloque um limite máximo de iterações. Sempre.

Hierarchical (Supervisor)

Um agente supervisor recebe a tarefa, decide quais sub-agentes acionar e em que ordem. Ele delega, recebe resultados e decide o próximo passo.

    S[Supervisor] --> A[Pesquisador]
    S --> B[Programador]
    S --> C[Analista]
    A -->|resultado| S
    B -->|resultado| S
    C -->|resultado| S
    S --> D[Output Final]

Usa quando: a decomposição da tarefa não é óbvia e precisa de um LLM decidindo o fluxo. É o padrão mais flexível e o mais caro.

Trade-off: o supervisor é um ponto único de falha. Se ele alucina e delega errado, tudo vai pro lixo. E cada chamada ao supervisor é uma chamada extra ao LLM.

Swarm / Handoff

Agentes se passam o controle entre si baseado no contexto da conversa. Não tem um supervisor central. Cada agente sabe quando deve passar o bastão pra outro.

    A[Atendimento] -->|problema técnico| B[Suporte Técnico]
    A -->|problema financeiro| C[Financeiro]
    B -->|precisa escalar| D[Engenharia]
    C -->|precisa escalar| D

Usa quando: cenários tipo atendimento ao cliente, onde o fluxo depende do que o usuário pede. Cada agente é especialista num domínio e transfere pro próximo quando sai do seu escopo.

Trade-off: difícil de debugar porque o fluxo é dinâmico. E se os critérios de handoff forem ambíguos, os agentes podem ficar jogando a tarefa um pro outro num ping-pong infinito.

Selector Group Chat

Vários agentes numa "conversa em grupo" onde um seletor (geralmente um LLM) decide quem fala a cada turno baseado no contexto.

    SEL[Seletor] --> A[Agente Planner]
    SEL --> B[Agente Coder]
    SEL --> C[Agente Critic]
    A -->|mensagem| SEL
    B -->|mensagem| SEL
    C -->|mensagem| SEL
    SEL -->|termination| D[Output]

Usa quando: tarefas complexas onde múltiplas perspectivas são necessárias e a ordem de participação não é predefinida. O seletor escolhe dinamicamente quem contribui.

Trade-off: o custo explode porque cada turno tem uma chamada extra pro seletor decidir quem fala. E a conversa pode ficar circular se os agentes ficarem repetindo argumentos.

Na prática: código com Google ADK, CrewAI e AutoGen

Chega de teoria. Vou implementar o mesmo cenário nos três frameworks: um sistema que pesquisa um tópico, escreve um resumo e faz review.

Google ADK

O ADK do Google tem agentes de workflow prontos: SequentialAgent, ParallelAgent, LoopAgent. Pra delegação inteligente, você usa um LlmAgent com sub_agents.

# pip install google-adk

from google.adk.agents import LlmAgent, SequentialAgent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types

# Agente pesquisador
researcher = LlmAgent(
    name="researcher",
    model="gemini-2.0-flash",
    instruction="""Você é um pesquisador. Dado um tópico, 
    liste os 5 pontos mais relevantes com fontes.
    Seja factual e conciso.""",
    output_key="research_results"  # salva no state
)

# Agente escritor
writer = LlmAgent(
    name="writer",
    model="gemini-2.0-flash",
    instruction="""Você é um escritor técnico. Use os resultados 
    da pesquisa em {research_results} pra escrever um resumo 
    claro e bem estruturado de 3 parágrafos.""",
    output_key="draft"
)

# Agente revisor
reviewer = LlmAgent(
    name="reviewer",
    model="gemini-2.0-flash",
    instruction="""Você é um revisor. Leia o rascunho em {draft} 
    e forneça a versão final corrigida. Corrija erros factuais, 
    melhore clareza, mantenha o tom técnico.""",
    output_key="final_output"
)

# Pipeline sequencial
pipeline = SequentialAgent(
    name="content_pipeline",
    sub_agents=[researcher, writer, reviewer]
)

# Execução
session_service = InMemorySessionService()
runner = Runner(
    agent=pipeline,
    app_name="content_app",
    session_service=session_service
)

async def run():
    session = await session_service.create_session(
        app_name="content_app", user_id="user1"
    )
    
    message = types.Content(
        role="user",
        parts=[types.Part(text="Kubernetes autoscaling em 2025")]
    )
    
    async for event in runner.run_async(
        session_id=session.id, user_id="user1", new_message=message
    ):
        if event.is_final_response():
            print(event.content.parts[0].text)

import asyncio
asyncio.run(run())

O ADK com SequentialAgent cuida do fluxo automaticamente. O output_key salva o resultado de cada agente no state da sessão, e o próximo agente acessa via template {key}.

Pra paralelo, troca SequentialAgent por ParallelAgent:

from google.adk.agents import ParallelAgent

# Três pesquisadores rodando em paralelo
parallel_research = ParallelAgent(
    name="parallel_research",
    sub_agents=[researcher_web, researcher_papers, researcher_docs]
)

Pra loop com condição de saída:

from google.adk.agents import LoopAgent

# Loop: gera código → testa → corrige (máx 3 iterações)
code_loop = LoopAgent(
    name="code_refinement",
    sub_agents=[coder, tester],  # tester chama escalate() pra sair
    max_iterations=3
)

O ponto forte do ADK: os workflow agents (Sequential, Parallel, Loop) são determinísticos. Não gastam tokens extras pra orquestração. O fluxo é definido no código, não por um LLM decidindo o próximo passo. Se você quer delegação dinâmica via LLM, aí sim usa um LlmAgent como supervisor com sub_agents.

CrewAI

CrewAI pensa em termos de Crew (equipe), Agents (membros) e Tasks (tarefas).

# pip install crewai

from crewai import Agent, Task, Crew, Process

# Agentes
researcher = Agent(
    role="Pesquisador",
    goal="Encontrar informações relevantes e atualizadas sobre o tópico",
    backstory="""Você é um pesquisador meticuloso que prioriza 
    fontes confiáveis e dados verificáveis.""",
    verbose=True,
    llm="gpt-4o"
)

writer = Agent(
    role="Escritor Técnico",
    goal="Transformar pesquisa em conteúdo claro e bem estruturado",
    backstory="""Você é um escritor técnico que traduz informações 
    complexas em texto acessível sem perder profundidade.""",
    verbose=True,
    llm="gpt-4o"
)

reviewer = Agent(
    role="Revisor",
    goal="Garantir qualidade, precisão e clareza do conteúdo",
    backstory="""Você é um revisor experiente que identifica 
    erros factuais, problemas de clareza e inconsistências.""",
    verbose=True,
    llm="gpt-4o"
)

# Tasks
research_task = Task(
    description="Pesquise sobre {topic}. Liste os 5 pontos mais relevantes.",
    expected_output="Lista de 5 pontos com explicação e fontes",
    agent=researcher
)

writing_task = Task(
    description="Escreva um resumo de 3 parágrafos baseado na pesquisa.",
    expected_output="Texto de 3 parágrafos, claro e técnico",
    agent=writer,
    context=[research_task]  # recebe output da pesquisa
)

review_task = Task(
    description="Revise o texto. Corrija erros e melhore clareza.",
    expected_output="Texto final revisado e polido",
    agent=reviewer,
    context=[writing_task]
)

# Crew sequencial
crew = Crew(
    agents=[researcher, writer, reviewer],
    tasks=[research_task, writing_task, review_task],
    process=Process.sequential,
    verbose=True
)

result = crew.kickoff(inputs={"topic": "Kubernetes autoscaling em 2025"})
print(result.raw)

Pra modo hierárquico com supervisor:

crew = Crew(
    agents=[researcher, writer, reviewer],
    tasks=[research_task, writing_task, review_task],
    process=Process.hierarchical,
    manager_llm="gpt-4o",  # LLM que age como supervisor
    verbose=True
)

No modo hierárquico, o CrewAI cria um agente manager automaticamente que decide a ordem de execução e delega tarefas. Você não define explicitamente quem faz o quê primeiro.

CrewAI também tem memory embutida:

crew = Crew(
    agents=[researcher, writer, reviewer],
    tasks=[research_task, writing_task, review_task],
    process=Process.sequential,
    memory=True,  # habilita short-term, long-term e entity memory
    verbose=True
)

O ponto forte do CrewAI: abstração de alto nível. O conceito de role, goal e backstory pro agente é intuitivo. Pra quem tá começando, é o framework mais fácil de entender. O trade-off é que você tem menos controle sobre o que tá acontecendo por baixo.

AutoGen (Microsoft)

AutoGen v0.4+ tem a API AgentChat de alto nível. Os padrões de grupo (SelectorGroupChat, Swarm) são cidadãos de primeira classe.

# pip install autogen-agentchat autogen-ext[openai]

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import RoundRobinGroupChat
from autogen_agentchat.conditions import TextMentionTermination
from autogen_ext.models.openai import OpenAIChatCompletionClient

model_client = OpenAIChatCompletionClient(model="gpt-4o")

# Agentes
researcher = AssistantAgent(
    name="researcher",
    model_client=model_client,
    system_message="""Você é um pesquisador. Dado um tópico, 
    liste os 5 pontos mais relevantes. Seja factual e conciso."""
)

writer = AssistantAgent(
    name="writer",
    model_client=model_client,
    system_message="""Você é um escritor técnico. Baseado na pesquisa 
    apresentada, escreva um resumo de 3 parágrafos."""
)

reviewer = AssistantAgent(
    name="reviewer",
    model_client=model_client,
    system_message="""Você é um revisor. Revise o texto, corrija erros 
    e melhore clareza. Quando estiver satisfeito, inclua 
    APPROVED no final."""
)

# Round-robin: cada agente fala na sua vez
termination = TextMentionTermination("APPROVED")

team = RoundRobinGroupChat(
    participants=[researcher, writer, reviewer],
    termination_condition=termination,
    max_turns=6
)

async def run():
    result = await team.run(
        task="Kubernetes autoscaling em 2025"
    )
    print(result.messages[-1].content)

import asyncio
asyncio.run(run())

Pra Selector Group Chat (o LLM decide quem fala):

from autogen_agentchat.teams import SelectorGroupChat

team = SelectorGroupChat(
    participants=[researcher, writer, reviewer],
    model_client=model_client,  # LLM que decide quem fala
    termination_condition=termination,
    max_turns=10
)

Pra Swarm com handoff explícito:

from autogen_agentchat.agents import AssistantAgent
from autogen_agentchat.teams import Swarm
from autogen_agentchat.conditions import HandoffTermination

support = AssistantAgent(
    name="support",
    model_client=model_client,
    handoffs=["engineering"],  # pode transferir pra engineering
    system_message="""Você é suporte nível 1. Se o problema for 
    técnico demais, transfira pra engineering."""
)

engineering = AssistantAgent(
    name="engineering",
    model_client=model_client,
    handoffs=["support"],
    system_message="""Você é engenharia. Resolva problemas técnicos. 
    Se for dúvida simples, devolva pro support."""
)

team = Swarm(
    participants=[support, engineering],
    termination_condition=TextMentionTermination("RESOLVED"),
    max_turns=10
)

O ponto forte do AutoGen: flexibilidade nos padrões de comunicação. SelectorGroupChat e Swarm são poderosos pra cenários dinâmicos. O GraphFlow permite definir grafos complexos de comunicação. O trade-off é a curva de aprendizado: a API é mais verbosa e a documentação teve mudanças grandes entre v0.2 e v0.4.

Comparativo real dos frameworks

Aspecto Google ADK CrewAI AutoGen
Curva de aprendizado Média Baixa Alta
Workflow determinístico SequentialAgent, ParallelAgent, LoopAgent Process.sequential RoundRobinGroupChat
Delegação por LLM LlmAgent com sub_agents Process.hierarchical SelectorGroupChat
Swarm/Handoff Via transfer_to_agent() Não nativo Swarm nativo
Memory Session state Short/long-term/entity Memory capabilities
Linguagens Python, TS, Go, Java Python Python, .NET
Lock-in de modelo Otimizado pra Gemini, suporta outros Agnóstico Agnóstico
Debugging Bom (Astra, logs estruturados) Razoável (verbose mode) Razoável (event logging)
Maturidade Novo (2025) Estável Em transição (v0.2→v0.4)

Minha leitura:

Google ADK brilha quando você quer workflow agents determinísticos (Sequential, Parallel, Loop) sem gastar tokens extras com orquestração. A separação clara entre workflow agents (código controla o fluxo) e LLM agents (modelo controla o fluxo) é elegante. Se você já tá no ecossistema Google/Gemini, é escolha natural.

CrewAI é o melhor pra começar. A abstração de role/goal/backstory é intuitiva. Pra pipelines simples tipo "pesquise, escreva, revise", funciona muito bem com pouco código. Fica limitado quando você precisa de padrões mais complexos que sequential e hierarchical.

AutoGen é o mais poderoso em termos de padrões de comunicação. SelectorGroupChat, Swarm, GraphFlow cobrem praticamente qualquer cenário. Mas a complexidade da API e as mudanças entre versões são um custo real. Usa quando o cenário realmente pede comunicação dinâmica entre agentes.

As armadilhas que ninguém te conta

1. Loops infinitos queimando dinheiro

O agente revisor reprova. O escritor reescreve. O revisor reprova de novo. O escritor reescreve. Isso pode rodar 50 vezes antes de você perceber.

# ERRADO
loop = LoopAgent(
    name="refinement",
    sub_agents=[writer, reviewer]
    # sem max_iterations = conta do cartão chorando
)

# CERTO
loop = LoopAgent(
    name="refinement",
    sub_agents=[writer, reviewer],
    max_iterations=3  # SEMPRE defina um limite
)

Regra: todo loop precisa de max_iterations. Sem exceção. E coloque alertas de custo. Se uma execução passar de X dólares, mate o processo.

2. Custo explodindo silenciosamente

Cada agente é uma chamada ao LLM. Num sistema com supervisor + 3 agentes em loop de 3 iterações, você tem:

  • 1 chamada pro supervisor decidir

  • 3 chamadas pros agentes

  • × 3 iterações

    • 1 chamada final pro supervisor

Ou seja: 13 chamadas pra uma única tarefa. Com GPT-4o a ~\(5/1M tokens de input, uma tarefa complexa pode custar \)0.50 a $2.00. Multiplica por mil usuários por dia.

Dica prática: use modelos menores (GPT-4o-mini, Gemini Flash, Claude Haiku) pros agentes que fazem trabalho braçal. Reserve o modelo grande pro supervisor e pro agente que precisa de mais raciocínio.

# Modelo caro só pro supervisor
supervisor = LlmAgent(model="gpt-4o", ...)

# Modelo barato pros trabalhadores
researcher = LlmAgent(model="gemini-2.0-flash", ...)
writer = LlmAgent(model="gpt-4o-mini", ...)

3. Debugging impossível

Quando algo dá errado num pipeline de 4 agentes, boa sorte descobrindo onde foi. O Agente C produziu lixo. Foi porque o Agente B passou contexto ruim? Ou porque o Agente A pesquisou errado? Ou porque o prompt do C tá mal escrito?

Solução: logue tudo. Cada input e output de cada agente. Cada chamada ao LLM com o prompt completo e a resposta. Sem isso, você tá debugando no escuro.

import logging

logging.basicConfig(level=logging.DEBUG)

# No CrewAI
crew = Crew(..., verbose=True)

# No ADK, use callbacks ou o Astra debugger

# No AutoGen, capture os eventos
async for message in team.run_stream(task="..."):
    print(f"[{message.source}]: {message.content[:200]}")

4. Context window overflow

Cada agente acumula contexto. Num group chat com 5 agentes, depois de 10 turnos, cada agente tá recebendo todas as mensagens anteriores. O contexto cresce exponencialmente.

O que acontece quando estoura: o modelo começa a ignorar informação do início (lost-in-the-middle), alucina mais, e eventualmente a API retorna erro.

Mitigações:

  • Sumarize o contexto periodicamente em vez de passar o histórico completo

  • Use output_key (ADK) ou context (CrewAI) pra passar só o relevante, não tudo

  • Defina max_turns agressivo

  • Considere modelos com janela maior (Gemini 1M tokens) quando o contexto é realmente necessário

5. Alucinação em cascata

Agente A alucina um dado. Agente B usa esse dado como fato. Agente C constrói uma análise inteira em cima. O output final tá completamente errado mas parece convincente porque foi "validado" por múltiplos agentes.

Multi-agent não reduz alucinação automaticamente. Pode até amplificar. O fato de três agentes concordarem não significa nada se todos estão operando sobre a mesma informação alucinada.

Mitigação: tenha pelo menos um agente com acesso a tools que verificam informação (busca web, consulta a banco de dados). Não confie em agentes que só raciocinam sem ground truth.

6. O overhead da comunicação

Agentes precisam se comunicar em linguagem natural. Isso é ineficiente. Quando o Agente A passa resultado pro B, ele serializa em texto, o B precisa parsear, entender e usar. Informação se perde nessa tradução.

Compare com código normal onde você passa um objeto estruturado entre funções. Zero ambiguidade. Agentes conversando em texto natural introduzem ambiguidade em cada handoff.

Dica: use outputs estruturados (JSON) entre agentes quando possível. A maioria dos frameworks suporta isso.

Quando usar (e quando NÃO usar)

Usa multi-agent quando:

  • A tarefa tem sub-tarefas claramente distintas que se beneficiam de prompts especializados

  • Você precisa de paralelismo real (pesquisar múltiplas fontes ao mesmo tempo)

  • O fluxo é dinâmico e depende do resultado intermediário (tipo suporte ao cliente com escalação)

  • O contexto de uma tarefa única não cabe na janela do modelo

Onde um agente solo ainda faz sentido:

  • Tarefas simples e isoladas. "Resuma esse texto", "traduza isso", "responda essa pergunta". Montar uma squad pra isso é overhead desnecessário.

  • Protótipos rápidos. Quando você tá validando uma ideia, começa com um agente e evolui pra multi quando a complexidade pedir.

Mas pra qualquer coisa que envolva múltiplas etapas, múltiplos domínios de conhecimento ou contextos que não deveriam se misturar, multi-agent é o caminho. Pensa na analogia da squad: um projeto complexo com um dev solo vira um monolito de contexto onde tudo se mistura. Separar em agentes especializados é como ter cada membro do time focado no que faz melhor, com seu próprio escopo, sem poluir o contexto dos outros.

O segredo tá na modelagem. Comece identificando os papéis claros (pesquisador, escritor, revisor, analista), defina o escopo de cada um e escolha o padrão de orquestração que faz sentido pro fluxo. Comece simples (sequential), meça os resultados e evolua a arquitetura conforme a necessidade. Multi-agent não é hype. É arquitetura de software aplicada a agentes de AI.