| name | sessions |
| description | Gerencia sessões do sistema Ravi. Use quando o usuário quiser:
- Listar, ver detalhes ou renomear sessões
- Resetar ou deletar sessões
- Configurar modelo ou thinking level por sessão
- Limpar sessões inativas com dry-run e filtros explícitos
- Criar sessões efêmeras com TTL
- Estender, manter ou excluir sessões efêmeras
- Enviar prompts, perguntas ou comandos entre sessões
- Ler histórico de mensagens de uma sessão
- Inspecionar trace SQLite de uma sessão para incidentes de runtime/canal
- Atachar um chat como output target de uma sessão
- Atachar múltiplos chats numa mesma sessão sem fork de histórico
|
Sessions Manager
Sessões são conversas persistentes entre agents e usuários. Cada sessão tem um nome único, um agent associado, e pode ter canal de saída (WhatsApp, Matrix, etc).
Sessões são a superfície de comunicação do Ravi. Não são o task runtime. Se o trabalho precisa de dono, progresso e estado terminal, use ravi tasks .... Se a pergunta é medir regressão ou comparar comportamento, use ravi eval ....
Tipos de Sessão
- Permanent (padrão): Sessão normal, sem expiração.
- Ephemeral: Sessão com TTL (time-to-live). Expira automaticamente após o tempo definido. 10 minutos antes de expirar, o agent recebe um aviso com comandos CLI para estender, manter ou excluir.
Comandos
Listagem e Info
ravi sessions list
ravi sessions list --agent <id>
ravi sessions list --ephemeral
ravi sessions info <name>
ravi sessions read <name> [-n count]
ravi sessions trace <name> --since 2h --explain
Gerenciamento
ravi sessions rename <name> <novo-nome-canonico>
ravi sessions set-display <name> "Novo Nome Humano"
ravi sessions set-model <name> <model>
ravi sessions set-thinking <name> <level>
ravi sessions reset <name>
ravi sessions delete <name>
ravi sessions prune --inactive-for 2d --json
ravi sessions prune --inactive-for 2d --execute
prune usa updated_at/última atividade da sessão, não created_at.
Isso evita apagar uma sessão antiga que teve atividade recente.
Filtros úteis:
ravi sessions prune --inactive-for 1d --agent dev
ravi sessions prune --inactive-for 2d --name-prefix task-
ravi sessions prune --inactive-for 12h --ephemeral
Sem --execute, prune é sempre dry-run. Use o dry-run antes de apagar em lote.
Attach (multi-input + speech control)
Diferença chave vs routes: routes decide qual agent atende um chat; attach decide quais chats alimentam uma sessão e qual superfície é o default de fala. Cada subscription tem speech=speak|muted: muted continua escutando sem responder naquele chat; speak permite que uma resposta ao inbound daquele chat saia ali.
Regra crítica: sessions attach NÃO cria, corrige nem troca a route do chat. Use attach apenas quando a route já resolve para o agent correto, ou depois de criar uma route explícita para esse agent. Para chat novo/rota errada, configure a rota primeiro; se quiser forçar a mesma sessão já na route, use ravi instances routes add <instance> <pattern> <agent> --session <session>.
Ver spec sessions/attach pro modelo completo.
ravi sessions subscriptions <session>
ravi sessions attach <session> --chat <chat-id> [--reason "..."]
ravi sessions mute <session> --chat <chat-id>
ravi sessions unmute <session> --chat <chat-id>
ravi sessions detach <session> --chat <chat-id>
Receitas operacionais (validadas em produção):
-
Responder em outro grupo com a mesma sessão. Caso típico: você está falando com dev no grupo de teste, mas quer que o resultado apareça no grupo principal.
sessions attach dev --chat <chat-id-do-grupo-principal>
- Próximas respostas da sessão
dev saem no grupo principal quando o inbound vier de chats muted; se o source chat estiver speech=speak, a resposta sai no próprio source.
- O comando imprime o hint de detach para desligar esse output depois.
-
Unificar histórico de N grupos numa sessão. Caso: dev atende o grupo ravi - dev e você quer que o mesmo dev também receba inbound de ravi - dev - test.
- Primeiro garanta que a route do grupo novo aponta para o agent
dev: ravi instances routes add <instance> "group:<id>" dev --priority 10.
- Se a intenção é fixar a sessão canônica já na route, prefira:
ravi instances routes add <instance> "group:<id>" dev --session dev --priority 10.
- Se o grupo novo já criou uma sessão paralela (
dev-2, vazia), apague a paralela (sessions delete dev-2) antes de consolidar.
- Depois use
sessions attach dev --chat <chat-id-do-test> para ligar o chat à sessão existente e ajustar fala/output.
- Use
sessions mute dev --chat <chat-id-do-test> se o test deve ser listen-only.
-
Migrar grupo de um agent pra outro (sem unificar sessão). Caso: grupo nasceu na sessão de onboarding (auto-criada pelo default agent da instance), você quer mover pro agent dev com sessão SEPARADA.
ravi instances routes add <instance> group:<id> <novo-agent> --priority 10
- O
routes add faz cleanup automático de session conflitante (chama Cleaned N conflicting session(s)).
- Próxima inbound: matchRoute → novo agent → cria sessão nova pra esse (agent, grupo).
- Não confunda com attach — essa NÃO compartilha histórico.
Como compõe na prática (sequence diagram resumido):
inbound chega ─► consumer normaliza chat
─► matchRoute resolve agent + session_key candidato
─► [Fase 2] consumer.findSessionByAttachedChat(chat_id)
│ se subscription existe ─► matched.sessionKey = subscription.sessionKey
│ (subscription override prevalece sobre matchRoute)
─► policy checks
─► commitMatchedRoute + attachChatToSession (idempotente)
─► dispatch turn na sessão escolhida
─► runtime gera resposta
─► resolveSessionOutputTarget:
1. source chat inscrito com speech=speak → win
2. output default com speech=speak → win
3. nada → fail closed (sem envio externo)
─► gateway emite no target resolvido
Anti-patterns:
- ❌ Adicionar route pra "trocar destino" quando o chat já está atachado em outra sessão. A subscription override puxa o inbound de volta. Use detach/delete da sessão antiga antes, ou attach explícito na nova.
- ❌ Usar
sessions attach como se ele configurasse route. Attach não muda o agent que atende o chat; ele só liga o chat a uma sessão quando a route/agent já está correta.
- ❌ Tentar usar
focus pra responder em outro chat. Focus foi removido; attach é o primitive que escolhe o chat de output.
- ❌ Deixar inbound-route bookkeeping roubar output. Inbound pode criar subscription
muted, mas não deve mudar o output target escolhido por operador.
- ❌ Narrar mute/unmute/attach/routing para usuários finais; esse controle é interno.
- ❌ Esperar que
attach sozinho mude o agent que atende o chat. Attach decide sessão; agent vem da route ou do default da instance.
Quando route vs attach:
| Você quer | Use |
|---|
| Outro agent atender o chat (histórico isolado) | instances routes add |
| Mesma sessão em chat cuja route já aponta para o agent correto | sessions attach |
| Mesma sessão em chat novo ou com route errada | instances routes add ... --session <name> e depois sessions attach se precisar ajustar fala/output |
| Forçar uma sessão específica num chat | routes add ... --session <name> (redirect estático) |
Sessões Efêmeras
ravi sessions set-ttl <name> <duration>
ravi sessions extend <name> [duration]
ravi sessions keep <name>
Fluxo automático:
- Sessão criada com
set-ttl recebe TTL
- 10 min antes de expirar, o agent recebe aviso via
[System] Inform: com os comandos CLI
- O agent pode executar
extend, keep, ou delete
- Sem ação → sessão é automaticamente deletada pelo runner
Session Followups
Use sessions followups para cadências de inatividade em sessões/chats/listas. Isso é diferente de cron: --every conta a partir da última atividade externa relevante.
ravi sessions followups add "Follow-up ravi-dev" --target-chat <chat-id> --every 15m --message "Revise o contexto e faça follow-up curto."
ravi sessions followups add "Follow-up ravi-dev" --target-chat <chat-id> \
--step "15m=Revise o contexto e faça um follow-up curto." \
--step "30m=Estude o próximo passo relevante e recomende uma ação concreta."
ravi sessions followups update <id> \
--step "15m=Revise o contexto e faça um follow-up curto." \
--step "30m=Estude o próximo passo relevante e recomende uma ação concreta."
ravi sessions followups update <id> --message "Nova mensagem."
Regras:
- Use
update, não recrie/pausa cadência, quando a intenção é editar nome, descrição, barrier, mensagem ou steps.
- Em cadências progressivas,
--step substitui a lista inteira de steps. Não use --message para tentar editar o segundo step.
update preserva nextRunAt por padrão; use --recalculate-next só quando quiser recalcular a próxima execução.
Comunicação Inter-Sessão
ravi sessions send <name> "mensagem" [-w] [-a agent] [-i]
ravi sessions ask <name> "pergunta" [sender]
ravi sessions answer <name> "resposta" [sender]
ravi sessions execute <name> "tarefa"
ravi sessions inform <name> "info"
sessions send envia prompt/contexto para a sessão do agent; ele não publica texto visível diretamente em WhatsApp, Telegram, Matrix ou outro canal externo. Se o objetivo é falar com uma pessoa/canal, deixe a sessão responder normalmente ou use uma CLI explícita de canal/mídia/outbound apropriada.
Session Trace
Use ravi sessions trace quando precisar entender uma sessão real ponta a ponta:
inbound de canal, routing, prompt publish, decisões de dispatch, request final
do adapter, tools, resposta, delivery e falhas.
SQLite (ravi.db) é a fonte canônica do trace. NATS/logs são apoio para debug
ao vivo, não a fonte primária para reconstruir incidente.
ravi sessions trace <name> --since 2h --explain
ravi sessions trace <name> --turn <turn_id> --explain
ravi sessions trace <name> --run <run_id>
ravi sessions trace <name> --message <source_message_id> --explain
ravi sessions trace <name> --correlation <correlation_id> --raw --explain
ravi sessions trace <name> --only adapter
ravi sessions trace <name> --only tools
ravi sessions trace <name> --only delivery
ravi sessions trace <name> --only dispatch
ravi sessions trace <name> --only turn
ravi sessions trace <name> --since 30m --limit 40
ravi sessions trace <name> --json
ravi sessions trace <name> --show-system-prompt
ravi sessions trace <name> --turn <turn_id> --show-user-prompt
ravi sessions trace <name> --turn <turn_id> --raw
--show-system-prompt resolve o system prompt mais recente da sessão e não
depende do turn estar visível no recorte/limit. User prompt e raw request
continuam escopados a turn/request.
Leitura rápida:
channel.message.received = inbound chegou no Ravi.
route.resolved = rota escolheu sessão e agent.
prompt.published = prompt entrou no stream da sessão.
dispatch.* = cold start, push em sessão viva, queue, interrupt, restart ou task barrier.
runtime.start = runtime começou ou falhou antes do provider.
adapter.request = Ravi montou a request final para o provider. Se existe, chegou no handoff.
tool.start / tool.end = atividade de tool do provider.
assistant.message = texto do assistant recebido do provider.
response.emitted = Ravi emitiu resposta para o gateway.
delivery.* = gateway observou delivered, failed, dropped ou outro status.
turn.complete / turn.failed / turn.interrupted = estado terminal do turno.
session.stalled = evento legado do watchdog de runtime; hoje deve aparecer só em traces históricos. Código novo deve fechar o turno via evento terminal do provider.
Achados comuns do --explain:
prompt-without-adapter-request: prompt nao chegou no handoff do provider; olhar dispatch, debounce, task barrier ou runtime startup.
adapter-request-without-terminal-turn: request foi criada, mas nao houve terminal turn; olhar provider/runtime apos handoff.
response-without-delivery: resposta saiu do runtime mas nao teve delivery observado.
delivery-failed / delivery-dropped: falha ou drop no outbound; olhar payload de delivery e target.
interruption-or-abort: houve interrupt/abort; ler abortReason, session.abort e dispatch.interrupt_requested.
runtime-stalled: trace historico contem session.stalled do watchdog removido; verificar se foi produzido por daemon antigo.
timeout: timeout interrompeu a sessao/turno.
resume-disabled-with-provider-session: havia provider session id mas resume=false; investigar reset/delete/fork/troca de provider ou modelo.
tool-start-without-end: tool iniciou e nao completou no trace.
system-prompt-changed: hashes de system prompt mudaram entre turns.
Golden path SDE para "agent viu a mensagem mas nao respondeu":
ravi sessions trace <name> --since 2h --explain
ravi sessions trace <name> --message <source_message_id> --explain
ravi sessions trace <name> --turn <turn_id> --explain
Classifique pela ultima linha confiavel:
- sem
channel.message.received: inbound nao chegou ou janela/sessao errada.
channel.message.received sem route.resolved: routing/contact resolution.
route.resolved sem prompt.published: publish no stream da sessao.
prompt.published sem adapter.request: dispatch, task barrier, debounce, concorrencia ou runtime startup.
adapter.request sem terminal turn: provider/runtime apos handoff.
session.stalled: trace histórico do watchdog removido; se aparecer em evento novo, há daemon antigo rodando.
assistant.message sem response.emitted: resposta silenciosa, suppressao ou interrupcao.
response.emitted sem delivery.*: gateway/outbound observation.
delivery.failed / delivery.dropped: entrega final no canal.
Para abort/context loss, procure session.abort, session.timeout,
turn.interrupted, provider_session_id_before, provider_session_id_after e
hash de system prompt. resume=false com provider session id existente e
suspeito, exceto se reset/delete/fork/troca de provider/modelo/capability
explicar.
Use placeholders em runbooks e issues (<name>, <turn_id>, <message_id>).
Nao cole telefones reais, ids de grupo/chat, prompts de cliente, context keys,
tokens ou provider session ids em documentacao compartilhada.
Notas
- Reset vs Delete:
reset limpa a conversa mas mantém nome/routing/config. delete remove a sessão inteira.
- Session names: nomes canonicos unicos usados em routing, historico e topicos NATS. Use um token sem espacos, pontos (
.), * ou >. sessions rename muda esse nome canonico e atualiza rotas que apontavam para o nome antigo.
- Display labels: labels humanos vivem em
display_name. Use sessions set-display para nomes com espaco, acentos ou contexto visual; isso nao altera routing nem historico.
- Source automático: Todos os comandos de comunicação incluem source (channel/chatId) automaticamente — o agent sabe onde responder.
send vs inform: send é a opção mais geral e pode esperar resposta com -w; inform é fogo-e-esqueça explícito para contexto.
- Isolamento de contexto:
sessions read deve recuperar apenas a sessão atual. Nunca use histórico de outro grupo/DM como fallback para responder uma sessão fria.