Skip to main content

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.

State vs Memory
MemoryState
Enviado ao LLM✅ Sim — como contexto❌ Não
PersistênciaEntre sessõesApenas na sessão atual
Uso típicoPerfil do usuário, histórico relevanteFlags, 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âmetroTipoPadrãoDescrição
ctxActionContextContexto de execução
max_charsint10000Limite 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çãoQuando ocorre
MemoryLimitExceededExceptionOperação de escrita ultrapassaria o max_chars

MemoryLimitExceededException tem os atributos:

  • max_chars — limite configurado
  • current_chars — tamanho atual da memória
  • attempted_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(),
)