State Management
O StateManager gerencia o estado volátil da sessão — dados descartados quando a conversa termina. Use para flags de controle, configurações temporárias e informações de negócio que não precisam ser enviadas ao LLM como contexto.
| State | Memory | |
|---|---|---|
| Propósito | Controle interno e regras de negócio | Contexto enviado ao LLM |
| Visibilidade para o LLM | ❌ Não | ✅ Sim |
| Persistência | Dura a sessão | Persistente entre sessões |
| Uso típico | Flags, etapas de workflow, dados temporários | Fatos do usuário, preferências, histórico |
Use MemoryManager quando quiser que os dados influenciem as respostas do LLM.
Inicialização
from actions_sdk.core.types.action_context import ActionContext
from actions_sdk.features.conversational.state import StateManager
ctx: ActionContext
state = StateManager(ctx)
O StateManager extrai ctx.initial_state e ctx.state_protected_keys automaticamente no construtor.
Métodos
update(path, value)
Define ou insere um valor no estado. Cria dicionários intermediários automaticamente.
# Chave simples
state.update("etapa", "validacao")
# Notação por ponto — cria {"usuario": {"nome": "Alice"}}
state.update("usuario.nome", "Alice")
state.update("usuario.cpf", "123.456.789-00")
# Valor booleano
state.update("flags.aceite_termos", True)
Parâmetros:
| Parâmetro | Tipo | Descrição |
|---|---|---|
path | str | list[str] | Chave ou caminho com notação por ponto |
value | Any | Valor a definir |
model_class | Type[BaseModel] | None | Modelo Pydantic para validação antes de persistir |
Retorna: True se bem-sucedido.
Exceções:
PermissionError— se o caminho referenciar uma chave protegida
get(path, default=None)
Recupera um valor do estado.
etapa = state.get("etapa") # None se não existir
nome = state.get("usuario.nome", "Desconhecido") # Default customizado
cpf = state.get("usuario.cpf")
Parâmetros:
| Parâmetro | Tipo | Descrição |
|---|---|---|
path | str | list[str] | Chave ou caminho com notação por ponto |
default | Any | Valor retornado se o caminho não existir (padrão: None) |
model_class | Type[BaseModel] | None | Modelo Pydantic para validar o retorno |
Exceções:
ValidationError— semodel_classfor fornecido e a validação falhar
delete(path)
Remove um valor do estado. Retorna o valor removido, ou None se não existir.
valor_removido = state.delete("etapa")
state.delete("usuario.cpf")
Parâmetros:
| Parâmetro | Tipo | Descrição |
|---|---|---|
path | str | list[str] | Caminho do valor a remover |
Retorna: Valor removido ou None.
Exceções:
PermissionError— se o caminho referenciar uma chave protegida
merge(path, data)
Realiza merge raso de um dicionário no estado no caminho informado. Útil para atualizar múltiplos campos de um objeto sem sobrescrever tudo.
# State: {"usuario": {"nome": "Alice"}}
state.merge("usuario", {"cpf": "123", "telefone": "11999"})
# Resultado: {"usuario": {"nome": "Alice", "cpf": "123", "telefone": "11999"}}
Parâmetros:
| Parâmetro | Tipo | Descrição |
|---|---|---|
path | str | list[str] | Caminho de destino |
data | dict | BaseModel | Dicionário ou modelo Pydantic para mesclar |
Retorna: True se bem-sucedido.
Exceções:
PermissionError— se o caminho referenciar uma chave protegida
has_key(key)
Verifica se uma chave de raiz existe no estado.
if state.has_key("usuario"):
nome = state.get("usuario.nome")
Parâmetros: key (str) — chave de raiz.
Retorna: bool
get_full_state()
Retorna uma cópia rasa do dicionário completo de estado. Use sempre no campo state_updates do retorno da action.
return ResponseToAgent(
status=ResponseStatus.SUCCESS,
instruction="Operação concluída.",
state_updates=state.get_full_state(),
)
Retorna: dict[str, Any]
Notação por ponto
O StateManager suporta caminhos aninhados com . em qualquer profundidade:
state.update("pedido.itens.0.status", "processando")
state.update("pedido.itens.0.valor", 99.90)
status = state.get("pedido.itens.0.status") # "processando"
Dicionários intermediários são criados automaticamente.
Chaves protegidas
Algumas chaves são marcadas como protegidas pelo motor e não podem ser sobrescritas ou deletadas:
# PermissionError — chave protegida
state.delete("files")
state.update("files", [])
Para listas protegidas, apenas append é permitido (a nova lista deve estender a atual sem modificar itens existentes).
Validação com Pydantic
from pydantic import BaseModel
class DadosUsuario(BaseModel):
nome: str
cpf: str
# Salvar com validação
state.update("usuario", {"nome": "Alice", "cpf": "123"}, model_class=DadosUsuario)
# Ler como modelo
dados: DadosUsuario = state.get("usuario", model_class=DadosUsuario)
print(dados.nome) # "Alice"
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.state import StateManager
from actions_sdk.features.tracing import ActionSpan
ctx: ActionContext
CHAVE_PROGRESSO = "minha_action.progresso"
def processar_pedido(pedido_id: str):
span = ActionSpan(ctx)
state = StateManager(ctx)
span.event("action.processar_pedido.inicio", {"pedido_id": pedido_id})
try:
# Salvar andamento no state
state.update(CHAVE_PROGRESSO, "buscando_pedido")
state.update("pedido.id", pedido_id)
state.update("pedido.status", "em_processamento")
# ... lógica de negócio ...
valor_confirmado = state.get("pedido.id")
state.update(CHAVE_PROGRESSO, "concluido")
return ResponseToAgent(
status=ResponseStatus.SUCCESS,
instruction=f"Pedido {valor_confirmado} processado com sucesso.",
state_updates=state.get_full_state(),
)
except Exception as erro:
state.update(CHAVE_PROGRESSO, "erro")
span.event("action.processar_pedido.erro", {"erro": str(erro)})
return ResponseToAgent(
status=ResponseStatus.ERROR,
instruction=f"Falha ao processar pedido: {traceback.format_exc()}",
state_updates=state.get_full_state(),
)