Skip to content

🎯 Resumo: Implementação Completa de Persistência de Contexto

📋 Status: ✅ COMPLETADO

Data: 17 de novembro de 2025


🎯 Objetivo Final

Resolver o problema: "Agent perde contexto entre mensagens"

Resultado: ✅ RESOLVIDO

O Agent agora mantém: - ✅ Contexto na mesma sessão - Lembra todas as mensagens da conversa atual - ✅ Contexto entre diferentes sessões - Armazena histórico em Firestore - ✅ Rate limiting - Evita sobrecarga (2 simultâneas, 3/min por usuário) - ✅ Error handling - Trata erros 503/429 do Gemini


🏗️ Arquitetura Implementada

┌─────────────────────────────────────────────────────────────┐
│ Layer 1: Rate Limiting & Concurrency Control               │
│ - 2 requisições simultâneas globalmente                    │
│ - 3 requisições por usuário/minuto                         │
│ - Semáforo global + Lock por usuário                       │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│ Layer 2: ADK Runner com SessionService + MemoryService     │
│ - Runner gerencia ciclo de vida da conversa                │
│ - SessionService persiste no Firestore                     │
│ - MemoryService armazena histórico                         │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│ Layer 3: Root Agent (LlmAgent)                             │
│ - Acesso a ferramentas para busca de produtos              │
│ - Acesso a histórico via SessionService                    │
│ - Acesso a memória de longo prazo via MemoryService        │
└─────────────────────────────────────────────────────────────┘
                          ↓
┌─────────────────────────────────────────────────────────────┐
│ Layer 4: Tools Especializadas                              │
│ - busca_produtos_tool                                       │
│ - tem_variacao_tool                                         │
│ - listar_variacoes_tool                                     │
│ - detalhes_experience                                       │
│ - disponibilidade_calendario_tool                           │
│ - disponibilidade_horarios_tool                             │
│ - calcular_preco_tool                                       │
│ - gerar_csv_tool                                            │
└─────────────────────────────────────────────────────────────┘

📦 Componentes Implementados

1. FirestoreSessionService (session/session_service.py)

Gerencia o ciclo de vida da sessão:

class FirestoreSessionService(BaseSessionService):
    # Métodos principais:

    async def create_session(...)
    # Cria nova sessão no Firestore
    # Inicializa com messages=[]

    async def get_session(...)
    # Recupera sessão existente
    # Se não existe, cria automaticamente
    # Carrega histórico do Firestore

    async def update_session(...)
    # Atualiza com nova mensagem
    # Mantém histórico completo

    async def append_event(...)
    # Adiciona evento/interação à sessão
    # Chamado automaticamente pelo Runner

    async def delete_session(...)
    # Cleanup de sessão expirada

    async def list_sessions(...)
    # Lista todas as sessões ativas do usuário

    async def cleanup_expired_sessions(...)
    # Remove sessões antigas (>TTL)

Armazenamento Firestore:

Collection: agente_busca_produtos_sessions
Document: {session_id}
  - id: string
  - user_id: string
  - app_name: string
  - created_at: timestamp
  - updated_at: timestamp
  - expires_at: timestamp
  - messages: [
      {role, parts, timestamp},
      {role, parts, timestamp},
      ...
    ]

2. FirestoreMemoryService (session/memory_service.py)

Gerencia conhecimento de longo prazo:

class FirestoreMemoryService(BaseMemoryService):
    # Métodos principais:

    async def add_session_to_memory(session: Session)
    # Extrai conhecimento da sessão completa
    # Armazena para futuras referências
    # Chamado ao final de cada conversa

    async def search_memory(app_name, user_id, query)
    # Busca informações relevantes no histórico
    # Busca por palavras-chave
    # Retorna resultados relevantes

    async def delete_memory(app_name, user_id)
    # Remove toda a memória de um usuário
    # Cleanup completo

Armazenamento Firestore:

Collection: agente_busca_produtos_memory
Document: {user_id}_{timestamp}
  - app_name: string
  - user_id: string
  - session_id: string
  - created_at: timestamp
  - content: string (extracted knowledge)
  - event_count: number

3. Slack Bot Integration (slack_bot.py)

Integrações principais:

