05-03-02 — Comunicação entre agentes: shared state vs message passing
TL;DR
Em sistemas multi-agent, agentes precisam trocar informações. Dois modelos: Shared State (todos acessam um contexto comum — simples, mas com race conditions) e Message Passing (agentes enviam mensagens estruturadas — mais robusto, mais complexo). A escolha impacta escalabilidade, consistência e custo de debug.
Shared State (estado compartilhado)
Todos os agentes acessam e modificam um objeto de estado centralizado. É como um quadro branco que todos podem ver e escrever.
graph TD
S[(Estado Compartilhado\nJSON/Dict)]
A1[Agent 1: Pesquisador] -->|lê/escreve| S
A2[Agent 2: Analista] -->|lê/escreve| S
A3[Agent 3: Escritor] -->|lê/escreve| S
style S fill:#1e40af,color:#fff
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
import operator
# Define o estado compartilhado (typed)
class ResearchState(TypedDict):
query: str
search_results: list[str]
analysis: str
final_report: str
messages: Annotated[list, operator.add] # append-only
# Cada nó (agente) lê e escreve no estado
def researcher(state: ResearchState) -> ResearchState:
results = search_web(state["query"])
return {"search_results": results} # Atualiza apenas seu campo
def analyst(state: ResearchState) -> ResearchState:
# Lê os resultados do pesquisador
analysis = analyze(state["search_results"])
return {"analysis": analysis}
def writer(state: ResearchState) -> ResearchState:
report = write_report(state["analysis"])
return {"final_report": report}
# Grafo com estado compartilhado (LangGraph)
graph = StateGraph(ResearchState)
graph.add_node("researcher", researcher)
graph.add_node("analyst", analyst)
graph.add_node("writer", writer)
graph.add_edge("researcher", "analyst")
graph.add_edge("analyst", "writer")
graph.add_edge("writer", END)
app = graph.compile()
result = app.invoke({"query": "Market share ERP Brasil 2024"})
LangGraph usa shared state: É o modelo nativo do LangGraph. O estado é um dict tipado que flui pelo grafo, cada nó recebe o estado atual e retorna as mudanças. Simples de debugar porque você vê o estado a qualquer ponto.
Message Passing (passagem de mensagens)
Agentes se comunicam enviando mensagens estruturadas. Não há estado global — cada agente tem seu próprio contexto e recebe apenas o que é enviado a ele.
graph LR
A1[Agent 1] -->|Message: {task, data}| Q[(Queue)]
Q -->|deliver| A2[Agent 2]
A2 -->|Message: {result}| Q2[(Queue)]
Q2 -->|deliver| A3[Agent 3]
style Q fill:#4c1d95,color:#fff
style Q2 fill:#4c1d95,color:#fff
import asyncio
from dataclasses import dataclass
from typing import Any
@dataclass
class AgentMessage:
sender: str
recipient: str
task: str
data: Any
correlation_id: str
# Message bus simples
class MessageBus:
def __init__(self):
self.queues: dict[str, asyncio.Queue] = {}
def register(self, agent_name: str):
self.queues[agent_name] = asyncio.Queue()
async def send(self, message: AgentMessage):
await self.queues[message.recipient].put(message)
async def receive(self, agent_name: str) -> AgentMessage:
return await self.queues[agent_name].get()
# Agente que usa message passing
class ResearcherAgent:
def __init__(self, bus: MessageBus):
self.bus = bus
bus.register("researcher")
async def run(self):
while True:
msg = await self.bus.receive("researcher")
results = await search_web(msg.data["query"])
# Envia resultado para o próximo agente
await self.bus.send(AgentMessage(
sender="researcher",
recipient="analyst",
task="analyze",
data={"results": results},
correlation_id=msg.correlation_id
))
Trade-offs: quando usar cada um
| Critério | Shared State | Message Passing |
|---|---|---|
| Simplicidade | ✅ Mais simples | ❌ Mais complexo |
| Debugabilidade | ✅ Estado visível | 💛 Requer tracing |
| Race conditions | ⚠️ Risco com paralelo | ✅ Isolado por design |
| Escalabilidade | 💛 Limitada ao processo | ✅ Distribuível (queues) |
| Agentes distribuídos | ❌ Difícil | ✅ Nativo (Kafka, Service Bus) |
| Consistência | ⚠️ Requer locks | ✅ Eventual consistency |
Modelo híbrido (comum em produção): Shared state dentro de um grafo de execução (LangGraph) + message passing para comunicação entre serviços diferentes (Azure Service Bus, Kafka). O estado local é shared; a comunicação entre microsserviços é via mensagens.
Azure Service Bus para multi-agent: Para sistemas multi-agent em escala, Azure Service Bus ou Azure Event Grid fornecem a infraestrutura de message passing. Cada agente é um serviço separado consumindo de uma fila. Isso permite deploy independente e scaling por agente.
Shared state + paralelismo = risco: Se dois agentes modificam o mesmo campo do estado ao mesmo tempo, você pode ter condições de corrida. LangGraph resolve isso com reducer functions (ex:
operator.add para listas). Sem reducers, use message passing para operações paralelas.
Como isso se conecta
Fontes
- LangGraph — Low Level Concepts (State Management) — documentação do modelo de shared state do LangGraph.
- Microsoft — Azure Service Bus overview — message passing em escala no Azure.
- Microsoft AutoGen — AgentChat — message passing entre agentes com AutoGen.
- Chen et al. — AgentVerse: Facilitating Multi-Agent Collaboration (2024) — análise de padrões de comunicação em sistemas multi-agent.