Skip to main content
By the end of this page you will know which session a chat lands in, how to talk to any session from your terminal, how to control when a message reaches a busy agent, and how to reset a session or change its model.

What a session is

A session is one ongoing conversation of one agent. It holds the conversation history, the provider’s own session (so the next turn resumes with context), the place where replies go, and any per-session overrides such as model or effort. Sessions are how Ravi communicates. They are not a task tracker: when work needs an owner, progress and a done/failed state, use ravi tasks.

Keys and names

Every session has two identifiers:
  • A key, built from the route that created it. It encodes the agent, channel, instance and peer.
  • A name, short and unique, which you type in commands. Names are single tokens with no spaces, dots, * or >, because they appear in NATS subjects.
Every ravi sessions command accepts either one. ravi sessions list shows both. The <peer> in a DM key is the phone number on WhatsApp and the Slack member ID (U...) on Slack. Groups, channels and threads always get their own session, whatever the DM scope. DM scope decides how DMs are grouped: Set it per agent with ravi agents set main dmScope main, or per route (see Instances and routing). Changing the scope only affects chats that have no session yet. A chat that already talked stays attached to its old session; to move it, detach it with ravi sessions detach <old-session> --chat <chat-id> and its next message goes to the session the new scope computes.

Find and read a session

read returns the stored message log without tool calls. That log survives resets and provider changes.

Talk to a session from the terminal

  • -a main creates the session with agent main if no session has that name or key. Without -a, a missing session fails with Session not found: main. Use -a <agent> to create it.
  • -w waits for this turn’s reply and prints it. Without -w, send returns as soon as the prompt is published.
  • -i opens an interactive loop. Inside it, /reset, /info and /exit work.
When you run send from your shell, the agent receives your text as is. If the session came from a chat, the reply is also posted in that chat. A session created from the terminal has no chat: read its replies with -w or ravi sessions read. send prompts a session. It does not post your literal text into a chat. To make the agent say something in a channel, ask it to.

Messages between sessions

Agents use the same commands to coordinate with each other. Each one wraps the text so the receiving agent knows what kind of message it is. The ask/answer flow: session A asks B; B answers right away if it knows, otherwise it asks in its own chat and relays every related reply back to A with ravi sessions answer. All five accept --channel and --to, used together, to deliver the agent’s reply to another chat. What you pass is still a prompt for the agent, not text posted as is.

Delivery barriers

A barrier decides when a message reaches an agent that is in the middle of a turn. On WhatsApp, a chat message that starts with urgent, urgente or p0: is delivered as p0.

Chat prefixes: >> and !!

In Slack and WhatsApp you can start a message with a prefix to change how it is delivered:
  • >>your text waits for the current turn to end (p2) instead of steering it.
  • !!your text is saved to the conversation without running a turn. The agent sees it together with the next message that does run a turn.
The prefix must be the first non-space text in the message, so a mention before it (@Ravi >>...) turns it off. >>> (a Slack quote) and !!! are not prefixes. A prefix with nothing after it is sent literally, and editing a message does not reapply a prefix.
The >> and !! prefixes ship in ravi.bot@next and are not in @latest.

Reset and delete

Reset and delete are dry-run by default: without --execute they print the plan and exit with code 3.
Reset stops a running turn and drops the provider conversation, the last-used provider and the token counters. The next message starts with a fresh context. The name, routing, attached chats and overrides stay, and so does the message log that read shows.
Delete stops the session and removes it. The next message from that chat creates a new session. To clean up in bulk, preview first:
For a session that should expire on its own, ravi sessions set-ttl <name> 5h makes it ephemeral. Ten minutes before it expires, the agent gets a notice; ravi sessions extend <name> [duration] adds time (5h by default) and ravi sessions keep <name> makes it permanent again.

Model, provider and effort per session

Overrides on a session win over the agent’s settings, which win over global defaults (ravi settings set runtime.defaultProvider claude, runtime.defaultModel, runtime.defaultEffort).
  • set-model saves the override and notifies the running daemon. An active session switches without a restart when the provider supports it.
  • set-provider applies on the next turn. If the session’s provider conversation belongs to another provider, it is cleared.
  • set-effort applies on the next turn and restarts an active runtime when the effort changes. With nothing set anywhere, effort is xhigh; a session created from the terminal with send -a starts at high.
  • set-thinking applies on the next session start (after a reset or a daemon restart).
  • set-model and set-provider take --propagate to also set the agent’s default and move its other sessions that have no override.
A session that already ran remembers its last-used provider. Change the agent’s provider with ravi agents set main provider claude: it also moves the agent’s sessions that have no override (add --force to clear session overrides too).

Rename and label

rename keeps the key and updates routes that pointed at the old name. set-display only changes the label shown in listings.

Attach more chats to one session

A route decides which agent answers a chat. Attach decides which session a chat feeds, so one session can share its history across several chats.
  • Each incoming message is answered in its own chat or thread.
  • The attached chat becomes the default output for turns that have no incoming message, such as cron jobs, triggers and send from the shell.
  • --chat takes Ravi’s chat id or the platform id (for Slack, the channel id C...).
Attach does not create a route. Create the route first, for example ravi instances routes add slack-main group:C0ABC123 main --session <session>, then attach. Once attached, the chat’s messages go to this session and its agent even if a route names another agent (ravi routes explain reports it as Sticky attach). Every chat that has already talked is attached to its own session, so detach it from that session first.

When something goes wrong

The session trace shows every step from the incoming message to delivery:
Troubleshooting explains how to read it. Agents only see and change sessions inside their permission scope. A session outside it is reported as Session not found, so check ravi sessions list before concluding a session does not exist.