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

```mermaid
    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.

```mermaid
    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.

```mermaid
    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.

```mermaid
    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.

```mermaid
    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.

```mermaid
    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`.

```python
# 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`:

```python
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:

```python
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).

```python
# 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:

```python
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:

```python
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.

```python
# 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):

```python
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:

```python
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.

```python
# 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.

```python
# 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.

```python
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.
