Skip to content

✅ Passo 2: MemoryService Implementado

🎯 Objetivo

Permitir que o Agent acesse informações de conversas passadas (cross-session), não apenas da conversa atual.

📚 Conceito

Session vs Memory

Aspecto Session Memory
Escopo UMA conversa MUITAS conversas
Duração Enquanto conversa ativa Indefinido (histórico)
Armazenamento session.events MemoryService
Acesso Automático (Runner passa) Tool (Agent solicita)
Exemplo "O que você respondeu antes?" "Lembra quando você me ajudou semana passada?"

🔧 Implementação

1. FirestoreMemoryService (session/memory_service.py)

class FirestoreMemoryService(BaseMemoryService):
    async def add_session_to_memory(session: Session) -> None:
        """Salva conhecimento extraído de uma sessão ao histórico"""
        # Extrai conteúdo relevante dos eventos
        # Armazena no Firestore com user_id + timestamp

    async def search_memory(app_name, user_id, query) -> SearchMemoryResponse:
        """Busca informações relevantes no histórico"""
        # Busca por palavras-chave nos documentos de memória do usuário
        # Retorna resultados relevantes

2. Integração com Slack Bot (slack_bot.py)

# Configuração
memory_service = FirestoreMemoryService(collection_name="...")
runner = Runner(
    agent=root_agent,
    app_name="...",
    session_service=session_service,
    memory_service=memory_service  # ← Passo 2
)

# Após cada conversa, salvar memória
completed_session = await session_service.get_session(...)
await memory_service.add_session_to_memory(completed_session)

3. Agent com PreloadMemoryTool (agent.py)

from google.adk.tools import PreloadMemoryTool

root_agent = LlmAgent(
    name='root_agent',
    instruction="...",
    tools=[
        PreloadMemoryTool(),  # ← Agent pode acessar histórico
        busca_produtos_tool,
        ...
    ]
)

🔄 Fluxo Completo (2 Passos + Memory)

═══════════════════════════════════════════════════════════════

REQUEST 1 (primeira conversa com usuário)
────────────────────────────────────────────────────────────
1️⃣  Usuário: "Quais produtos vocês têm?"

2️⃣  slack_bot.py:
    - Cria session_id = "user123_slack_channel456"
    - runner.run_async(user_id, session_id, mensagem)

3️⃣  Runner:
    - Chama: session_service.get_session()
    - Retorna: Session(events=[]) ← Primeira vez
    - Passa ao Agent

4️⃣  Agent:
    - Pode chamar PreloadMemoryTool() ← Busca histórico
    - Resultado: Nenhuma memória anterior (primeira conversa)
    - Responde: "Temos produtos X, Y, Z"

5️⃣  Runner:
    - Chama: session_service.append_event(session, evento_user)
    - Chama: session_service.append_event(session, evento_agent)
    - Eventos salvos no Firestore ✅

6️⃣  slack_bot.py finaliza:
    - Recupera session completa com events
    - Chama: memory_service.add_session_to_memory(session)
    - Memória extraída e salva! ✅

════════════════════════════════════════════════════════════

REQUEST 2 (dias depois, mesmo usuário, novo canal)
────────────────────────────────────────────────────────────
1️⃣  Usuário: "Você consegue lembrar o que você falou antes?"

2️⃣  slack_bot.py:
    - Nova session_id = "user123_slack_channel789"
    - runner.run_async(user_id, session_id, mensagem)

3️⃣  Runner:
    - Chama: session_service.get_session()
    - Retorna: Session(events=[]) ← Nova sessão (vazia)
    - Passa ao Agent

4️⃣  Agent ✨:
    - Vê que não tem eventos nesta sessão
    - Chama: PreloadMemoryTool("produtos que ofereço")
    - MemoryService busca no histórico
    - Encontra: "Temos produtos X, Y, Z"
    - Responde: "Claro! Você perguntou sobre produtos X, Y, Z no nosso último papo."

5️⃣  Runner:
    - Chama: session_service.append_event(session, evento_user)
    - Chama: session_service.append_event(session, evento_agent)
    - Novos eventos salvos ✅

6️⃣  slack_bot.py finaliza:
    - Chama: memory_service.add_session_to_memory(session)
    - Nova memória adicionada ao histórico ✅

════════════════════════════════════════════════════════════

🧠 Dados no Firestore