# Configuração
session_service = FirestoreSessionService(...)
memory_service = FirestoreMemoryService(...)
runner = Runner(
    agent=root_agent,
    session_service=session_service,
    memory_service=memory_service
)

# Handler de mensagens
@app.message(".*")
async def handle_message(message, say, context, ack, client):
    # 1. Rate limiting check
    # 2. Criar session_id único
    # 3. Enviar feedback em tempo real
    # 4. Executar Agent com runner.run_async()
    # 5. Tratar erros 503/429
    # 6. Salvar memória após conversa
    # 7. Responder no Slack

4. Root Agent (agent.py)

Agent inteligente com acesso completo:

root_agent = LlmAgent(
    name='root_agent',
    model=llm_with_retry,  # Com retry automático
    instruction="...",      # Instruções detalhadas
    tools=[
        busca_produtos_tool,
        tem_variacao_tool,
        listar_variacoes_tool,
        detalhes_experience,
        disponibilidade_calendario_tool,
        disponibilidade_horarios_tool,
        calcular_preco_tool,
        gerar_csv_tool
    ]
)

🔄 Fluxo de Funcionamento

Primeira Interação

1. Slack: Usuário envia mensagem
           ↓
2. slack_bot.py: 
   - Rate limit check ✅
   - Cria session_id = "user123_slack_channel456"
           ↓
3. runner.run_async():
   - Chama session_service.get_session()
   - Retorna Session (primeira vez = vazia)
           ↓
4. root_agent:
   - Processa mensagem
   - Chama ferramentas conforme necessário
           ↓
5. runner:
   - Chama session_service.append_event() [x2]
   - Salva interações no Firestore
           ↓
6. slack_bot.py:
   - Recupera session completa
   - Chama memory_service.add_session_to_memory()
   - Responde no Slack

Interação Subsequente (mesma sessão)

1. Slack: Usuário envia nova mensagem
           ↓
2. runner.run_async():
   - Chama session_service.get_session()
   - Retorna Session COM HISTÓRICO CARREGADO ✅
           ↓
3. root_agent:
   - VÊ mensagens anteriores
   - Mantém continuidade da conversa
   - Respostas contextualizadas
           ↓
... (resto do fluxo igual)

Interação em Sessão Futura (usuário novo)

1. Slack: Usuário pergunta "Você lembra do que falamos antes?"
           ↓
2. runner.run_async():
   - Cria nova Session (diferente channel/dia)
   - Session vazia (primeira da nova sessão)
           ↓
3. root_agent:
   - Pode chamar memory_service.search_memory()
   - Busca no histórico armazenado
   - Encontra contexto de conversas passadas
   - Responde com informações do passado ✅
           ↓
... (resto do fluxo igual)

📊 Dados Persistidos

Firestore - Collection 1: Sessions

agente_busca_produtos_sessions/user123_slack_channel456:
{
  "id": "user123_slack_channel456",
  "user_id": "user123",
  "app_name": "ifriend_busca_produtos_slack",
  "created_at": "2025-11-17T10:00:00Z",
  "updated_at": "2025-11-17T10:05:30Z",
  "expires_at": "2025-11-17T11:00:00Z",
  "messages": [
    {
      "role": "user",
      "parts": [{"text": "Quais produtos vocês têm de viagem?"}],
      "timestamp": "2025-11-17T10:00:05Z"
    },
    {
      "role": "assistant",
      "parts": [{"text": "Encontrei 5 produtos de viagem..."}],
      "timestamp": "2025-11-17T10:00:15Z"
    },
    {
      "role": "user",
      "parts": [{"text": "Qual é o preço do primeiro?"}],
      "timestamp": "2025-11-17T10:00:20Z"
    },
    {
      "role": "assistant",
      "parts": [{"text": "O primeiro produto custa R$ 299..."}],
      "timestamp": "2025-11-17T10:00:30Z"
    }
  ]
}

Firestore - Collection 2: Memory

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:05:35Z",
  "content": "P: Quais produtos vocês têm de viagem?\n\nEncontrei 5 produtos de viagem...\n\nP: Qual é o preço do primeiro?\n\nO primeiro produto custa R$ 299...",
  "event_count": 4
}

🧪 Testes Inclusos

