π― Diagrama Visual: SoluΓ§Γ£o de Contexto Persistente
π Arquitetura Completa
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SLACK USER β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
"Qual Γ© o preΓ§o?"
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SLACK_BOT.PY β
β Rate Limiting: 2 simultΓ’neas, 3/min por user β
β ConcorrΓͺncia: AsyncApp + asyncio locks β
ββββββββββββββ¬βββββββββββββββββββββββββββββββββββ¬βββββββββββββββββ
β β
β check_user_rate_limit() β
β β
βΌ βΌ
βββββββββββββββββββ ββββββββββββββββββββ
β PASS: 1/3 β
β β FAIL: >= 3 β β
β Proceed β β Reject with msg β
ββββββββββ¬βββββββββ ββββββββββββββββββββ
β
β runner.run_async(user_id, session_id, msg)
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ADK RUNNER (google.adk.runners.Runner) β
β Orquestra Session + Memory Services β
ββββββββββββββ¬βββββββββββββββββββββββββββββββββ¬βββββββββββββββββββ
β β
Etapa 1β session_service.get_session() β Etapa 3
β β memory_service
βΌ β .add_session_...
ββββββββββββββββββββββββ β
β SESSION SERVICE β β
β (Firestore) β β
ββββββββββββββββββββββββ€ β
β π PASSO 1 β β
β β β
β Recupera session_id β β
β β β β
β Carrega messages do β β
β Firestore β β
β β β β
β Converte para Event β β
β objects β β
β β β β
β Popula session.eventsβ β
β β β β
β Return Session β
β β
β with events β β
βββββββββββ¬βββββββββββββ β
β β
β Session(events=[...]) β
β β
βΌ β
ββββββββββββββββββββββββ β
β ROOT_AGENT β β
β (LlmAgent) β β
ββββββββββββββββββββββββ€ β
β Instruction: "Buscar β β
β produtos..." β β
β β β
β Tools: β β
β β’ PreloadMemoryTool βββββββββ β
β β’ busca_produtos β β β
β β’ calcular_preco β β β
β β’ ... β β β
β β β β
β Agent vΓͺ: β β β
β β’ session.events = [ β β β Etapa 2
β "PreΓ§o?", β β β Agent
β "R$ 100" β β chama β pode
β ] β β buscar β buscar
β β’ user_id = "user123"β β histΓ³rico
β β β β
β Responde com contextoβ β β
β "VocΓͺ perguntou..." β β β
βββββββββββ¬βββββββββββββ β β
β β β
Evento (user + β β
agent response) β β
β β β
βΌ β β
ββββββββββββββββββββββββ β β
β append_event() β β β
β [x2 calls] β β β
β β β β
β EVENT 1: User msg β β β
β EVENT 2: Agent resp β β β
β β β β
β Salva no Firestore β β β
β session.messages β
β β β
ββββββββββββ¬ββββββββββββ β β
β β β
β β β
β Session( β β
β events=[...], β β
β messages: [ β β
β {msg1}, β β
β {msg2} β β
β ]) β β
β β β
ββββββββββββ¬βββββββββΌββββββββββ
β β
β β
βΌ βΌ
ββββββββββββββββββββββββββββββββββ
β MEMORY SERVICE β
β (Firestore) β
ββββββββββββββββββββββββββββββββββ€
β π PASSO 2 β
β β
β add_session_to_memory() β
β β β
β Extrai content relevante: β
β "P: Qual Γ© o preΓ§o?" β
β "R: R$ 100" β
β β β
β Salva em collection: β
β agente_busca_produtos_memory β
β β β
β user_id + timestamp = key β
β
β β
β search_memory() β
β β β
β Busca por keyword: β
β "preΓ§o" β encontra! β
β
ββββββββββββββ¬βββββββββββββββββββββ
β
β SearchMemoryResponse
β [resultado1, ...]
β
βΌ
ββββββββββββββββββββββββββββββββββ
β Agent Usa Resultado β
β β
β PreloadMemoryTool("preΓ§o") β
β β β
β "Ah sim, vocΓͺ perguntou sobre β
β preΓ§o antes e era R$ 100" β
β β
β PersonalizacΓ£o! β
β
ββββββββββββββββββββββββββββββββββ
π Fluxo Temporal: 2 Conversas Mesma Session
TEMPO βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ>
T0: UsuΓ‘rio comeΓ§a conversa
user123 em channel#produtos
session_id = "user123_slack_products"
β
ββ> runner.run_async(user_id, session_id, "Produtos de viagem?")
β
ββ> get_session() β Carrega eventos
β β Firestore: messages = []
β β session.events = []
β ββ> Retorna Session vazio (primeira vez)
β
ββ> Agent processa
β ββ> PreloadMemoryTool("viagem")
β β ββ> search_memory() β Busca histΓ³rico anterior
β β ββ> "Nenhum resultado" (primeira conversa)
β β
β ββ> busca_produtos_tool("viagem")
β ββ> "Temos Safari, Cruzeiro, Ski"
β
ββ> append_event(evento_user) β Salva pergunta
ββ> append_event(evento_agent) β Salva resposta
β β Firestore: messages = [{user_msg}, {agent_msg}]
β β
β ββ> add_session_to_memory() β Extrai conhecimento
β ββ> memory collection = [{content: "P:Viagem? R:Safari..."}]
β
ββ> Resposta ao Slack: "Temos Safari, Cruzeiro, Ski"
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
(segundos depois)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
T1: UsuΓ‘rio faz pergunta 2
user123 em channel#produtos
session_id = "user123_slack_products" (MESMA)
β
ββ> runner.run_async(user_id, session_id, "Qual Γ© mais barato?")
β
ββ> get_session() β Carrega eventos
β β Firestore: messages = [{user_msg1}, {agent_msg1}]
β β session.events = [Event(user_msg1), Event(agent_msg1)]
β ββ> Retorna Session COM histΓ³rico! β
β
ββ> Agent processa
β ββ> VΓͺ session.events = [pergunta1, resposta1]
β β ββ> Agent entende contexto! "Eles perguntaram sobre viagem"
β β
β ββ> PreloadMemoryTool("viagem barato")
β β ββ> "Cruzeiro Γ© mais barato"
β β
β ββ> calcular_preco_tool(safari, cruzeiro, ski)
β ββ> "Safari $2000, Cruzeiro $800, Ski $1500"
β
ββ> append_event(evento_user)
ββ> append_event(evento_agent)
β ββ> Firestore: messages = [{user_msg1}, {agent_msg1},
β {user_msg2}, {agent_msg2}]
β
ββ> Resposta: "Cruzeiro Γ© mais barato a $800"
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
(dias depois, novo canal)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
T2: UsuΓ‘rio volta em novo canal
user123 em channel#suporte (DIFERENTE!)
session_id = "user123_slack_suporte" (NOVA SESSION)
β
ββ> runner.run_async(user_id, session_id, "Lembra de mim?")
β
ββ> get_session() β Carrega eventos
β β Firestore: messages = [] (nova sessΓ£o!)
β β session.events = []
β ββ> Retorna Session vazio
β
ββ> Agent processa
β ββ> VΓͺ session.events = [] (vazio, nova sessΓ£o)
β β ββ> Agent nΓ£o tem contexto desta sessΓ£o
β β
β ββ> PreloadMemoryTool("histΓ³rico") β Busca MEMΓRIA! π§
β β β search_memory(user_id, query)
β β β ββ> Busca em memory collection
β β β ββ> Encontra: "Conversas sobre viagem, Safari $2000..."
β β β
β β ββ> SearchMemoryResponse([resultado1, resultado2])
β β
β ββ> Agent responde com contexto de LONGO PRAZO!
β "Sim! VocΓͺ perguntou sobre viagens. Recomendei Safari ($2000),
β Cruzeiro ($800), Ski ($1500). Cruzeiro era mais barato."
β
ββ> Resposta: "Claro! VocΓͺ tinha interesse em viagens..."
π― ComparaΓ§Γ£o: Antes vs Depois
β ANTES (Sem Contexto)
Request 1:
User: "Produtos de viagem?"
Agent: "Temos Safari, Cruzeiro, Ski" β
Request 2 (MESMA SESSION):
User: "Qual Γ© mais barato?"
Agent: "Desculpe, preciso saber qual produto vocΓͺ quer comparar" β
(Agent nΓ£o lembrava das opΓ§Γ΅es!)
Request 3 (NOVA SESSION):
User: "Lembra de mim?"
Agent: "Desculpe, Γ© a primeira vez que conversamos" β
(Agent perdia todo histΓ³rico!)
β
DEPOIS (Com Contexto)
Request 1:
User: "Produtos de viagem?"
Agent: "Temos Safari, Cruzeiro, Ski" β
[Salvo em session.events + memory]
Request 2 (MESMA SESSION):
User: "Qual Γ© mais barato?"
Agent: "Cruzeiro Γ© mais barato a $800" β
(Agent viu session.events!)
Request 3 (NOVA SESSION):
User: "Lembra de mim?"
Agent: "Sim! VocΓͺ perguntou sobre viagens.
Recomendei Safari, Cruzeiro e Ski.
Cruzeiro era o mais barato a $800" β
(Agent usou PreloadMemoryTool!)
π§ Modelo Mental: 2 NΓveis de MemΓ³ria
ββββββββββββββββββββββββββββββββββββββββ
β SHORT-TERM MEMORY (Session) β
β β
β session.events = [ β
β Event(role="user", ...), β
β Event(role="assistant", ...), β
β Event(role="user", ...), β
β Event(role="assistant", ...) β
β ] β
β β
β VΓ‘lido por: DuraΓ§Γ£o da conversa β
β Armazenado em: SessionService β
β Acessado por: Automaticamente (Runner)
β β
β Exemplo: "O que vocΓͺ respondeu β
β na primeira mensagem?" β
ββββββββββββββββββββββββββββββββββββββββ
β
β (quando conversa termina)
βΌ
ββββββββββββββββββββββββββββββββββββββββ
β LONG-TERM MEMORY (MemoryService) β
β β
β memory_content = "P: Viagens? β
β R: Safari, Cruzeiro, Ski" β
β β
β VΓ‘lido por: Indefinido β
β Armazenado em: MemoryService β
β Acessado por: Agent com tool β
β (PreloadMemoryTool) β
β β
β Exemplo: "O que vocΓͺ me recomendou β
β semana passada?" β
ββββββββββββββββββββββββββββββββββββββββ
π SeguranΓ§a & Privacidade
βββββββββββββββββββββββββββββββββββββββββββ
β SESSION DATA (Firestore) β
β collection: agente_busca_produtos_... β
β β
β document: {user_id}_slack_{channel_id} β
β ββ messages: [...] β
β ββ updated_at: timestamp β
β ββ expires_at: timestamp (60 minutos) β
β ββ TTL: Auto-delete apΓ³s expiraΓ§Γ£o β
β
β β
β ProteΓ§Γ£o: Dados antigos deletados β
βββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββββββββββββββ
β MEMORY DATA (Firestore) β
β collection: agente_busca_produtos_... β
β β
β document: {user_id}_{timestamp} β
β ββ content: extracted text β
β ββ user_id: indexed para busca β
β ββ created_at: timestamp β
β β
β ProteΓ§Γ£o: Acesso por user_id β
β (isolamento entre usuΓ‘rios) β
βββββββββββββββββββββββββββββββββββββββββββ