Skip to content

Sessions

Hermes Agent automatically saves every conversation as a session. Sessions enable conversation resume, cross-session search, and full conversation history management.

Every conversation — whether from the CLI, Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Teams, or any other messaging platform — is stored as a session with full message history. Sessions are tracked in two complementary systems:

  1. SQLite database (~/.hermes/state.db) — structured session metadata with FTS5 full-text search
  2. JSONL transcripts (~/.hermes/sessions/) — raw conversation transcripts including tool calls (gateway)

The SQLite database stores:

  • Session ID, source platform, user ID
  • Session title (unique, human-readable name)
  • Model name and configuration
  • System prompt snapshot
  • Full message history (role, content, tool calls, tool results)
  • Token counts (input/output)
  • Timestamps (started_at, ended_at)
  • Parent session ID (for compression-triggered session splitting)

Each session is tagged with its source platform:

SourceDescription
cliInteractive CLI (hermes or hermes chat)
telegramTelegram messenger
discordDiscord server/DM
slackSlack workspace
whatsappWhatsApp messenger
signalSignal messenger
matrixMatrix rooms and DMs
mattermostMattermost channels
emailEmail (IMAP/SMTP)
smsSMS via Twilio
dingtalkDingTalk messenger
feishuFeishu/Lark messenger
wecomWeCom (WeChat Work)
weixinWeixin (personal WeChat)
bluebubblesApple iMessage via BlueBubbles macOS server
qqbotQQ Bot (Tencent QQ) via Official API v2
homeassistantHome Assistant conversation
webhookIncoming webhooks
api-serverAPI server requests
acpACP editor integration
cronScheduled cron jobs
batchBatch processing runs

Resume previous conversations from the CLI using --continue or --resume:

Окно терминала
# Resume the most recent CLI session
hermes --continue
hermes -c
# Or with the chat subcommand
hermes chat --continue
hermes chat -c

This looks up the most recent cli session from the SQLite database and loads its full conversation history.

If you’ve given a session a title (see Session Naming below), you can resume it by name:

Окно терминала
# Resume a named session
hermes -c "my project"
# If there are lineage variants (my project, my project #2, my project #3),
# this automatically resumes the most recent one
hermes -c "my project" # → resumes "my project #3"
Окно терминала
# Resume a specific session by ID
hermes --resume 20250305_091523_a1b2c3d4
hermes -r 20250305_091523_a1b2c3d4
# Resume by title
hermes --resume "refactoring auth"
# Or with the chat subcommand
hermes chat --resume 20250305_091523_a1b2c3d4

Session IDs are shown when you exit a CLI session, and can be found with hermes sessions list.

When you resume a session, Hermes displays a compact recap of the previous conversation in a styled panel before the input prompt:

Stylized preview of the Previous Conversation recap panel shown when resuming a Hermes session.

Resume mode shows a compact recap panel with recent user and assistant turns before returning you to the live prompt.

The recap:

  • Shows user messages (gold ) and assistant responses (green )
  • Truncates long messages (300 chars for user, 200 chars / 3 lines for assistant)
  • Collapses tool calls to a count with tool names (e.g., [3 tool calls: terminal, web_search])
  • Hides system messages, tool results, and internal reasoning
  • Caps at the last 10 exchanges with a ”… N earlier messages …” indicator
  • Uses dim styling to distinguish from the active conversation

To disable the recap and keep the minimal one-liner behavior, set in ~/.hermes/config.yaml:

display:
resume_display: minimal # default: full

Give sessions human-readable titles so you can find and resume them easily.

Hermes automatically generates a short descriptive title (3–7 words) for each session after the first exchange. This runs in a background thread using a fast auxiliary model, so it adds no latency. You’ll see auto-generated titles when browsing sessions with hermes sessions list or hermes sessions browse.

Auto-titling only fires once per session and is skipped if you’ve already set a title manually.

Use the /title slash command inside any chat session (CLI or gateway):

/title my research project

