Seu agente perde conversa (sem state management robusto)
Agente sem persistência = conversa perdida. Postgres durable workflows: state robusto. Quando agente perde contexto, cliente cancela.
Equipe OpenClaw · Time de Engenharia & Produto
A Equipe OpenClaw é formada por engenheiros, designers e especialistas em IA dedicados a construir a melhor plataforma de agentes conversacionais para negócios brasileiros. Combinamos expertise…
Seu agente perde conversa (sem state management robusto)
Você tem SaaS.
Seu SaaS: agente IA no WhatsApp (atendimento).
Cliente conversa com agente:
Cliente: "Oi, quero reembolso no pedido #12345"
Agente: "Qual é seu email?"
Cliente: "meu@email.com"
Agente: "Qual foi a razão da devolução?"
Cliente: "Produto chegou quebrado"
Agente: "Entendi. Vou processar seu reembolso."
Cliente: "Obrigado!"
5 minutos depois:
Cliente: "Você vai enviar email com comprovante do reembolso?"
Agente: "Qual é seu email?"
Cliente: "WTF? Acabei de contar pro você que meu email é meu@email.com!"
Cliente PUTO: "Seu agente é broken. Não lembra da conversa anterior."
Você:
"WTF? Agente deveria lembrar do email que cliente mandou 5 minutos atrás!
Por que agente perguntou de novo?"
Resposta:
Seu agente NÃO TEM STATE MANAGEMENT ROBUSTO.
Seu agente não persiste conversa (em database).
Agente rodou em memória (RAM).
Quando request terminou, memória foi limpa.
Agente perdeu contexto.
Proxima conversa = agente não sabe nada (start from zero).
O problema: agente sem state management = conversa fragmentada
Agente stateless (seu agente agora): conversa quebrada
ARQUITETURA: Stateless agente
Cliente conversa com agente:
Request 1:
- Input: "Oi, quero reembolso"
- Agente em RAM (processa request)
- Agente responde: "Qual é seu email?"
- Request termina
- Agente STATE em RAM é APAGADO (memória liberada)
Request 2 (5 minutos depois):
- Input: "Produto quebrado"
- Agente em RAM (processa request NOVO)
- Agente NOT SÃO sabe o que cliente disse antes (estado anterior foi apagado)
- Agente responde: "Qual é seu email?" (pergunta de novo)
- Customer PUTO: "Agente perdeu nossa conversa!"
POR QUE AGENTE PERDEU CONVERSA?
Request 1 had data:
- email: meu@email.com
- pedido_id: 12345
- razão: "Produto quebrado"
But data was only in RAM (Request 1).
When Request 1 finished:
- RAM liberated (memory cleared)
- Data lost (not persisted to database)
Request 2 started:
- Fresh RAM (no data from Request 1)
- Agente não sabe nada
- Agente pergunta de novo (email, razão, etc)
RESULT:
Agente perdeu conversa (estado não foi persistido). Cliente frustra (agente não lembra). Cliente cancela (agente is broken).
Agente stateful (com Postgres): conversa contínua
ARQUITETURA: Stateful agente (Postgres)
Cliente conversa com agente:
Request 1:
- Input: "Oi, quero reembolso"
- Agente em RAM (processa request)
- Agente responde: "Qual é seu email?"
- Agente PERSISTE estado em Postgres:
- conversation_id: "conv_12345"
- user_email: NULL (waiting for input)
- pedido_id: NULL
- razão: NULL
- status: "awaiting_email"
- Request termina
- Agente estado em RAM é APAGADO (mas Postgres tem backup)
Cliente responde:
- Input: "meu@email.com"
Request 2:
- Agente carrega estado de Postgres (conversation_id: "conv_12345")
- Agente vê: user_email = NULL (previous request), now user input = "meu@email.com"
- Agente ATUALIZA Postgres:
- user_email: "meu@email.com"
- status: "awaiting_reason"
- Agente responde: "Qual foi a razão da devolução?"
- Request termina
Cliente responde:
- Input: "Produto quebrado"
Request 3:
- Agente carrega estado de Postgres (conversation_id: "conv_12345")
- Agente vê: email = "meu@email.com" (from previous request)
- Agente vê: pedido_id = "12345" (from request 1)
- Agente ATUALIZA Postgres:
- razão: "Produto quebrado"
- status: "ready_to_process_refund"
- Agente responde: "Entendi. Vou processar seu reembolso para meu@email.com, pedido #12345, razão: produto quebrado."
- Request termina
5 minutos depois:
Cliente: "Você vai enviar email com comprovante?"
Request 4:
- Agente carrega estado de Postgres (conversation_id: "conv_12345")
- Agente VÊ TUDO (email, pedido_id, razão, status de refund)
- Agente responde: "Sim, já enviei comprovante pro seu email meu@email.com. Você receberá em 2-3 dias."
- Customer HAPPY: "Agente lembrou de tudo!"
RESULT:
Agente persistiu estado (Postgres database). Agente remembers conversa (estado carregado de DB). Customer happy (seamless experience). Customer não cancela (agente works).
3 tipos de state que agente precisa persistir (para não quebrar conversa)
State Type 1: Conversation context (o que cliente disse)
CONTEXT:
Cliente diz várias coisas durante conversa. Agente precisa lembrar de TUDO que cliente disse (pra dar resposta consistente).
EXEMPLO:
Message 1: Cliente: "Quero reembolso do pedido #12345" Message 2: Cliente: "Produto chegou quebrado" Message 3: Cliente: "Preciso de urgência, tenho evento amanhã" Message 4: Cliente: "Meu email é meu@email.com"
State que agente precisa persistir:
- conversation_id: "conv_12345"
- pedido_id: "12345"
- razão_refund: "Produto quebrado"
- urgência: "Sim, cliente tem evento amanhã"
- email: "meu@email.com"
- timestamp: 2026-05-28T10:00:00Z
Sem persistência:
- Agente recebe Message 4
- Agente não sabe contexto (messages 1-3)
- Agente responde genérico (não leva em conta urgência, razão, etc)
- Response é ruim (não contextualizado)
Com Postgres persistência:
- Agente recebe Message 4
- Agente carrega conversação de Postgres (vê todas messages 1-3)
- Agente sabe contexto (pedido, razão, urgência)
- Response é contextualizado ("Entendo urgência, vou priorizar seu refund")
- Customer happy (agente entende situação)
State Type 2: Workflow state (qual é o progresso do problema)
WORKFLOW STATE:
Agente é multi-step (não é single-step). Agente precisa rastrear qual step está em (pra não repetir steps).
EXEMPLO: Refund workflow
Step 1: Entender pedido (qual pedido? qual email?) Step 2: Verificar policy (refund é válido? cliente dentro do prazo?) Step 3: Processar refund (chamar payment API) Step 4: Enviar confirmação (mandar email)
Workflow state que agente precisa persistir:
conversation_id: "conv_12345" workflow_step: 3 (currently processing refund) step_1_status: "completed" (entendimento OK) step_2_status: "completed" (verificação OK, refund válido) step_3_status: "in_progress" (processando refund agora) step_3_attempt: 1 (tentativa 1) step_3_retry_count: 0 step_3_error: NULL (sem erro até agora)
Sem persistência:
- Agente no Step 3 (processando refund)
- Payment API call falha (timeout)
- Request termina (error)
- Agente não sabe que estava no Step 3 (estado perdido)
- Next request, agente começa do Step 1 de novo (repete tudo)
- Resultado: refund processado 2x (ou customer dados com requests repetidos)
Com Postgres persistência:
- Agente no Step 3 (processando refund)
- Payment API call falha (timeout)
- Agente persiste erro em Postgres: step_3_error: "timeout"
- Request termina
- Next request, agente vê: workflow_step = 3, step_3_status = "in_progress"
- Agente retries Step 3 (não repete Steps 1-2)
- Agente é smart (resume from where it left off)
- Resultado: refund processado 1x (sem duplicatas)
State Type 3: External API state (o que APIs retornaram)
EXTERNAL API STATE:
Agente chama APIs (payment, email, database, etc). Agente precisa lembrar o que APIs retornaram (pra não chamar de novo).
EXEMPLO:
Step 3: Agente chama payment API
- Payment API: "Refund processado, transaction_id = txn_12345"
- Agente precisa persistir: transaction_id = "txn_12345" (pra depois rastrear)
Step 4: Agente manda email
- Email API: "Email enviado, message_id = msg_67890"
- Agente precisa persistir: message_id = "msg_67890" (pra depois rastrear)
State que agente precisa persistir:
conversation_id: "conv_12345" external_calls: [ { api_name: "payment_api", endpoint: "/process_refund", status: "success", response: { transaction_id: "txn_12345", amount: 500, currency: "BRL" }, timestamp: 2026-05-28T10:05:00Z }, { api_name: "email_api", endpoint: "/send_email", status: "success", response: { message_id: "msg_67890", recipient: "meu@email.com" }, timestamp: 2026-05-28T10:06:00Z } ]
Sem persistência:
- Agente processou refund (transaction_id = txn_12345)
- Agente mandou email (message_id = msg_67890)
- Request termina
- Estado perdido (not persisted)
- Customer responde: "Você mandou email? Não recebi ainda."
- Next request, agente não sabe que já mandou email (estado perdido)
- Agente manda email de novo (segunda vez)
- Customer recebe 2 emails (duplicatas)
Com Postgres persistência:
- Agente processou refund (transaction_id = txn_12345)
- Agente mandou email (message_id = msg_67890)
- Agente persiste tudo em Postgres (external_calls array)
- Request termina
- Customer responde: "Você mandou email? Não recebi ainda."
- Next request, agente carrega estado
- Agente vê: email_api já foi chamado (status = "success")
- Agente NÃO manda email de novo (smart, evita duplicata)
- Agente responde: "Já enviei email antes. Pode ter caído em spam. Deixa eu reenviar." (ou verifica status)
Por que Postgres é a solução (não cache em memória, não Redis)
Problema com memória (RAM): dados perdidos quando agente cai
ARQUITETURA: In-memory state (RAM)
Agente usa:
- Node.js (em memória)
- Python dict/cache (em memória)
- Cache simples (não persistido)
Problema 1: Server restart
- Agente rodando em 1 servidor
- Estado em RAM (memória)
- Servidor bate um crash (bug, memory leak, deploy novo)
- RAM é wiped
- Agente estado PERDIDO
- Customer conversação APAGADA
- Customer puto ("Minha conversa desapareceu!")
Problema 2: Horizontal scaling (múltiplos servidores)
- Agente roda em 3 servidores (load balancer distribui requests)
- Request 1: Server A (estado em RAM de Server A)
- Request 2: Load balancer distribui pra Server B
- Server B não tem estado (estado de Request 1 estava em Server A)
- Agente não lembra nada
- Customer puto ("Agente esqueceu tudo!")
Problem 3: Long-lived conversations
- Conversation dura dias/semanas (customer não resolve tudo em 1 request)
- Agente estado em RAM (esperando customer responder)
- RAM não é infinito (memory usage cresce)
- Server roda out of memory (OOM)
- Agente crashes
- Conversation perdida
RESULT:
In-memory state é FRÁGIL. Perde dados quando server crashes. Não funciona em distributed systems. Não funciona pra long-lived conversations.
Problema com Redis: dados perdidos quando Redis cai
ARQUITETURA: Redis cache
Agente usa:
- Redis (in-memory cache with persistence)
- Set TTL (time-to-live): 24 horas
- Goal: persistência + velocidade
Problema 1: Redis crash
- Agente state em Redis
- Redis server crashes (bug, maintenance, network partition)
- Redis data lost (default: no backup)
- Agente estado PERDIDO
- Customer conversação APAGADA
Problema 2: TTL expiration
- Conversation state tem TTL: 24 horas
- Customer não responde por 25 horas
- TTL expired
- Redis deletes conversation state
- Customer responde (day 2)
- Agente não lembra contexto (state expired)
- Agente pergunta de novo
Problem 3: Network partition
- Agente em Server A, Redis em Server B
- Network partition (network down)
- Agente can't reach Redis
- Agente fallback to in-memory (unreliable)
- Network heals
- Data inconsistency (Redis tem versão 1, in-memory tem versão 2)
RESULT:
Redis é FAST mas UNRELIABLE. Perde dados quando Redis crashes. TTL expires conversation (bad for long-lived convs). Network partitions cause inconsistency.
Solução: Postgres (ACID durability)
ARQUITETURA: Postgres (durable workflows)
Agente usa:
- Postgres (relational DB with ACID guarantees)
- State persisted em disk (não em RAM)
- Backup + replication (alta disponibilidade)
PROS:
-
DURABILITY:
- Write to Postgres = durável (salvo em disk)
- Mesmo se agente crashes, dados em Postgres (safe)
- Mesmo se server reboots, dados em Postgres (safe)
-
CONSISTENCY:
- ACID transactions (atomicity, consistency, isolation, durability)
- Estado é always consistent (não pode ficar em estado intermediário)
-
AVAILABILITY:
- Postgres replication (multiple replicas)
- Backup (nightly, or continuous)
- Disaster recovery (restore from backup)
- State is never lost (even if primary crashes)
-
SCALABILITY:
- Postgres is shared (multiple agente servers can read/write same Postgres)
- Horizontal scaling works (Request 1 → Server A, Request 2 → Server B, ambos acessam same Postgres)
- Long-lived conversations work (estado persisted, não depende de in-memory)
-
QUERYING:
- SQL queries (analyze conversation patterns, debug, etc)
- Indexes (fast lookups)
- Joins (relate conversation to customer, order, etc)
CONS:
- SLIGHTLY SLOWER than Redis (disk I/O vs in-memory)
- MORE COMPLEX (need to schema design, migrations, etc)
BUT WORTH IT (durability > speed, reliability > speed)
Como implementar agente com Postgres durable workflows
Step 1: Schema design (conversa + estado)
sql CREATE TABLE conversations ( conversation_id UUID PRIMARY KEY, customer_id UUID NOT NULL, channel VARCHAR(50) NOT NULL, -- 'whatsapp', 'sms', 'email' status VARCHAR(50) NOT NULL, -- 'active', 'completed', 'waiting_customer' created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), INDEX (customer_id), INDEX (channel), INDEX (status) );
CREATE TABLE conversation_messages ( message_id UUID PRIMARY KEY, conversation_id UUID NOT NULL, sender VARCHAR(50) NOT NULL, -- 'customer', 'agent' message_text TEXT NOT NULL, timestamp TIMESTAMP DEFAULT NOW(), FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id), INDEX (conversation_id) );
CREATE TABLE conversation_state ( state_id UUID PRIMARY KEY, conversation_id UUID NOT NULL, workflow_step INT, workflow_status VARCHAR(50), -- 'pending', 'in_progress', 'completed', 'error' context_data JSONB, -- all context (email, pedido_id, razão, etc) external_calls JSONB, -- array of API calls (payment, email, etc) last_error VARCHAR(500), updated_at TIMESTAMP DEFAULT NOW(), FOREIGN KEY (conversation_id) REFERENCES conversations(conversation_id), INDEX (conversation_id), INDEX (workflow_status) );
Step 2: Agent logic (load state, process, save state)
python
Pseudocode
def process_customer_message(conversation_id, customer_message): # Step 1: Load conversation state from Postgres conversation = db.query("SELECT * FROM conversations WHERE id = %s", conversation_id) messages = db.query("SELECT * FROM conversation_messages WHERE conversation_id = %s ORDER BY timestamp", conversation_id) state = db.query("SELECT * FROM conversation_state WHERE conversation_id = %s", conversation_id)
# Step 2: Process message with context
context = {
'messages': messages, # all previous messages
'state': state, # workflow state, external API calls
'customer_message': customer_message
}
agent_response = llm.generate(context) # use LLM with context
# Step 3: Save new message
db.insert("INSERT INTO conversation_messages (conversation_id, sender, message_text) VALUES (%s, %s, %s)",
conversation_id, 'customer', customer_message)
# Step 4: Save agent response
db.insert("INSERT INTO conversation_messages (conversation_id, sender, message_text) VALUES (%s, %s, %s)",
conversation_id, 'agent', agent_response)
# Step 5: Update state (if workflow progressed)
if agent_did_api_call:
db.update("UPDATE conversation_state SET external_calls = %s WHERE conversation_id = %s",
new_api_calls, conversation_id)
if agent_progressed_workflow:
db.update("UPDATE conversation_state SET workflow_step = %s WHERE conversation_id = %s",
next_step, conversation_id)
return agent_response
Conclusão: Postgres durable workflows = conversas que não quebram
**O que você precisa saber:
-
Agente sem state management = conversas quebradas
- Agente em RAM = dados perdidos quando request termina
- Próxima conversa = agente não lembra nada (start from zero)
- Customer puto ("Agente perdeu nossa conversa!")
- Customer cancela (agente is broken)
-
3 tipos de state que agente precisa persistir:
- Conversation context (o que customer disse)
- Workflow state (qual step você está)
- External API state (o que APIs retornaram)
- Sem persistência = customer recebe respostas genéricas + APIs chamadas múltiplas vezes
-
Por que Postgres (não memória, não Redis):
- In-memory: perde dados quando server crashes
- Redis: perde dados quando Redis crashes, TTL expires
- Postgres: ACID durability (dados safe em disk, replicated, backed up)
- Postgres: funciona com horizontal scaling (múltiplos servidores, 1 Postgres)
- Postgres: funciona com long-lived conversations (dias/semanas)
-
Implementação:
- 3 tabelas (conversations, messages, state)
- Agent logic: load state → process → save state
- Simple (mas transformative)
-
Impact:
- Customer conversa persiste (mesmo se agente crashes)
- Customer não precisa repetir contexto (agente remembers)
- Workflow é durável (não repete steps, não faz API calls duplicadas)
- Customer happy (agente is reliable)
- Customer não cancela (agente works)
Na OpenClaw, ajudamos startup de agente IA a:
- AUDIT state management (seu agente tem Postgres? Redis? In-memory?)
- IDENTIFY conversation loss (quantas conversas são perdidas quando server crashes?)
- DESIGN schema (qual estrutura de data para persistir estado?)
- IMPLEMENT durable workflows (build agent com Postgres persistência)
- MONITOR conversation health (são conversas completando? Estão sendo abandonadas?)
Resultado: Seu agente é durável (conversas não quebram, customers não cancela).
Seu agente persiste estado em Postgres?
Ou você está perdendo conversas quando server crashes?
Publicado em 29 de maio de 2026