Channel Docking

One conversation, many channels. Start in Telegram, continue in CLI, finish from VSCode โ€” all the same session.

How it works

Every message has a sessionKey. The gateway uses this key, not the channel name, to look up session state. So as long as you reuse the same key, the conversation continues:

# On Telegram bot (sessionKey = chat_id "12345")
> "What is the BTC status?"

# Later from CLI (passing sessionKey="12345"):
curl -X POST http://127.0.0.1:18789/agent \
  -d '{
    "sessionKey": "12345",
    "message": "More detail on what I asked earlier",
    "channel": "cli"
  }'
# โ†’ agent remembers BTC context from Telegram message

Choosing sessionKey

The sessionKey identifies you, not the channel. Common patterns:

  • Telegram chat_id โ€” natural per-user key
  • Slack user_id โ€” same person across DM and channels
  • Your username โ€” for CLI/VSCode (e.g. process.env.USER)
  • Workspace name โ€” separate work vs personal threads

Storage

Sessions live in ~/.openvesper/workspace/sessions/<safe-key>.json with file mode 0600. Each session holds:

  • Session ID, sessionKey, active agent
  • Last 200 messages (older auto-trimmed)
  • Created/updated timestamps
  • Free-form metadata

Cached in-memory (LRU, max 100 active). Disk read on cold start.

Privacy

All session data stays on your machine. Nothing transmitted to OpenVesper (we have no servers). LLM calls go directly from your gateway to your chosen provider per their privacy policy.

Channel attribution

Each message records which channel it arrived through. Useful for debugging ("the user asked this from Telegram on phone, that's why response was short").

Source

Implementation: apps/gateway/src/sessions.ts.

What's next?