The title is applied immediately. If the session hasn’t been created in the database yet (e.g., you run /title before sending your first message), it’s queued and applied once the session starts.

You can also rename existing sessions from the command line:

Окно терминала
hermes sessions rename 20250305_091523_a1b2c3d4 "refactoring auth module"
  • Unique — no two sessions can share the same title
  • Max 100 characters — keeps listing output clean
  • Sanitized — control characters, zero-width chars, and RTL overrides are stripped automatically
  • Normal Unicode is fine — emoji, CJK, accented characters all work

When a session’s context is compressed (manually via /compress or automatically), Hermes creates a new continuation session. If the original had a title, the new session automatically gets a numbered title:

"my project" → "my project #2" → "my project #3"

When you resume by name (hermes -c "my project"), it automatically picks the most recent session in the lineage.

The /title command works in all gateway platforms (Telegram, Discord, Slack, WhatsApp):

  • /title My Research — set the session title
  • /title — show the current title

Hermes provides a full set of session management commands via hermes sessions:

Окно терминала
# List recent sessions (default: last 20)
hermes sessions list
# Filter by platform
hermes sessions list --source telegram
# Show more sessions
hermes sessions list --limit 50

When sessions have titles, the output shows titles, previews, and relative timestamps:

Title Preview Last Active ID
────────────────────────────────────────────────────────────────────────────────────────────────
refactoring auth Help me refactor the auth module please 2h ago 20250305_091523_a
my project #3 Can you check the test failures? yesterday 20250304_143022_e
— What's the weather in Las Vegas? 3d ago 20250303_101500_f

When no sessions have titles, a simpler format is used:

Preview Last Active Src ID
──────────────────────────────────────────────────────────────────────────────────────
Help me refactor the auth module please 2h ago cli 20250305_091523_a
What's the weather in Las Vegas? 3d ago tele 20250303_101500_f
Окно терминала
# Export all sessions to a JSONL file
hermes sessions export backup.jsonl
# Export sessions from a specific platform
hermes sessions export telegram-history.jsonl --source telegram
# Export a single session
hermes sessions export session.jsonl --session-id 20250305_091523_a1b2c3d4

Exported files contain one JSON object per line with full session metadata and all messages.

Окно терминала
# Delete a specific session (with confirmation)
hermes sessions delete 20250305_091523_a1b2c3d4
# Delete without confirmation
hermes sessions delete 20250305_091523_a1b2c3d4 --yes
Окно терминала
# Set or change a session's title
hermes sessions rename 20250305_091523_a1b2c3d4 "debugging auth flow"
# Multi-word titles don't need quotes in the CLI
hermes sessions rename 20250305_091523_a1b2c3d4 debugging auth flow

If the title is already in use by another session, an error is shown.

Окно терминала
# Delete ended sessions older than 90 days (default)
hermes sessions prune
# Custom age threshold
hermes sessions prune --older-than 30
# Only prune sessions from a specific platform
hermes sessions prune --source telegram --older-than 60
# Skip confirmation
hermes sessions prune --older-than 30 --yes

Pruning only deletes ended sessions (sessions that have been explicitly ended or auto-reset). Active sessions are never pruned.

Окно терминала
hermes sessions stats

Output:

Total sessions: 142
Total messages: 3847
cli: 89 sessions
telegram: 38 sessions
discord: 15 sessions
Database size: 12.4 MB

For deeper analytics — token usage, cost estimates, tool breakdown, and activity patterns — use hermes insights.

The agent has a built-in session_search tool that performs full-text search across all past conversations using SQLite’s FTS5 engine.

  1. FTS5 searches matching messages ranked by relevance
  2. Groups results by session, takes the top N unique sessions (default 3)
  3. Loads each session’s conversation, truncates to ~100K chars centered on matches
  4. Sends to a fast summarization model for focused summaries
  5. Returns per-session summaries with metadata and surrounding context

The search supports standard FTS5 query syntax:

  • Simple keywords: docker deployment
  • Phrases: "exact phrase"
  • Boolean: docker OR kubernetes, python NOT java
  • Prefix: deploy*

