π Resumo Executivo: SoluΓ§Γ£o de Contexto Persistente¶
β Problema Resolvido¶
Antes:
Usuario1: "Qual Γ© o preΓ§o do produto X?"
Agent: "Custa R$ 100"
---
Usuario1: "O que vocΓͺ respondeu antes?"
Agent: "NΓ£o tenho histΓ³rico π" β
Depois:
Usuario1: "Qual Γ© o preΓ§o do produto X?"
Agent: "Custa R$ 100"
---
Usuario1: "O que vocΓͺ respondeu antes?"
Agent: "VocΓͺ perguntou sobre o preΓ§o, que Γ© R$ 100" β
ποΈ Arquitetura Implementada¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SLACK_BOT.PY β
β - Rate Limiting: 2 simultΓ’neas, 3/min por usuΓ‘rio β
β - ConcorrΓͺncia: AsyncApp com locks β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ADK RUNNER (google.adk.runners.Runner) β
β - Orquestra Session + Memory Services β
β - Gerencia ciclo de vida de conversas β
βββββββ¬ββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββ
β β
β β
ββββββββββββββββββββ ββββββββββββββββββββββ
βSESSION SERVICE β β MEMORY SERVICE β
β(Firestore) β β (Firestore) β
ββββββββββββββββββββ€ ββββββββββββββββββββββ€
ββ
Passo 1: β ββ
Passo 2: β
β get_session() β β add_session_to_ β
β + session.events β β memory() β
β β β β
β append_event() β β search_memory() β
β = salva eventos β β = busca histΓ³rico β
ββββββββββββββββββββ ββββββββββββββββββββββ
β β
ββββββββββββ¬βββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β FIRESTORE (Google Cloud) β
β β
β collections: β
β ββ agente_busca_produtos_sessions β
β β ββ session_id β {events: [...], messages: [...]} β
β β β
β ββ agente_busca_produtos_memory β
β ββ user_id_timestamp β {content, events_count} β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ROOT_AGENT (LlmAgent) β
β - Tools: β
β β
PreloadMemoryTool() β NOVO (Passo 2) β
β β
busca_produtos_tool β
β β
tem_variacao_tool β
β β
... (outras tools) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π― Dois Passos Implementados¶
Passo 1: Session.events (Contexto na Mesma SessΓ£o)¶
Arquivo: session/session_service.py
Problema: Agent perdia contexto a cada mensagem
SoluΓ§Γ£o: Carregar eventos do Firestore em session.events
async def get_session(app_name, user_id, session_id):
# Carrega messages do Firestore
events = []
for msg in stored_messages:
event = Event(author=msg.role, role=msg.role, content=...)
events.append(event)
# Retorna Session COM eventos
return Session(id=session_id, events=events) # β KEY!
async def append_event(session, event):
# Runner chama isto apΓ³s cada resposta
# Salva interaΓ§Γ£o no Firestore para prΓ³xima get_session()
messages.append(convert_event_to_message(event))
firestore.update(messages)
Resultado:
Request 1: session.events = []
Request 2: session.events = [evento1, evento2] β Agent VΓ HISTΓRICO
Request 3: session.events = [evento1, evento2, evento3, evento4]
Passo 2: MemoryService (Contexto Cross-Session)¶
Arquivo: session/memory_service.py
Problema: Agent nΓ£o sabia de conversas passadas SoluΓ§Γ£o: Armazenar memΓ³ria de longo prazo e permitir busca
async def add_session_to_memory(session):
# Chamado apΓ³s conversa terminar
memory_content = extract_knowledge(session) # "Temos produtos X, Y, Z"
firestore.save(user_id, memory_content)
async def search_memory(app_name, user_id, query):
# Agent chama PreloadMemoryTool("vocΓͺ jΓ‘ recomendou algo?")
results = firestore.search_by_keyword(user_id, query)
return results # "Sim, recomendei produtos X, Y, Z"
IntegraΓ§Γ£o:
# slack_bot.py
runner = Runner(
agent=root_agent,
session_service=session_service,
memory_service=memory_service # β Passo 2
)
# ApΓ³s conversa
await memory_service.add_session_to_memory(completed_session)
# agent.py
root_agent = LlmAgent(
tools=[
PreloadMemoryTool(), # β Agent pode buscar histΓ³rico
busca_produtos_tool,
...
]
)
Resultado:
SesiΓ³n A (semana passada): User fala sobre viagem
β Salvo em MemoryService β
SessΓ£o B (hoje, novo canal): User "Lembra de mim?"
β Agent usa PreloadMemoryTool()
β "Claro! VocΓͺ tinha interesse em viagem!" β
π Dados no Firestore¶
Collection: agente_busca_produtos_sessions¶
{
"user123_slack_channel456": {
"id": "user123_slack_channel456",
"user_id": "user123",
"messages": [
{"role": "user", "parts": [{"text": "Qual produto?"}], ...},
{"role": "assistant", "parts": [{"text": "Temos X, Y, Z"}], ...}
]
}
}
Collection: agente_busca_produtos_memory¶
{
"user123_1731834000000": {
"user_id": "user123",
"session_id": "user123_slack_channel456",
"content": "P: Qual produto?\n\nTemos X, Y, Z",
"event_count": 2
}
}
π§ͺ Como Testar¶
# 1. Execute a validaΓ§Γ£o completa
cd /Users/glauberportella/Projects/ifriend/ifriend-agents/busca_produtos
python validate.py
# 2. SaΓda esperada
β
Passo 1 (session.events): β
PASSOU
β
Passo 2 (MemoryService): β
PASSOU
β
IntegraΓ§Γ£o Completa: β
PASSOU
π TODAS AS VALIDAΓΓES PASSARAM!
π DocumentaΓ§Γ£o¶
PASSO_1_SESSION_EVENTS.md- Detalhe tΓ©cnico do histΓ³rico de mesma sessΓ£oPASSO_2_MEMORY_SERVICE.md- Detalhe tΓ©cnico do histΓ³rico cross-sessionvalidate.py- Script de validaΓ§Γ£o automΓ‘tica
π Deploy Checklist¶
- β CΓ³digo compilado (sem erros de imports)
- β Firestore collections criadas
- β SessionService persistindo eventos
- β MemoryService funcionando
- β PreloadMemoryTool integrada ao agent
- β Testes de validaΓ§Γ£o passando
PrΓ³ximo: Deploy em Cloud Run
π BenefΓcios Finais¶
| MΓ©trica | Antes | Depois |
|---|---|---|
| Contexto na mesma sessΓ£o | β Nenhum | β 100% |
| Contexto cross-session | β Nenhum | β DisponΓvel |
| PersonalizaΓ§Γ£o do Agent | β BΓ‘sica | β AvanΓ§ada |
| ExperiΓͺncia do UsuΓ‘rio | ββ | βββββ |
π‘ PrΓ³ximos Melhoramentos¶
- Busca SemΓ’ntica - Usar embeddings para busca inteligente
- Limpeza AutomΓ‘tica - Remover memΓ³ria antiga (>6 meses)
- Analytics - Dashboard de hits/misses de memΓ³ria
- ExportaΓ§Γ£o - Permitir usuΓ‘rio baixar histΓ³rico
- Privacidade - EncriptaΓ§Γ£o de dados sensΓveis em memΓ³ria
π Suporte¶
DΓΊvidas sobre a arquitetura?
- Revisar PASSO_1_SESSION_EVENTS.md para detalhes de session.events
- Revisar PASSO_2_MEMORY_SERVICE.md para detalhes de MemoryService
- Executar validate.py para confirmar funcionamento