Collection: agente_busca_produtos_sessions

{
  "user123_slack_channel456": {
    "id": "user123_slack_channel456",
    "user_id": "user123",
    "app_name": "ifriend_busca_produtos_slack",
    "messages": [
      {
        "role": "user",
        "parts": [{"text": "Quais produtos?"}],
        "timestamp": "2025-11-17T10:00:00Z"
      },
      {
        "role": "assistant",
        "parts": [{"text": "Temos produtos X, Y, Z"}],
        "timestamp": "2025-11-17T10:00:05Z"
      }
    ]
  }
}

Collection: agente_busca_produtos_memory

{
  "user123_1731834000000": {
    "app_name": "ifriend_busca_produtos_slack",
    "user_id": "user123",
    "session_id": "user123_slack_channel456",
    "created_at": "2025-11-17T10:00:10Z",
    "content": "P: Quais produtos vocês têm?\n\nTemos produtos X, Y, Z",
    "event_count": 2
  }
}

🎯 O que o Agent pode fazer agora

Cenário 1: Contexto na mesma sessão

User: "Qual é o preço?"
Agent: [busca_produtos_tool] → tem info → responde com preço ✅

User: "Você já calculou isso antes?"
Agent: Vê session.events → "Sim, foi R$ 100"  ✅

Cenário 2: Contexto em sessão futura

User: "O que você me recomendou antes?"
Agent: [PreloadMemoryTool("minhas recomendações")]
       → Busca em agente_busca_produtos_memory
       → Encontra: "Recomendei produtos X, Y, Z"
       → Responde ✅

Cenário 3: Personalizacão

User: "Gera um relatório de tudo que conversei com você"
Agent: [PreloadMemoryTool("todo histórico")]
       → Busca todas as memórias do usuário
       → Consolida informações
       → Gera relatório personalizado ✅

📊 Fluxo de Dados

Slack Message
      ↓
slack_bot.py (rate limiting + concurrency)
      ↓
runner.run_async()
      ├→ session_service.get_session()
      │   └→ Carrega session.events do Firestore (Passo 1)
      │
      ├→ root_agent.run()
      │   ├→ PreloadMemoryTool()
      │   │   └→ memory_service.search_memory()
      │   │       └→ Busca em histórico cross-session
      │   │
      │   └→ Outras tools (busca_produtos_tool, etc)
      │
      ├→ session_service.append_event() [x2]
      │   └→ Salva interações no Firestore
      │
      └→ memory_service.add_session_to_memory()
          └→ Extrai e armazena conhecimento
                 ↓
         Resposta final ao Slack ✅

✨ Benefícios

Antes Depois
❌ Agent esquecia tudo entre mensagens ✅ Agent lembra tudo na mesma sessão (Passo 1)
❌ Nenhuma memória de conversas passadas ✅ Agent tem acesso a histórico indefinido (Passo 2)
❌ Não personalizava ✅ Respostas personalizadas baseadas em histórico
❌ Cada conversa era isolada ✅ Continuidade e contexto cross-session

🧪 Testes

Teste a integração completa:

Teste 1: Mesma sessão

# Request 1
curl -X POST http://localhost:8000/slack/events \
  -H "Content-Type: application/json" \
  -d '{"user_id":"user123","text":"Produtos de viagem"}'

# Request 2 (MESMA SESSION)
curl -X POST http://localhost:8000/slack/events \
  -H "Content-Type: application/json" \
  -d '{"user_id":"user123","text":"Qual era o nome do primeiro produto que você listou?"}'

# Agent deveria responder com o nome do produto ✅

Teste 2: Diferentes sessões

# Request 1 - Sessão A
curl -X POST .../events -d '{"user_id":"user123","channel":"ch1","text":"Produtos de viagem"}'

# Aguarde alguns segundos (simula usuário voltando depois)

# Request 2 - Sessão B (diferente channel)
curl -X POST .../events -d '{"user_id":"user123","channel":"ch2","text":"Lembra do que falamos antes?"}'

# Agent deveria usar PreloadMemoryTool e responder ✅

🚀 Próximos Passos

  1. Teste em produção com dados reais
  2. Monitorar Firestore - verificar quantidade de documentos
  3. Otimizar busca - implementar busca semântica com embeddings
  4. Cleanup automático - remover memórias antigas (>6 meses)
  5. Analytics - rastrear hits de memória vs misses