The agent is prompted to use session search automatically:

“When the user references something from a past conversation or you suspect relevant prior context exists, use session_search to recall it before asking them to repeat themselves.”

On messaging platforms, sessions are keyed by a deterministic session key built from the message source:

Chat TypeDefault Key FormatBehavior
Telegram DMagent:main:telegram:dm:<chat_id>One session per DM chat
Discord DMagent:main:discord:dm:<chat_id>One session per DM chat
WhatsApp DMagent:main:whatsapp:dm:<canonical_identifier>One session per DM user (LID/phone aliases collapse to one identity when mapping exists)
Group chatagent:main:<platform>:group:<chat_id>:<user_id>Per-user inside the group when the platform exposes a user ID
Group thread/topicagent:main:<platform>:group:<chat_id>:<thread_id>Shared session for all thread participants (default). Per-user with thread_sessions_per_user: true.
Channelagent:main:<platform>:channel:<chat_id>:<user_id>Per-user inside the channel when the platform exposes a user ID

When Hermes cannot get a participant identifier for a shared chat, it falls back to one shared session for that room.

By default, Hermes uses group_sessions_per_user: true in config.yaml. That means:

  • Alice and Bob can both talk to Hermes in the same Discord channel without sharing transcript history
  • one user’s long tool-heavy task does not pollute another user’s context window
  • interrupt handling also stays per-user because the running-agent key matches the isolated session key

If you want one shared “room brain” instead, set:

group_sessions_per_user: false

That reverts groups/channels to a single shared session per room, which preserves shared conversational context but also shares token costs, interrupt state, and context growth.

Gateway sessions are automatically reset based on configurable policies:

  • idle — reset after N minutes of inactivity
  • daily — reset at a specific hour each day
  • both — reset on whichever comes first (idle or daily)
  • none — never auto-reset

Before a session is auto-reset, the agent is given a turn to save any important memories or skills from the conversation.

Sessions with active background processes are never auto-reset, regardless of policy.

WhatPathDescription
SQLite database~/.hermes/state.dbAll session metadata + messages with FTS5
Gateway transcripts~/.hermes/sessions/JSONL transcripts per session + sessions.json index
Gateway index~/.hermes/sessions/sessions.jsonMaps session keys to active session IDs

The SQLite database uses WAL mode for concurrent readers and a single writer, which suits the gateway’s multi-platform architecture well.

Key tables in state.db:

  • sessions — session metadata (id, source, user_id, model, title, timestamps, token counts). Titles have a unique index (NULL titles allowed, only non-NULL must be unique).
  • messages — full message history (role, content, tool_calls, tool_name, token_count)
  • messages_fts — FTS5 virtual table for full-text search across message content
  • Gateway sessions auto-reset based on the configured reset policy
  • Before reset, the agent saves memories and skills from the expiring session
  • Opt-in auto-pruning: when sessions.auto_prune is true, ended sessions older than sessions.retention_days (default 90) are pruned at CLI/gateway startup
  • After a prune that actually removed rows, state.db is VACUUMed to reclaim disk space (SQLite does not shrink the file on plain DELETE)
  • Pruning runs at most once per sessions.min_interval_hours (default 24); the last-run timestamp is tracked inside state.db itself so it’s shared across every Hermes process in the same HERMES_HOME

Default is off — session history is valuable for session_search recall, and silently deleting it could surprise users. Enable in ~/.hermes/config.yaml:

sessions:
auto_prune: true # opt in — default is false
retention_days: 90 # keep ended sessions this many days
vacuum_after_prune: true # reclaim disk space after a pruning sweep
min_interval_hours: 24 # don't re-run the sweep more often than this

Active sessions are never auto-pruned, regardless of age.

Окно терминала
# Prune sessions older than 90 days
hermes sessions prune
# Delete a specific session
hermes sessions delete <session_id>
# Export before pruning (backup)
hermes sessions export backup.jsonl
hermes sessions prune --older-than 30 --yes