Memory Management
O MemoryManager gerencia a memória persistente da conversa — dados que o LLM recebe como contexto e que são mantidos entre sessões. Use para armazenar fatos relevantes sobre o usuário, preferências e progresso de workflows.
| Memory | State | |
|---|---|---|
| Enviado ao LLM | ✅ Sim — como contexto | ❌ Não |
| Persistência | Entre sessões | Apenas na sessão atual |
| Uso típico | Perfil do usuário, histórico relevante | Flags, etapas de controle interno |
Use StateManager para dados que não devem ir para o LLM.
Inicialização
from actions_sdk.core.types.action_context import ActionContext
from actions_sdk.features.conversational.memory import MemoryManager
ctx: ActionContext
memory = MemoryManager(ctx)
# Com limite de caracteres customizado
memory = MemoryManager(ctx, max_chars=5000)
O MemoryManager extrai ctx.initial_memory automaticamente no construtor.
Parâmetros do construtor:
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
ctx | ActionContext | — | Contexto de execução |
max_chars | int | 10000 | Limite máximo de caracteres na memória |
Categorias padrão
O MemoryManager organiza a memória em categorias predefinidas via MemoryCategories:
from actions_sdk.features.conversational.memory import MemoryCategories
MemoryCategories.USER_INFO # "informacoes_usuario"
MemoryCategories.CONVERSATION_FACTS # "fatos_da_conversa"
MemoryCategories.WORKFLOW_PROGRESS # "progresso_workflow"
MemoryCategories.USER_PREFERENCES # "preferencias_usuario"
MemoryCategories.CONTEXT_HINTS # "dicas_contexto"
Métodos de conveniência por categoria
Fatos da conversa
# Armazenar um fato
memory.store_conversation_fact("Usuário mencionou que tem cachorro.")
memory.store_conversation_fact("Usuário já fez compra anteriormente.", metadata={"data": "2025-01"})
# Recuperar fatos (mais recentes primeiro)
fatos = memory.get_conversation_facts(limit=5)
# [{"content": "...", "timestamp": "...", "metadata": {...}}, ...]
Informações do usuário
# Armazenar
memory.store_user_info("nome", "Alice")
memory.store_user_info("cpf", "123.456.789-00")
# Recuperar campo específico
nome = memory.get_user_info("nome")
# Recuperar tudo
dados = memory.get_user_info()
Preferências do usuário
memory.store_user_preference("idioma", "pt-BR")
memory.store_user_preference("canal_preferido", "whatsapp")
pref = memory.get_user_preferences("idioma") # "pt-BR"
todas = memory.get_user_preferences()
Progresso de workflow
memory.store_workflow_progress(
workflow_name="sinistro_auto",
step="coleta_dados",
data={"placa": "ABC-1234", "km": 50000},
)
progresso = memory.get_workflow_progress("sinistro_auto")
# {"current_step": "coleta_dados", "data": {...}, "updated_at": "..."}
Dicas de contexto para o LLM
memory.add_context_hint("Usuário é cliente premium — priorizar atendimento.", priority=2)
memory.add_context_hint("Última compra foi há 3 meses.", priority=1)
Métodos genéricos (acesso livre)
Para armazenar dados fora das categorias padrão:
update(path, value)
memory.update("perfil.cidade", "São Paulo")
memory.update("historico.compras", ["pedido_001", "pedido_002"])
get(path, default=None)
cidade = memory.get("perfil.cidade", "Não informado")
delete(path)
memory.delete("perfil.cidade")
merge(path, data)
# Merge raso
memory.merge("perfil", {"estado": "SP", "pais": "BR"})
Todos suportam notação por ponto para caminhos aninhados e lançam MemoryLimitExceededException se o limite for ultrapassado.
Limite de memória
O MemoryManager valida o tamanho total da memória (em caracteres JSON) a cada operação de escrita. Se o limite for excedido, a operação falha sem modificar a memória:
from actions_sdk.features.conversational.memory.manager import MemoryLimitExceededException
try:
memory = MemoryManager(ctx, max_chars=100)
memory.store_conversation_fact("Este texto longo vai ultrapassar o limite configurado.")
except MemoryLimitExceededException as excecao:
print(excecao.max_chars) # 100
print(excecao.current_chars) # tamanho atual antes da operação
print(excecao.attempted_chars) # tamanho que seria após a operação
Verificar uso de memória
info = memory.get_size_info()
# {
# "current_chars": 1250,
# "max_chars": 10000,
# "available_chars": 8750,
# "usage_percentage": 12
# }
Serialização para Markdown
O MemoryManager converte a memória para Markdown — formato enviado ao LLM como contexto:
# Memória completa como Markdown
markdown = memory.to_markdown()
# Categoria específica
markdown_perfil = memory.get_category_markdown("informacoes_usuario")
Erros e Exceções
| Exceção | Quando ocorre |
|---|---|
MemoryLimitExceededException | Operação de escrita ultrapassaria o max_chars |
MemoryLimitExceededException tem os atributos:
max_chars— limite configuradocurrent_chars— tamanho atual da memóriaattempted_chars— tamanho que seria após a operação
Exemplo completo
Baseado nas actions de homologação do SDK v2:
import traceback
from actions_sdk.core.types.action_context import ActionContext
from actions_sdk.core.types.responses import ResponseStatus, ResponseToAgent
from actions_sdk.features.conversational.memory import MemoryManager
from actions_sdk.features.conversational.memory.manager import MemoryLimitExceededException
from actions_sdk.features.conversational.state import StateManager
from actions_sdk.features.tracing import ActionSpan
ctx: ActionContext
CHAVE_PROGRESSO = "action.memoria.progresso"
LIMITE_FATOS = 10
def registrar_informacao_usuario(fato: str):
span = ActionSpan(ctx)
state = StateManager(ctx)
span.event("action.registrar_info.inicio", {"fato": fato})
try:
memory = MemoryManager(ctx)
memory.store_conversation_fact(fato)
fatos = memory.get_conversation_facts(limit=LIMITE_FATOS)
state.update(CHAVE_PROGRESSO, "SUCESSO ✓")
span.event("action.registrar_info.sucesso", {"total_fatos": len(fatos)})
return ResponseToAgent(
status=ResponseStatus.SUCCESS,
instruction=(
f"Fato registrado na memória.\n"
f"Total de fatos armazenados: {len(fatos)}"
),
state_updates=state.get_full_state(),
)
except MemoryLimitExceededException as excecao:
state.update(CHAVE_PROGRESSO, "LIMITE ✗")
return ResponseToAgent(
status=ResponseStatus.ERROR,
instruction=(
f"Limite de memória atingido.\n"
f"Atual: {excecao.current_chars} chars / Limite: {excecao.max_chars} chars."
),
state_updates=state.get_full_state(),
)
except Exception as erro:
state.update(CHAVE_PROGRESSO, "ERRO ✗")
return ResponseToAgent(
status=ResponseStatus.ERROR,
instruction=f"Falha ao registrar informação: {traceback.format_exc()}",
state_updates=state.get_full_state(),
)