Memória compartilhada e comunicação entre agentes
Implemente uma camada de memória compartilhada usando um armazenamento de chave-valor do qual os agentes leiam e no qual escrevam, permitindo colaboração assíncrona sem acoplamento rígido entre eles.
Memória compartilhada e comunicação entre agentes é uma aula grátis de AI Engineering Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Engineering Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Engineering Academy inclui 4 aulas no total.
O problema do isolamento dos agentes
Em um sistema multiagente, cada agente é executado em seu próprio contexto e não tem conhecimento do que os outros agentes estão fazendo ou já fizeram. Se um agente pesquisador descobrir um fato importante, como o agente redator ficará sabendo? Como um agente de monitoramento saberá quando o agente programador encontrar um erro? Sem um mecanismo de comunicação compartilhado, os agentes ficam isolados em compartimentos que não conseguem colaborar de maneira eficaz.
Memória compartilhada: o modelo Blackboard
A solução clássica para a comunicação entre agentes é o modelo Blackboard: um armazenamento de dados compartilhado (o Blackboard) do qual qualquer agente pode ler ou no qual pode escrever. Os agentes publicam suas descobertas, leem as contribuições dos outros e se coordenam implicitamente por meio do estado compartilhado. Esse modelo desacopla os agentes uns dos outros: eles não precisam conhecer a existência uns dos outros, apenas a estrutura da memória compartilhada.
# Simple in-memory blackboard using a dictionary
from threading import Lock
class Blackboard:
def __init__(self):
self._data = {}
self._lock = Lock() # thread-safe for parallel agents
def write(self, key: str, value, agent_id: str):
with self._lock:
self._data[key] = {'value': value, 'written_by': agent_id}
print(f'[{agent_id}] wrote: {key}')
def read(self, key: str):
with self._lock:
return self._data.get(key, {}).get('value')
def keys(self):
with self._lock:
return list(self._data.keys())
blackboard = Blackboard()Memória compartilhada persistente com Redis
Para sistemas multiagente de produção nos quais os agentes são executados como processos ou serviços separados, dicionários mantidos na memória não são suficientes. Redis é a opção mais popular para a memória compartilhada dos agentes: é rápido, oferece suporte a tipos de dados avançados (strings, hashes, listas e conjuntos ordenados), possui TTL integrado para expiração e lida com leituras e escritas simultâneas com segurança por meio de operações atômicas.
import redis
import json
class RedisSharedMemory:
def __init__(self, prefix='agent:'):
self.redis = redis.Redis(host='localhost', port=6379, decode_responses=True)
self.prefix = prefix
def set(self, key: str, value, ttl_seconds=3600):
full_key = self.prefix + key
self.redis.setex(full_key, ttl_seconds, json.dumps(value))
def get(self, key: str):
full_key = self.prefix + key
raw = self.redis.get(full_key)
return json.loads(raw) if raw else None
def append_to_list(self, key: str, item):
full_key = self.prefix + key
self.redis.rpush(full_key, json.dumps(item))
def get_list(self, key: str):
full_key = self.prefix + key
return [json.loads(x) for x in self.redis.lrange(full_key, 0, -1)]
memory = RedisSharedMemory(prefix='research_project:')Definindo namespaces na memória compartilhada
Em sistemas multiagente complexos, os agentes escrevem muitos tipos diferentes de dados, e um namespace de chaves plano rapidamente se torna caótico. Use um namespace hierárquico para organizar claramente a memória compartilhada. Um padrão comum é project_id:agent_role:data_type, por exemplo proj_123:researcher:findings ou proj_123:coder:error_log. Isso facilita consultar todos os dados de um projeto ou todas as saídas de um agente específico.
class NamespacedMemory:
def __init__(self, project_id: str, agent_id: str, redis_client):
self.base = f'{project_id}:{agent_id}'
self.redis = redis_client
def write_finding(self, topic: str, content: str):
key = f'{self.base}:findings:{topic}'
self.redis.set(key, content)
def read_all_findings(self, project_id: str):
# Read findings from ALL agents in this project
pattern = f'{project_id}:*:findings:*'
keys = self.redis.keys(pattern)
return {k: self.redis.get(k) for k in keys}
# Usage
researcher_memory = NamespacedMemory('proj_123', 'researcher', redis_client)
researcher_memory.write_finding('competitors', 'OpenAI, Anthropic, Google...')
writer_memory = NamespacedMemory('proj_123', 'writer', redis_client)
all_findings = writer_memory.read_all_findings('proj_123')Memória estruturada versus não estruturada
O conteúdo da memória compartilhada pode ser não estruturado (blocos de texto bruto que o LLM lerá) ou estruturado (objetos JSON/Python com campos tipados). A memória estruturada é preferível porque permite consultas programáticas, validação e mesclagem. Sempre defina um esquema para o que cada agente escreve na memória compartilhada, documente-o e valide as escritas conforme esse esquema para impedir que um agente com defeito corrompa o armazenamento de memória.
from pydantic import BaseModel
from typing import Optional, list
from datetime import datetime
class ResearchFinding(BaseModel):
topic: str
summary: str
sources: list[str]
confidence: float # 0.0 to 1.0
written_by: str
timestamp: datetime
# Validated write - bad data is caught before it enters shared memory
def write_finding(memory, finding_dict: dict):
finding = ResearchFinding(**finding_dict) # validates on creation
memory.set(f'findings:{finding.topic}', finding.model_dump())
print(f'Validated finding written for topic: {finding.topic}')Comunicação orientada a eventos com Pub/Sub
Em vez de consultar repetidamente a memória compartilhada para verificar atualizações, os agentes podem usar a comunicação de publicação/assinatura (pub/sub) para notificar outros agentes quando concluem uma tarefa. O Agente A publica um evento (“research_complete”) e o Agente B, que está inscrito nesse evento, é ativado e começa a processar. O pub/sub do Redis e filas de mensagens como RabbitMQ ou Kafka oferecem suporte a esse padrão.
import redis
# Publisher (researcher agent)
def researcher_agent(topic, redis_client):
findings = do_research(topic)
redis_client.set(f'findings:{topic}', findings)
# Notify all subscribers that research is done
redis_client.publish('agent_events', f'research_complete:{topic}')
print(f'Research complete, published event for topic: {topic}')
# Subscriber (writer agent) - runs in separate process
def writer_agent_listener(redis_client):
pubsub = redis_client.pubsub()
pubsub.subscribe('agent_events')
for message in pubsub.listen():
if message['type'] == 'message':
event = message['data']
if event.startswith('research_complete:'):
topic = event.split(':')[1]
findings = redis_client.get(f'findings:{topic}')
write_draft(findings) # start writing immediatelyMemória compartilhada no LangGraph
Em LangGraph, a memória compartilhada entre agentes é o próprio objeto de estado do grafo. Cada nó lê e grava no mesmo dicionário de estado tipado. LangGraph gerencia automaticamente a coordenação de leitura e gravação. Em cenários mais complexos, também é possível injetar um cliente de memória externo (Redis, banco de dados) em cada função de nó por meio de injeção de dependências.
from langgraph.graph import StateGraph
from typing import TypedDict
class SharedState(TypedDict):
# All shared data lives here - every node can read any field
query: str
research_findings: str # written by researcher, read by writer
written_draft: str # written by writer, read by reviewer
review_notes: str # written by reviewer, read by writer (loop)
final_output: str # written by synthesizer
# Researcher writes to 'research_findings'
def researcher(state: SharedState) -> dict:
findings = search_and_summarize(state['query'])
return {'research_findings': findings} # partial state update
# Writer reads 'research_findings', writes 'written_draft'
def writer(state: SharedState) -> dict:
draft = write_from_findings(state['research_findings']) # reads researcher output
return {'written_draft': draft}Conflitos e consistência da memória
Quando vários agentes gravam na memória compartilhada simultaneamente, podem ocorrer conflitos de gravação. Dois agentes podem sobrescrever o trabalho um do outro ou ler dados desatualizados entre uma leitura e uma gravação. Para lidar com isso, use: bloqueio otimista (verifique a versão antes de gravar), operações atômicas de comparação e troca no Redis ou serialize as gravações por meio de um agente orquestrador que seja o único responsável por gravar nos campos críticos da memória.
# Optimistic locking with Redis
def safe_write(redis_client, key, new_value, expected_version):
with redis_client.pipeline() as pipe:
try:
pipe.watch(key + ':version') # watch for concurrent modification
current_version = int(pipe.get(key + ':version') or 0)
if current_version != expected_version:
raise ValueError(f'Version conflict: expected {expected_version}, got {current_version}')
pipe.multi() # start transaction
pipe.set(key, new_value)
pipe.set(key + ':version', current_version + 1)
pipe.execute() # atomic commit
print('Write successful')
except redis.WatchError:
print('Conflict detected, retry write')TTL e limpeza da memória
A memória compartilhada dos agentes se acumula com o tempo e pode crescer sem limites se não for gerenciada. Sempre defina o tempo de vida (TTL) das entradas de memória para que elas expirem automaticamente. Para memória associada a um projeto, limpe todas as entradas quando o projeto for concluído. Use valores de TTL compatíveis com a duração esperada de um fluxo de trabalho: TTLs curtos (minutos) para dados transitórios e TTLs mais longos (horas a dias) para resultados que possam ser reutilizados.
def cleanup_project_memory(redis_client, project_id: str):
pattern = f'{project_id}:*'
keys = redis_client.keys(pattern)
if keys:
redis_client.delete(*keys)
print(f'Cleaned up {len(keys)} memory entries for project {project_id}')
# Set TTL when writing
def write_with_ttl(redis_client, key, value, ttl_hours=2):
redis_client.setex(
key,
ttl_hours * 3600, # convert to seconds
json.dumps(value)
)
# Register cleanup callback when workflow completes
def on_workflow_complete(project_id):
cleanup_project_memory(redis_client, project_id)
print(f'Workflow {project_id} complete, memory cleaned up')Memória como histórico do agente
A memória compartilhada também pode armazenar o histórico das ações dos agentes, e não apenas suas saídas. Registrar qual agente fez o quê, quando e por quê cria uma trilha de auditoria extremamente valiosa para depurar falhas, entender como uma saída final foi produzida e retomar fluxos de trabalho interrompidos. Esse registro de ações é o equivalente baseado em memória do rastreamento do LangSmith.
import time
from dataclasses import dataclass
@dataclass
class AgentAction:
agent_id: str
action_type: str # 'research', 'write', 'review', 'tool_call'
input_summary: str
output_summary: str
timestamp: float
success: bool
def log_action(memory, action: AgentAction):
key = f'action_log:{action.agent_id}:{action.timestamp}'
memory.set(key, vars(action))
# Usage in an agent
def researcher_with_logging(state, memory):
start = time.time()
findings = do_research(state['query'])
log_action(memory, AgentAction(
agent_id='researcher',
action_type='research',
input_summary=state['query'][:100],
output_summary=findings[:100],
timestamp=start,
success=True
))
return findingsEscolhendo uma arquitetura de memória
A arquitetura de memória compartilhada adequada depende do seu modelo de implantação. Para fluxos de trabalho do LangGraph em um único processo, o estado do grafo é suficiente. Para agentes em vários processos ou distribuídos, use Redis. Para projetos de longa duração que precisam manter os dados após reinicializações, use um banco de dados relacional com indexação adequada. Para coordenação orientada a eventos entre serviços, adicione publicação/assinatura sobre o armazenamento escolhido.
Verificação rápida
Verifique sua compreensão sobre memória compartilhada e comunicação entre agentes nesta lição.
Recapitulação da lição
Nesta lição, você aprendeu que o modelo de quadro-negro usa um armazenamento de dados compartilhado no qual qualquer agente pode ler e gravar, permitindo a coordenação implícita sem acoplamento direto entre agentes; que o Redis é a opção preferencial para memória compartilhada persistente em sistemas distribuídos com vários agentes; e que a publicação/assinatura permite comunicação orientada a eventos, fazendo com que os agentes reajam imediatamente quando as dependências são concluídas. A seguir, exploraremos o ciclo de execução de código para tarefas de agentes.
Perguntas Frequentes
A aula “Memória compartilhada e comunicação entre agentes” é grátis?
Sim — o texto completo de “Memória compartilhada e comunicação entre agentes” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Engineering Academy, atualize para CoddyKit PRO. O curso de AI Engineering Academy inclui 4 aulas no total.
O que vou aprender em “Memória compartilhada e comunicação entre agentes”?
Implemente uma camada de memória compartilhada usando um armazenamento de chave-valor do qual os agentes leiam e no qual escrevam, permitindo colaboração assíncrona sem acoplamento rígido entre eles. Você pratica AI Engineering Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Engineering Academy?
Nenhuma experiência prévia é necessária. AI Engineering Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Memória compartilhada e comunicação entre agentes”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Engineering Academy?
Sim. Cada aula de AI Engineering Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que agentes únicos chegam a um limite
- Padrão orquestrador-subagente
- Criando pipelines multiagentes com LangGraph
- Memória compartilhada e comunicação entre agentes