Test Files

  • tests/test_session_service.py - Testes de persistência
  • test_session_events_loaded_on_get() - Valida carregamento de eventos
  • test_append_event_saves_to_firestore() - Valida salvamento de eventos

Execute com:

cd busca_produtos
python -m pytest tests/test_session_service.py -v


🚀 Deployment

Cloud Run - Deploy

cd busca_produtos
./deploy-test.sh

Configurações automáticas: - ✅ Vertex AI habilitado (GOOGLE_GENAI_USE_VERTEXAI=1) - ✅ Rate limiting configurado - ✅ Firestore inicializado - ✅ Slack bot conectado

Verificação

curl https://agente-busca-produtos-slack-REGION.run.app/health

Esperado:

{
  "status": "healthy",
  "service": "ifriend_busca_produtos_slack",
  "slack_configured": true
}


📈 Métricas & Monitoramento

Logs (Cloud Logging)

✅ "ADK Runner inicializado com FirestoreSessionService + FirestoreMemoryService"
📝 "Sessão criada: user123_slack_channel456"
🧠 "Memória salva para user123 (4 eventos)"
✅ "Enviando resposta ao Slack"

Firestore Metrics

  • Sessions Collection: Crescimento linear com conversas
  • Memory Collection: Crescimento linear com conversas completadas
  • TTL: Sessions expiram em 60 minutos

🎯 Casos de Uso Habilitados

1. Contexto na Mesma Conversa ✅

User: "Qual é o preço?"
Agent: [busca no Firestore] "R$ 299"

User: "Você já calculou isso?"
Agent: [vê session.messages] "Sim, foi R$ 299" ✅

2. Personalizacão Entre Conversas ✅

Sessão 1 (Dia 1):
  User: "Gosto de viagem"
  Agent: Recomenda produtos de viagem

Sessão 2 (Dia 7):
  User: "Me recomende algo"
  Agent: [busca em memory_service] "Lembro que você gosta de viagem..."

3. Escalabilidade ✅

- Múltiplos usuários simultâneos
- Rate limiting previne sobrecarga
- Firestore escala automaticamente
- Sessions TTL evita crescimento infinito

📚 Documentação Associada

  1. PASSO_1_SESSION_EVENTS.md - Detalhes de persistência de sessão
  2. PASSO_2_MEMORY_SERVICE.md - Detalhes de memória de longo prazo
  3. FIREBASE_CONTEXT_SOLUTIONS.md - Soluções anteriores (referência)

🔍 Diagrama de Sequência

Slack          Bot         Runner        SessionService    MemoryService    Firestore
  |              |            |                |                |              |
  |--msg-------->|            |                |                |              |
  |              |--check---->|                |                |              |
  |              | rate limit |                |                |              |
  |              |<--ok-------|                |                |              |
  |              |            |--get_session()--->               |              |
  |              |            |                |--load from DB---------->      |
  |              |            |                |<--return session-------|      |
  |              |            |                |                |              |
  |              |            |--run_agent()---|                |              |
  |              |            |   [tool calls] |                |              |
  |              |            |                |                |              |
  |              |            |--append_event()|                |              |
  |              |            |                |--save to DB---------->       |
  |              |            |<--done---------|                |              |
  |              |            |                |                |              |
  |              |--add_to_memory()------------|                |              |
  |              |                             |--save knowledge----------->  |
  |              |                             |                |              |
  |<--response---|                             |                |              |
  |              |                             |                |              |

✅ Checklist Final

  • ✅ FirestoreSessionService implementado
  • ✅ FirestoreMemoryService implementado
  • ✅ Rate limiting funcional
  • ✅ Error handling (503/429)
  • ✅ Vertex AI integrado
  • ✅ Slack bot conectado
  • ✅ Firestore persistência
  • ✅ Testes inclusos
  • ✅ Documentação completa
  • ✅ Deploy automático

🎉 Resultado

O Agent agora: - Mantém contexto na mesma conversa ✅ - Lembra de conversas passadas ✅ - Responde a "Você lembra?" com histórico ✅ - Não fica sobrecarregado com rate limiting ✅ - Trata erros elegantemente ✅ - Escala bem com crescimento ✅

Status: PRONTO PARA PRODUÇÃO 🚀