Output:
╔══════════════════════════════════════════════════════════╗
  ║                    📊 Hermes Insights                    ║
  ║                       Last 3 days                        ║
  ╚══════════════════════════════════════════════════════════╝

  Period: May 11, 2026 — May 14, 2026

  📋 Overview
  ────────────────────────────────────────────────────────
  Sessions:          28            Messages:        3,292
  Tool calls:        1,548         User messages:   119
  Input tokens:      2,572,352     Output tokens:   266,190
  Total tokens:      52,771,255
  Active time:       ~2.5d         Avg session:     ~2h 12m
  Avg msgs/session:  117.6

  🤖 Models Used
  ────────────────────────────────────────────────────────
  Model                          Sessions       Tokens
  gpt-5.5                              16   39,769,553
  qwen-3.6-agent                       10   12,572,712
  openrouter                            1      428,990
  auto                                  1            0

  📱 Platforms
  ────────────────────────────────────────────────────────
  Platform       Sessions   Messages         Tokens
  telegram             17      3,202     51,854,281
  cron                 11         90        916,974

  🔧 Top Tools
  ────────────────────────────────────────────────────────
  Tool                            Calls        %
  terminal                          502    32.4%
  todo                              187    12.1%
  patch                             160    10.3%
  execute_code                      121     7.8%
  skill_view                        102     6.6%
  browser_console                    89     5.7%
  search_files                       83     5.4%
  write_file                         79     5.1%
  read_file                          52     3.4%
  skill_manage                       50     3.2%
  browser_navigate                   47     3.0%
  cronjob                            34     2.2%
  memory                             29     1.9%
  browser_vision                      5     0.3%
  session_search                      4     0.3%
  ... and 1 more tools

  🧠 Top Skills
  ────────────────────────────────────────────────────────
  Skill                          Loads   Edits   Last used
  health-data-management            41      48      May 12
  hermes-agent                      12       0      May 13
  cronjob                            9       0      May 13
  google-workspace                   9       0      May 12
  yazio-integration                  7       0      May 12
  github-repo-management             5       0      May 12
  jarvis-routing-policy              3       2      May 13
  github-auth                        3       0      May 12
  gog                                3       0      May 12
  gmail-archive                      3       0      May 12
  Distinct skills: 15  Loads: 102  Edits: 50

  📅 Activity Patterns
  ────────────────────────────────────────────────────────
  Mon  ███             4
  Tue  ███████████████ 17
  Wed  ████            5
  Thu  █               2
  Fri                  0
  Sat                  0
  Sun                  0

  Peak hours: 5AM (4), 9AM (4), 7PM (3), 7AM (2), 11AM (2)
  Active days: 4
  Best streak: 4 consecutive days

  🏆 Notable Sessions
  ────────────────────────────────────────────────────────
  Longest session      21h 54m            (May 13, 20260513_114750_)
  Most messages        346 msgs           (May 12, 20260512_225913_)
  Most tokens          449,873 tokens     (May 12, 20260512_112553_)
  Most tool calls      161 calls          (May 12, 20260512_225913_)

---30d---

  ╔══════════════════════════════════════════════════════════╗
  ║                    📊 Hermes Insights                    ║
  ║                       Last 30 days                       ║
  ╚══════════════════════════════════════════════════════════╝

  Period: May 07, 2026 — May 14, 2026

  📋 Overview
  ────────────────────────────────────────────────────────
  Sessions:          94            Messages:        7,538
  Tool calls:        3,448         User messages:   362
  Input tokens:      6,407,877     Output tokens:   560,089
  Total tokens:      112,479,834
  Active time:       ~6.9d         Avg session:     ~1h 51m
  Avg msgs/session:  80.2

  🤖 Models Used
  ────────────────────────────────────────────────────────
  Model                          Sessions       Tokens
  qwen-3.6-agent                       48   69,405,496
  gpt-5.5                              16   39,769,553
  openrouter                           29    3,304,785
  auto                                  1            0

  📱 Platforms
  ────────────────────────────────────────────────────────
  Platform       Sessions   Messages         Tokens
  telegram             49      7,005    106,347,018
  cron                 43        427      4,024,879
  cli                   2        106      2,107,937

  🔧 Top Tools
  ────────────────────────────────────────────────────────
  Tool                            Calls        %
  execute_code                    1,268    36.8%
  terminal                          692    20.1%
  patch                             239     6.9%
  todo                              216     6.3%
  skill_view                        158     4.6%
  write_file                        153     4.4%
  browser_navigate                  149     4.3%
  search_files                       93     2.7%
  browser_console                    91     2.6%
  read_file                          88     2.6%
  memory                             71     2.1%
  skill_manage                       58     1.7%
  cronjob                            58     1.7%
  browser_snapshot                   23     0.7%
  browser_click                      20     0.6%
  ... and 17 more tools

  🧠 Top Skills
  ────────────────────────────────────────────────────────
  Skill                          Loads   Edits   Last used
  health-data-management            41      52      May 12
  hermes-agent                      14       0      May 13
  cronjob                           11       0      May 13
  google-workspace                  11       0      May 12
  yazio-integration                  7       0      May 12
  gog                                7       0      May 12
  openclaw-imports:gog               6       0      May 09
  openclaw-imports:sherpa-onnx       6       0      May 07
  health-management                  3       3      May 12
  github-repo-management             5       0      May 12
  Distinct skills: 29  Loads: 158  Edits: 58

  📅 Activity Patterns
  ────────────────────────────────────────────────────────
  Mon  █████           8
  Tue  ████████████    17
  Wed  ███             5
  Thu  █████████       13
  Fri  ███████         11
  Sat  █████████████   19
  Sun  ███████████████ 21

  Peak hours: 5AM (9), 9AM (9), 10PM (8), 8PM (7), 11PM (6)
  Active days: 8
  Best streak: 8 consecutive days

  🏆 Notable Sessions
  ────────────────────────────────────────────────────────
  Longest session      21h 54m            (May 13, 20260513_114750_)
  Most messages        346 msgs           (May 12, 20260512_225913_)
  Most tokens          449,873 tokens     (May 12, 20260512_112553_)
  Most tool calls      161 calls          (May 12, 20260512_225913_)


terminal

Output:
URL https://hermes-agent.nousresearch.com/docs/search?q=compression
 Search the documentation Skip to main content Hermes Agent Docs Skills English English 简体中文 Home GitHub Discord Search the documentation Docs Getting Started User Guide Developer Guide Reference Community Discord GitHub Discussions Skills Hub More GitHub Nous Research Built by Nous Research · MIT License · 2026

URL https://hermes-agent.nousresearch.com/docs/search?q=tokens
 Search the documentation Skip to main content Hermes Agent Docs Skills English English 简体中文 Home GitHub Discord Search the documentation Docs Getting Started User Guide Developer Guide Reference Community Discord GitHub Discussions Skills Hub More GitHub Nous Research Built by Nous Research · MIT License · 2026

URL https://hermes-agent.nousresearch.com/docs/user-guide/features/context-management
ERR HTTP Error 404: Not Found

URL https://hermes-agent.nousresearch.com/docs/user-guide/features/memory
 Persistent Memory | Hermes Agent Skip to main content Hermes Agent Docs Skills English English 简体中文 Home GitHub Discord User Stories & Use Cases Getting Started Using Hermes Features Overview Tool Gateway Core Tools & Toolsets Skills System LSP — Semantic Diagnostics Curator Persistent Memory Memory Providers Context Files Context References Personality & SOUL.md Skins & Themes Plugins Built-in Plugins Automation Media & Web Management Advanced Skills Messaging Platforms Integrations Guides & Tutorials Developer Guide Reference Features Core Persistent Memory On this page Persistent Memory Hermes Agent has bounded, curated memory that persists across sessions. This lets it remember your preferences, your projects, your environment, and things it has learned. How It Works  Two files make up the agent's memory: File Purpose Char Limit MEMORY.md Agent's personal notes — environment facts, conventions, things learned 2,200 chars (~800 tokens) USER.md User profile — your preferences, communication style, expectations 1,375 chars (~500 tokens) Both are stored in ~/.hermes/memories/ and are injected into the system prompt as a frozen snapshot at session start. The agent manages its own memory via the memory tool — it can add, replace, or remove entries. info Character limits keep memory focused. When memory is full, the agent consolidates or replaces entries to make room for new information. How Memory Appears in the System Prompt  At the start of every session, memory entries are loaded from disk and rendered into the system prompt as a frozen block: ══════════════════════════════════════════════ MEMORY (your personal notes) [67% — 1,474/2,200 chars] ══════════════════════════════════════════════ User's project is a Rust web service at ~/code/myapi using Axum + SQLx § This machine runs Ubuntu 22.04, has Docker and Podman installed § User prefers concise responses, dislikes verbose explanations The format includes: A header showing

URL https://hermes-agent.nousresearch.com/docs/user-guide/gateway/telegram
ERR HTTP Error 404: Not Found

URL https://hermes-agent.nousresearch.com/docs/user-guide/messaging/telegram
 Telegram | Hermes Agent Skip to main content Hermes Agent Docs Skills English English 简体中文 Home GitHub Discord User Stories & Use Cases Getting Started Using Hermes Features Messaging Platforms Messaging Gateway Telegram Discord Slack WhatsApp Signal Email SMS (Twilio) Home Assistant Mattermost Matrix DingTalk Feishu / Lark WeCom (Enterprise WeChat) WeCom Callback (Self-Built App) Weixin (WeChat) BlueBubbles (iMessage) QQ Bot Yuanbao Microsoft Teams Teams Meetings Microsoft Graph Webhook Listener LINE Open WebUI Webhooks Integrations Guides & Tutorials Developer Guide Reference Messaging Platforms Telegram On this page Telegram Setup Hermes Agent integrates with Telegram as a full-featured conversational bot. Once connected, you can chat with your agent from any device, send voice memos that get auto-transcribed, receive scheduled task results, and use the agent in group chats. The integration is built on python-telegram-bot and supports text, voice, images, and file attachments. Step 1: Create a Bot via BotFather  Every Telegram bot requires an API token issued by @BotFather , Telegram's official bot management tool. Open Telegram and search for @BotFather , or visit t.me/BotFather Send /newbot Choose a display name (e.g., "Hermes Agent") — this can be anything Choose a username — this must be unique and end in bot (e.g., my_hermes_bot ) BotFather replies with your API token . It looks like this: 123456789:ABCdefGHIjklMNOpqrSTUvwxYZ warning Keep your bot token secret. Anyone with this token can control your bot. If it leaks, revoke it immediately via /revoke in BotFather. Step 2: Customize Your Bot (Optional)  These BotFather commands improve the user experience. Message @BotFather and use: Command Purpose /setdescription The "What can this bot do?" text shown before a user starts chatting /setabouttext Short text on the bot's profile page /setuserpic Upload an avatar for your bot /setcommands Define the command menu (the /


Explanation:
**Setting up SQLite schema**

I'm realizing that I need SQLite for my task. First things first: I need to define the schema to organize my data properly. It's crucial to get the schema right before diving into any database operations. I should think about what tables I need, their columns, and how they'll relate to each other. Starting with a clear plan will help me avoid confusion later on! Alright, let's get this setup going!

python - <<'PY'
import sqlite3, pathlib
p=pathlib.Path.home()/'.hermes/state.db'
con=sqlite3.connect(p)
for row in con.execute("select name, sql from sqlite_master where type='table'"):
 print('\nTABLE',row[0]); print(row[1][:1000])
PY


Output:
TABLE schema_version
CREATE TABLE schema_version (
    version INTEGER NOT NULL
)

TABLE sessions
CREATE TABLE sessions (
    id TEXT PRIMARY KEY,
    source TEXT NOT NULL,
    user_id TEXT,
    model TEXT,
    model_config TEXT,
    system_prompt TEXT,
    parent_session_id TEXT,
    started_at REAL NOT NULL,
    ended_at REAL,
    end_reason TEXT,
    message_count INTEGER DEFAULT 0,
    tool_call_count INTEGER DEFAULT 0,
    input_tokens INTEGER DEFAULT 0,
    output_tokens INTEGER DEFAULT 0,
    cache_read_tokens INTEGER DEFAULT 0,
    cache_write_tokens INTEGER DEFAULT 0,
    reasoning_tokens INTEGER DEFAULT 0,
    billing_provider TEXT,
    billing_base_url TEXT,
    billing_mode TEXT,
    estimated_cost_usd REAL,
    actual_cost_usd REAL,
    cost_status TEXT,
    cost_source TEXT,
    pricing_version TEXT,
    title TEXT,
    api_call_count INTEGER DEFAULT 0, "handoff_state" TEXT, "handoff_platform" TEXT, "handoff_error" TEXT,
    FOREIGN KEY (parent_session_id) REFERENCES sessions(id)
)

TABLE messages
CREATE TABLE messages (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    session_id TEXT NOT NULL REFERENCES sessions(id),
    role TEXT NOT NULL,
    content TEXT,
    tool_call_id TEXT,
    tool_calls TEXT,
    tool_name TEXT,
    timestamp REAL NOT NULL,
    token_count INTEGER,
    finish_reason TEXT,
    reasoning TEXT,
    reasoning_content TEXT,
    reasoning_details TEXT,
    codex_reasoning_items TEXT,
    codex_message_items TEXT
)

TABLE sqlite_sequence
CREATE TABLE sqlite_sequence(name,seq)

TABLE state_meta
CREATE TABLE state_meta (
    key TEXT PRIMARY KEY,
    value TEXT
)

TABLE messages_fts
CREATE VIRTUAL TABLE messages_fts USING fts5(
    content
)

TABLE messages_fts_data
CREATE TABLE 'messages_fts_data'(id INTEGER PRIMARY KEY, block BLOB)

TABLE messages_fts_idx
CREATE TABLE 'messages_fts_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID

TABLE messages_fts_content
CREATE TABLE 'messages_fts_content'(id INTEGER PRIMARY KEY, c0)

TABLE messages_fts_docsize
CREATE TABLE 'messages_fts_docsize'(id INTEGER PRIMARY KEY, sz BLOB)

TABLE messages_fts_config
CREATE TABLE 'messages_fts_config'(k PRIMARY KEY, v) WITHOUT ROWID

TABLE messages_fts_trigram
CREATE VIRTUAL TABLE messages_fts_trigram USING fts5(
    content,
    tokenize='trigram'
)

TABLE messages_fts_trigram_data
CREATE TABLE 'messages_fts_trigram_data'(id INTEGER PRIMARY KEY, block BLOB)

TABLE messages_fts_trigram_idx
CREATE TABLE 'messages_fts_trigram_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID

TABLE messages_fts_trigram_content
CREATE TABLE 'messages_fts_trigram_content'(id INTEGER PRIMARY KEY, c0)

TABLE messages_fts_trigram_docsize
CREATE TABLE 'messages_fts_trigram_docsize'(id INTEGER PRIMARY KEY, sz BLOB)

TABLE messages_fts_trigram_config
CREATE TABLE 'messages_fts_trigram_config'(k PRIMARY KEY, v) WITHOUT ROWID


Explanation:
**Calculating daily stats**

I need to gather daily statistics. I think I'll use an SQL query to group by date. It seems like total tokens could be calculated as input, output, and potential cache reads combined. I'm noticing that the total tokens are much higher than just input plus output, which probably means cache reads are included. So I need to clarify the numbers, especially since total tokens are around 112 million while input is only 6.4 million and output is about 0.56 million. I need to create that query!

python - <<'PY'
import sqlite3, datetime, pathlib
con=sqlite3.connect(pathlib.Path.home()/'.hermes/state.db')
con.row_factory=sqlite3.Row
print('Daily usage (local timezone naive from unix):')
q='''select date(started_at,'unixepoch','localtime') d, count(*) sessions, sum(message_count) msgs, sum(tool_call_count) tools,
 sum(input_tokens) inp, sum(output_tokens) out, sum(cache_read_tokens) cr, sum(cache_write_tokens) cw, sum(reasoning_tokens) rt,
 sum(input_tokens+output_tokens+cache_read_tokens+cache_write_tokens+reasoning_tokens) total
 from sessions group by d order by d'''
for r in con.execute(q):
 print(f"{r['d']} sessions={r['sessions']:2d} msgs={r['msgs'] or 0:4d} tools={r['tools'] or 0:4d} total={r['total'] or 0:10,d} input={r['inp'] or 0:9,d} output={r['out'] or 0:8,d} cache_read={r['cr'] or 0:10,d} cache_write={r['cw'] or 0:8,d} reasoning={r['rt'] or 0:8,d}")
print('\nTop 10 sessions by total tokens:')
q2='''select id, source, model, datetime(started_at,'unixepoch','localtime') st, message_count msgs, tool_call_count tools,
 (input_tokens+output_tokens+cache_read_tokens+cache_write_tokens+reasoning_tokens) total,
 input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, reasoning_tokens, title
 from sessions order by total desc limit 10'''
for r in con.execute(q2):
 print(f"{r['st']} {r['source']} {r['model']} total={r['total']:,} inp={r['input_tokens']:,} out={r['output_tokens']:,} cacheR={r['cache_read_tokens']:,} msgs={r['msgs']} tools={r['tools']} title={r['title']}")
PY


Output:
Daily usage (local timezone naive from unix):
2026-05-07 sessions=11 msgs=1443 tools= 648 total=15,692,296 input=1,057,282 output=  36,703 cache_read=14,598,311 cache_write=       0 reasoning=       0
2026-05-08 sessions=11 msgs=1354 tools= 616 total=18,919,837 input=1,046,209 output= 100,600 cache_read=17,773,028 cache_write=       0 reasoning=       0
2026-05-09 sessions=19 msgs= 564 tools= 254 total= 8,997,319 input=  606,389 output=  72,143 cache_read= 8,318,787 cache_write=       0 reasoning=       0
2026-05-10 sessions=21 msgs= 735 tools= 322 total=12,466,792 input=1,006,459 output=  68,670 cache_read=11,391,663 cache_write=       0 reasoning=       0
2026-05-11 sessions= 8 msgs= 218 tools=  88 total= 4,044,725 input=  182,091 output=  21,140 cache_read= 3,841,494 cache_write=       0 reasoning=       0
2026-05-12 sessions=17 msgs=3039 tools=1437 total=46,614,681 input=1,977,376 output= 228,505 cache_read=44,387,177 cache_write=       0 reasoning=  21,623
2026-05-13 sessions= 5 msgs= 181 tools=  82 total= 5,649,155 input=  481,768 output=  29,530 cache_read= 5,131,776 cache_write=       0 reasoning=   6,081
2026-05-14 sessions= 2 msgs=   4 tools=   1 total=   197,233 input=   56,025 output=   3,511 cache_read=   137,216 cache_write=       0 reasoning=     481

Top 10 sessions by total tokens:
2026-05-12 11:25:53 telegram qwen-3.6-agent total=7,641,194 inp=395,374 out=54,499 cacheR=7,187,236 msgs=147 tools=70 title=Status der Dokumentenprüfung
2026-05-12 20:40:59 telegram gpt-5.5 total=6,050,514 inp=161,931 out=19,843 cacheR=5,867,008 msgs=339 tools=160 title=Status der Dokumentenprüfung #7
2026-05-12 22:59:13 telegram gpt-5.5 total=5,193,158 inp=128,089 out=11,833 cacheR=5,051,392 msgs=346 tools=161 title=Status der Dokumentenprüfung #9
2026-05-12 21:13:21 telegram gpt-5.5 total=5,045,597 inp=231,504 out=18,706 cacheR=4,791,296 msgs=329 tools=153 title=Status der Dokumentenprüfung #8
2026-05-13 07:17:51 telegram gpt-5.5 total=5,021,526 inp=360,299 out=21,540 cacheR=4,635,136 msgs=126 tools=58 title=None
2026-05-07 21:18:06 telegram qwen-3.6-agent total=4,416,923 inp=53,172 out=7,020 cacheR=4,356,731 msgs=216 tools=95 title=Greeting and Offering Assistance #5
2026-05-12 17:18:43 telegram gpt-5.5 total=4,254,776 inp=137,606 out=17,236 cacheR=4,097,536 msgs=305 tools=149 title=Status der Dokumentenprüfung #3
2026-05-11 06:13:59 telegram qwen-3.6-agent total=3,540,931 inp=101,985 out=14,937 cacheR=3,424,009 msgs=137 tools=56 title=Tagebucheintragung für Durchfall und Verdachtsmomente
2026-05-12 16:41:49 telegram gpt-5.5 total=3,497,182 inp=162,249 out=21,893 cacheR=3,311,104 msgs=219 tools=105 title=Status der Dokumentenprüfung #2
2026-05-09 09:40:24 telegram qwen-3.6-agent total=3,319,901 inp=131,749 out=25,570 cacheR=3,162,582 msgs=117 tools=55 title=PARA Obsidian Vault Setup for Health


Explanation:
**Investigating context management**

I'm considering whether topics or multiple channels could reduce context in communication. I want to check if Telegram DM topic sessions are enabled and what the documentation and configuration say. Inspecting the gateway settings might help, so I'll search through the code for more details. This feels a bit technical, but I think getting into the specifics will help me understand better! Let's see what I can find!


     1|# Context Compression and Caching
     2|
     3|Hermes Agent uses a dual compression system and Anthropic prompt caching to
     4|manage context window usage efficiently across long conversations.
     5|
     6|Source files: `agent/context_engine.py` (ABC), `agent/context_compressor.py` (default engine),
     7|`agent/prompt_caching.py`, `gateway/run.py` (session hygiene), `run_agent.py` (search for `_compress_context`)
     8|
     9|
    10|## Pluggable Context Engine
    11|
    12|Context management is built on the `ContextEngine` ABC (`agent/context_engine.py`). The built-in `ContextCompressor` is the default implementation, but plugins can replace it with alternative engines (e.g., Lossless Context Management).
    13|
    14|```yaml
    15|context:
    16|  engine: "compressor"    # default — built-in lossy summarization
    17|  engine: "lcm"           # example — plugin providing lossless context
    18|```
    19|
    20|The engine is responsible for:
    21|- Deciding when compaction should fire (`should_compress()`)
    22|- Performing compaction (`compress()`)
    23|- Optionally exposing tools the agent can call (e.g., `lcm_grep`)
    24|- Tracking token usage from API responses
    25|
    26|Selection is config-driven via `context.engine` in `config.yaml`. The resolution order:
    27|1. Check `plugins/context_engine/<name>/` directory
    28|2. Check general plugin system (`register_context_engine()`)
    29|3. Fall back to built-in `ContextCompressor`
    30|
    31|Plugin engines are **never auto-activated** — the user must explicitly set `context.engine` to the plugin's name. The default `"compressor"` always uses the built-in.
    32|
    33|Configure via `hermes plugins` → Provider Plugins → Context Engine, or edit `config.yaml` directly.
    34|
    35|For building a context engine plugin, see [Context Engine Plugins](/docs/developer-guide/context-engine-plugin).
    36|
    37|## Dual Compression System
    38|
    39|Hermes has two separate compression layers that operate independently:
    40|
    41|```
    42|                     ┌──────────────────────────┐
    43|  Incoming message   │   Gateway Session Hygiene │  Fires at 85% of context
    44|  ─────────────────► │   (pre-agent, rough est.) │  Safety net for large sessions
    45|                     └─────────────┬────────────┘
    46|                                   │
    47|                                   ▼
    48|                     ┌──────────────────────────┐
    49|                     │   Agent ContextCompressor │  Fires at 50% of context (default)
    50|                     │   (in-loop, real tokens)  │  Normal context management
    51|                     └──────────────────────────┘
    52|```
    53|
    54|### 1. Gateway Session Hygiene (85% threshold)
    55|
    56|Located in `gateway/run.py` (search for `Session hygiene: auto-compress`). This is a **safety net** that
    57|runs before the agent processes a message. It prevents API failures when sessions
    58|grow too large between turns (e.g., overnight accumulation in Telegram/Discord).
    59|
    60|- **Threshold**: Fixed at 85% of model context length
    61|- **Token source**: Prefers actual API-reported tokens from last turn; falls back
    62|  to rough character-based estimate (`estimate_messages_tokens_rough`)
    63|- **Fires**: Only when `len(history) >= 4` and compression is enabled
    64|- **Purpose**: Catch sessions that escaped the agent's own compressor
    65|
    66|The gateway hygiene threshold is intentionally higher than the agent's compressor.
    67|Setting it at 50% (same as the agent) caused premature compression on every turn
    68|in long gateway sessions.
    69|
    70|### 2. Agent ContextCompressor (50% threshold, configurable)
    71|
    72|Located in `agent/context_compressor.py`. This is the **primary compression
    73|system** that runs inside the agent's tool loop with access to accurate,
    74|API-reported token counts.
    75|
    76|
    77|## Configuration
    78|
    79|All compression settings are read from `config.yaml` under the `compression` key:
    80|
    81|```yaml
    82|compression:
    83|  enabled: true              # Enable/disable compression (default: true)
    84|  threshold: 0.50            # Fraction of context window (default: 0.50 = 50%)
    85|  target_ratio: 0.20         # How much of threshold to keep as tail (default: 0.20)
    86|  protect_last_n: 20         # Minimum protected tail messages (default: 20)
    87|
    88|# Summarization model/provider configured under auxiliary:
    89|auxiliary:
    90|  compression:
    91|    model: null              # Override model for summaries (default: auto-detect)
    92|    provider: auto           # Provider: "auto", "openrouter", "nous", "main", etc.
    93|    base_url: null           # Custom OpenAI-compatible endpoint
    94|```
    95|
    96|### Parameter Details
    97|
    98|| Parameter | Default | Range | Description |
    99||-----------|---------|-------|-------------|
   100|| `threshold` | `0.50` | 0.0-1.0 | Compression triggers when prompt tokens ≥ `threshold × context_length` |
   101|| `target_ratio` | `0.20` | 0.10-0.80 | Controls tail protection token budget: `threshold_tokens × target_ratio` |
   102|| `protect_last_n` | `20` | ≥1 | Minimum number of recent messages always preserved |
   103|| `protect_first_n` | `3` | (hardcoded) | System prompt + first exchange always preserved |
   104|
   105|### Computed Values (for a 200K context model at defaults)
   106|
   107|```
   108|context_length       = 200,000
   109|threshold_tokens     = 200,000 × 0.50 = 100,000
   110|tail_token_budget    = 100,000 × 0.20 = 20,000
   111|max_summary_tokens   = min(200,000 × 0.05, 12,000) = 10,000
   112|```
   113|
   114|
   115|## Compression Algorithm
   116|
   117|The `ContextCompressor.compress()` method follows a 4-phase algorithm:
   118|
   119|### Phase 1: Prune Old Tool Results (cheap, no LLM call)
   120|
   121|Old tool results (>200 chars) outside the protected tail are replaced with:
   122|```
   123|[Old tool output cleared to save context space]
   124|```
   125|
   126|This is a cheap pre-pass that saves significant tokens from verbose tool
   127|outputs (file contents, terminal output, search results).
   128|
   129|### Phase 2: Determine Boundaries
   130|
   131|```
   132|┌─────────────────────────────────────────────────────────────┐
   133|│  Message list                                               │
   134|│                                                             │
   135|│  [0..2]  ← protect_first_n (system + first exchange)        │
   136|│  [3..N]  ← middle turns → SUMMARIZED                        │
   137|│  [N..end] ← tail (by token budget OR protect_last_n)        │
   138|│                                                             │
   139|└─────────────────────────────────────────────────────────────┘
   140|```
   141|
   142|Tail protection is **token-budget based**: walks backward from the end,
   143|accumulating tokens until the budget is exhausted. Falls back to the fixed
   144|`protect_last_n` count if the budget would protect fewer messages.
   145|
   146|Boundaries are aligned to avoid splitting tool_call/tool_result groups.
   147|The `_align_boundary_backward()` method walks past consecutive tool results
   148|to find the parent assistant message, keeping groups intact.
   149|
   150|### Phase 3: Generate Structured Summary
   151|
   152|:::warning Summary model context length
   153|The summary model must have a context window **at least as large** as the main agent model's. The entire middle section is sent to the summary model in a single `call_llm(task="compression")` call. If the summary model's context is smaller, the API returns a context-length error — `_generate_summary()` catches it, logs a warning, and returns `None`. The compressor then drops the middle turns **without a summary**, silently losing conversation context. This is the most common cause of degraded compaction quality.
   154|:::
   155|
   156|The middle turns are summarized using the auxiliary LLM with a structured
   157|template:
   158|
   159|```
   160|## Goal
   161|[What the user is trying to accomplish]
   162|
   163|## Constraints & Preferences
   164|[User preferences, coding style, constraints, important decisions]
   165|
   166|## Progress
   167|### Done
   168|[Completed work — specific file paths, commands run, results]
   169|### In Progress
   170|[Work currently underway]
   171|### Blocked
   172|[Any blockers or issues encountered]
   173|
   174|## Key Decisions
   175|[Important technical decisions and why]
   176|
   177|## Relevant Files
   178|[Files read, modified, or created — with brief note on each]
   179|
   180|## Next Steps
   181|[What needs to happen next]
   182|
   183|## Critical Context
   184|[Specific values, error messages, configuration details]
   185|```
   186|
   187|Summary budget scales with the amount of content being compressed:
   188|- Formula: `content_tokens × 0.20` (the `_SUMMARY_RATIO` constant)
   189|- Minimum: 2,000 tokens
   190|- Maximum: `min(context_length × 0.05, 12,000)` tokens
   191|
   192|### Phase 4: Assemble Compressed Messages
   193|
   194|The compressed message list is:
   195|1. Head messages (with a note appended to system prompt on first compression)
   196|2. Summary message (role chosen to avoid consecutive same-role violations)
   197|3. Tail messages (unmodified)
   198|
   199|Orphaned tool_call/tool_result pairs are cleaned up by `_sanitize_tool_pairs()`:
   200|- Tool results referencing removed calls → removed
   201|- Tool calls whose results were removed → stub result injected
   202|
   203|### Iterative Re-compression
   204|
   205|On subsequent compressions, the previous summary is passed to the LLM with
   206|instructions to **update** it rather than summarize from scratch. This preserves
   207|information across multiple compactions — items move from "In Progress" to "Done",
   208|new progress is added, and obsolete information is removed.
   209|
   210|The `_previous_summary` field on the compressor instance stores the last summary
   211|text for this purpose.
   212|
   213|
   214|## Before/After Example
   215|
   216|### Before Compression (45 messages, ~95K tokens)
   217|
   218|```
   219|[0] system:    "You are a helpful assistant..." (system prompt)
   220|[1] user:      "Help me set up a FastAPI project"
   221|

Use offset=221 to continue reading (showing 1-220 of 348 lines)


   221|[2] assistant: <tool_call> terminal: mkdir project </tool_call>
   222|[3] tool:      "directory created"
   223|[4] assistant: <tool_call> write_file: main.py </tool_call>
   224|[5] tool:      "file written (2.3KB)"
   225|    ... 30 more turns of file editing, testing, debugging ...
   226|[38] assistant: <tool_call> terminal: pytest </tool_call>
   227|[39] tool:      "8 passed, 2 failed\n..."  (5KB output)
   228|[40] user:      "Fix the failing tests"
   229|[41] assistant: <tool_call> read_file: tests/test_api.py </tool_call>
   230|[42] tool:      "import pytest\n..."  (3KB)
   231|[43] assistant: "I see the issue with the test fixtures..."
   232|[44] user:      "Great, also add error handling"
   233|```
   234|
   235|### After Compression (25 messages, ~45K tokens)
   236|
   237|```
   238|[0] system:    "You are a helpful assistant...
   239|               [Note: Some earlier conversation turns have been compacted...]"
   240|[1] user:      "Help me set up a FastAPI project"
   241|[2] assistant: "[CONTEXT COMPACTION] Earlier turns were compacted...
   242|
   243|               ## Goal
   244|               Set up a FastAPI project with tests and error handling
   245|
   246|               ## Progress
   247|               ### Done
   248|               - Created project structure: main.py, tests/, requirements.txt
   249|               - Implemented 5 API endpoints in main.py
   250|               - Wrote 10 test cases in tests/test_api.py
   251|               - 8/10 tests passing
   252|
   253|               ### In Progress
   254|               - Fixing 2 failing tests (test_create_user, test_delete_user)
   255|
   256|               ## Relevant Files
   257|               - main.py — FastAPI app with 5 endpoints
   258|               - tests/test_api.py — 10 test cases
   259|               - requirements.txt — fastapi, pytest, httpx
   260|
   261|               ## Next Steps
   262|               - Fix failing test fixtures
   263|               - Add error handling"
   264|[3] user:      "Fix the failing tests"
   265|[4] assistant: <tool_call> read_file: tests/test_api.py </tool_call>
   266|[5] tool:      "import pytest\n..."
   267|[6] assistant: "I see the issue with the test fixtures..."
   268|[7] user:      "Great, also add error handling"
   269|```
   270|
   271|
   272|## Prompt Caching (Anthropic)
   273|
   274|Source: `agent/prompt_caching.py`
   275|
   276|Reduces input token costs by ~75% on multi-turn conversations by caching the
   277|conversation prefix. Uses Anthropic's `cache_control` breakpoints.
   278|
   279|### Strategy: system_and_3
   280|
   281|Anthropic allows a maximum of 4 `cache_control` breakpoints per request. Hermes
   282|uses the "system_and_3" strategy:
   283|
   284|```
   285|Breakpoint 1: System prompt           (stable across all turns)
   286|Breakpoint 2: 3rd-to-last non-system message  ─┐
   287|Breakpoint 3: 2nd-to-last non-system message   ├─ Rolling window
   288|Breakpoint 4: Last non-system message          ─┘
   289|```
   290|
   291|### How It Works
   292|
   293|`apply_anthropic_cache_control()` deep-copies the messages and injects
   294|`cache_control` markers:
   295|
   296|```python
   297|# Cache marker format
   298|marker = {"type": "ephemeral"}
   299|# Or for 1-hour TTL:
   300|marker = {"type": "ephemeral", "ttl": "1h"}
   301|```
   302|
   303|The marker is applied differently based on content type:
   304|
   305|| Content Type | Where Marker Goes |
   306||-------------|-------------------|
   307|| String content | Converted to `[{"type": "text", "text": ..., "cache_control": ...}]` |
   308|| List content | Added to the last element's dict |
   309|| None/empty | Added as `msg["cache_control"]` |
   310|| Tool messages | Added as `msg["cache_control"]` (native Anthropic only) |
   311|
   312|### Cache-Aware Design Patterns
   313|
   314|1. **Stable system prompt**: The system prompt is breakpoint 1 and cached across
   315|   all turns. Avoid mutating it mid-conversation (compression appends a note
   316|   only on the first compaction).
   317|
   318|2. **Message ordering matters**: Cache hits require prefix matching. Adding or
   319|   removing messages in the middle invalidates the cache for everything after.
   320|
   321|3. **Compression cache interaction**: After compression, the cache is invalidated
   322|   for the compressed region but the system prompt cache survives. The rolling
   323|   3-message window re-establishes caching within 1-2 turns.
   324|
   325|4. **TTL selection**: Default is `5m` (5 minutes). Use `1h` for long-running
   326|   sessions where the user takes breaks between turns.
   327|
   328|### Enabling Prompt Caching
   329|
   330|Prompt caching is automatically enabled when:
   331|- The model is an Anthropic Claude model (detected by model name)
   332|- The provider supports `cache_control` (native Anthropic API or OpenRouter)
   333|
   334|```yaml
   335|# config.yaml — TTL is configurable (must be "5m" or "1h")
   336|prompt_caching:
   337|  cache_ttl: "5m"
   338|```
   339|
   340|The CLI shows caching status at startup:
   341|```
   342|💾 Prompt caching: ENABLED (Claude via OpenRouter, 5m TTL)
   343|```
   344|
   345|
   346|## Context Pressure Warnings
   347|
   348|Intermediate context-pressure warnings have been removed (see the iteration-budget block in `run_agent.py`, which notes: "No intermediate pressure warnings — they caused models to 'give up' prematurely on complex tasks"). Compression fires when prompt tokens reach the configured `compression.threshold` (default 50%) with no prior warning step; gateway session hygiene fires as the secondary safety net at 85% of the model's context window.
   349|


Explanation:
**Searching for solutions**

I need to find a comprehensive answer, but it seems I might need to check multiple channels. The search code didn’t return any results, possibly due to an issue with gateway/session.py. Should I try using the terminal with rg? The developer suggested using search_files, but that failed. Is the grep pattern not exact? I wonder whether I should use the terminal again, or maybe search for "topic" in the website documentation instead.

Telegram DM topic|DM topic|topic sessions|topics|topic


Explanation:
**Calculating percentages and trends**

I'm looking at recent data and seeing that the numbers fluctuate quite a bit. After a big project, the results seemed lower, although eight days isn't enough to spot a clear trend. In the last three days, the figures reached 52.8M, especially on the 12th. I might need to calculate specific percentages based on user messages. It seems mandatory to execute code for arithmetic to get precise calculations. Let's do that!

python - <<'PY'
# compute summary from queried known db directly
import sqlite3, pathlib
con=sqlite3.connect(pathlib.Path.home()/'.hermes/state.db')
q='''select sum(input_tokens),sum(output_tokens),sum(cache_read_tokens),sum(cache_write_tokens),sum(reasoning_tokens),sum(input_tokens+output_tokens+cache_read_tokens+cache_write_tokens+reasoning_tokens),sum(message_count),sum(tool_call_count),count(*) from sessions'''
inp,out,cr,cw,rt,total,msgs,tools,sess=con.execute(q).fetchone()
print('all', inp,out,cr,cw,rt,total,msgs,tools,sess)
for name,val in [('input',inp),('output',out),('cache_read',cr),('reasoning',rt)]: print(name, round(100*val/total,2))
# last active days averages excluding today? and before/after May12
for label, where in [('May7-12', "date(started_at,'unixepoch','localtime') between '2026-05-07' and '2026-05-12'"), ('May13-14', "date(started_at,'unixepoch','localtime') between '2026-05-13' and '2026-05-14'")]:
 r=con.execute(f'''select count(*),sum(message_count),sum(tool_call_count),sum(input_tokens+output_tokens+cache_read_tokens+cache_write_tokens+reasoning_tokens),sum(input_tokens),sum(output_tokens),sum(cache_read_tokens) from sessions where {where}''').fetchone()
 print(label, r, 'tokens/msg', round(r[3]/r[1],1) if r[1] else None, 'tokens/session', round(r[3]/r[0],1) if r[0] else None)
# sources
for r in con.execute('''select source,count(*),sum(input_tokens+output_tokens+cache_read_tokens+cache_write_tokens+reasoning_tokens) total from sessions group by source order by total desc'''):
 print('source',r)
PY


Output:
all 6424042 562617 105859004 0 28926 112874589 7538 3448 94
input 5.69
output 0.5
cache_read 93.78
reasoning 0.03
May7-12 (87, 7353, 3365, 106735650, 5875806, 527761, 100310460) tokens/msg 14515.9 tokens/session 1226846.6
May13-14 (7, 185, 83, 6138939, 548236, 34856, 5548544) tokens/msg 33183.5 tokens/session 876991.3
source ('telegram', 49, 106741289)
source ('cron', 43, 4025363)
source ('cli', 2, 2107937)


Mein Herr — kurze Antwort: **Ja, Session-Neustarts helfen. Nein, OpenClaw würde ich nicht als Standard reaktivieren. Ja, ich habe Token-Statistiken. Und ja: Hermes lädt nicht automatisch “alles”, aber innerhalb derselben Telegram-Session wächst der Kontext bis zur Compression.**

Ich habe gerade die Hermes-Doku/Repo-Docs und unsere lokale `hermes insights`/SQLite-Statistik geprüft.

## 1. Was du von deiner Seite aus tun kannst

### Beste Hebel

- **Nach abgeschlossenem Thema: `/new` oder Session neu starten**
  - Das ist der effektivste manuelle Hebel.
  - Memory bleibt erhalten, aber die lange Gesprächshistorie fällt weg.
  - Ideal nach: Health-Import abgeschlossen, Coding-Task fertig, Recherche fertig.

- **Für laufende, aber lange Themen: `/compress`**
  - Verdichtet die Session, ohne sie komplett zu vergessen.
  - Gut, wenn du sagst: “Wir sind noch im selben Projekt, aber räum den Kontext auf.”
  - Beispiel: `/compress Fokus: Gesundheitsdashboard und offene Fehler`

- **Themen trennen**
  - Nicht zwingend verschiedene Kanäle, aber verschiedene Sessions/Topics sind sinnvoll.
  - Beispiel:
    - Health
    - Dev/Hermes
    - Kalender/Todoist
    - Research
  - Vorteil: Ich muss nicht den Verlauf vom Health-Dashboard mitschleppen, wenn du nur fragst, ob ich eine Mail zusammenfassen kann. Revolutionär, ich weiss.

- **Bei einfachen Fragen explizit sagen: “kurz, ohne Recherche”**
  - Beispiel: “Kurz einschätzen, keine Tools.”
  - Für aktuelle Daten, Dateien, Systemstatus, Mathe etc. muss ich trotzdem Tools verwenden — aber bei Meinungs-/Planungsfragen reduziert es unnötige Recherche.

- **Keine grossen Rohdaten in Telegram kippen, wenn nicht nötig**
  - Besser:
    - “Nutze Datei X”
    - “Lies nur relevante Abschnitte”
    - “Fasse diese PDF zusammen, speichere Details extern”
  - Grosse Logs, PDFs, Screenshots und Tool-Ausgaben sind der klassische Token-Fresser.

- **Bei grossen Aufgaben: erst Auftrag und Scope klar machen**
  - Gut: “Analysiere nur die neuen Laborwerte seit Datum X.”
  - Teuer: “Schau mal alles an, was wir bisher haben.”

## 2. Brauchen wir verschiedene Kanäle?

**Nicht unbedingt verschiedene Plattform-Kanäle.** Entscheidend ist: **separate Sessions pro Thema**.

In Telegram ist ein frischer Thread/Topic oder `/new` besser als ein endloser Mega-Chat. Ein anderer Kanal bringt nur dann etwas, wenn Hermes dadurch wirklich eine andere Session-Historie verwendet. Der Grundverbrauch durch Systemprompt, Tools und Memory bleibt aber ähnlich.

Mein Vorschlag:

- **Für dich praktisch:** weiter Telegram DM nutzen.
- **Disziplin:** pro grösserem Thema `/new`.
- **Wenn Telegram Topics sauber funktionieren:** Topics nach Domänen nutzen:
  - `Health`
  - `Jarvis/Hermes`
  - `Admin`
  - `Research`
  - `Coding`

## 3. OpenClaw wieder aktivieren?

Meine Empfehlung: **Nein, nicht als Standard.**

Warum:

- OpenClaw würde zwar als separater Worker Kontext isolieren können.
- Aber Hermes hat bereits native Alternativen:
  - `delegate_task` für isolierte Subtasks
  - Cronjobs mit eingeschränkten Toolsets
  - lokale/Qwen-Worker für Zusammenfassung/Extraktion
  - eigene Sessions/Topics
- OpenClaw/Gateway/MCP bringt wieder:
  - zusätzliche Infrastruktur
  - potenzielle Duplikation
  - mehr Routing-Komplexität
  - mehr Risiko, dass Kontext/Dateien/Nontext unklar wandern

**Besserer Ansatz:** Ich nutze bei Bedarf native Hermes-Subagents mit minimalem Kontext und eingeschränkten Toolsets. Also nicht: “Hier, ganzer Chatverlauf.” Sondern: “Extrahiere aus Datei X nur Werte Y und gib JSON zurück.”

OpenClaw nur für Spezialfälle oder wenn du es explizit willst.

## 4. Lädt Hermes weniger Kontext, wenn das Thema es nicht benötigt?

**Teilweise ja — aber mit Grenzen.**

Hermes lädt nicht automatisch alle alten Sessions. Standardmässig kommen rein:

- Systemprompt / Persona / Regeln
- Memory + User Profile
- relevante Projekt-Kontextdateien, wenn im Workdir vorhanden
- Tool-Schemas der aktivierten Tools
- aktuelle Session-Historie
- Skills, wenn passend geladen
- Dateien/Webseiten/Bilder nur, wenn ich sie per Tool abrufe oder sie in der Session hängen

Was **nicht** automatisch geladen wird:

- alle alten Telegram-Chats
- alle Dateien auf der Platte
- komplette Health-Datenbank
- alte PDFs/Bilder, ausser wir greifen darauf zu
- alle Skills vollständig — nur geladene Skills

Aber: **Wenn du in derselben langen Telegram-Session bleibst**, bleibt die Session-Historie relevant, bis Compression greift. Darum ist `/new` so wirksam.

## 5. Unsere Token-Statistik

Ich habe `hermes insights` und die lokale Session-Datenbank geprüft.

### Letzte 14/30 Tage — effektiv seit 7. Mai

- **Sessions:** 94
- **Messages:** 7’538
- **Tool calls:** 3’448
- **Input tokens:** ca. 6.42 Mio.
- **Output tokens:** ca. 0.56 Mio.
- **Total tokens laut Hermes:** ca. 112.9 Mio.
- **Davon Cache-Read:** ca. 105.9 Mio. = **93.78%**

Wichtig: Die 112.9 Mio. sehen brutal aus, aber der grösste Teil ist **cache_read_tokens**. Das sind wiederverwendete Prefix-/Kontext-Tokens und je nach Provider deutlich günstiger bzw. anders behandelt als frische Input Tokens.

### Hauptverbraucher

- **Telegram:** ca. 106.7 Mio. Tokens
- **Cron:** ca. 4.0 Mio.
- **CLI:** ca. 2.1 Mio.

### Modelle

- `qwen-3.6-agent`: ca. 69.4 Mio.
- `gpt-5.5`: ca. 39.8 Mio.
- `openrouter`: ca. 3.3 Mio.

### Auffälligster Tag

- **12. Mai:** ca. 46.6 Mio. Tokens
  Das war der grosse Health-/Dokumentenprüfungs-Block mit sehr vielen Toolcalls und langen Sessions.

### Seitdem?

- **13. Mai:** ca. 5.65 Mio.
- **14. Mai bisher:** ca. 0.20 Mio.

Also: **Ja, nach dem grossen Health-Block sind wir deutlich sparsamer unterwegs.** Aber die Datenbasis ist noch kurz; ein echter Trend braucht ein paar weitere Tage.

## 6. Konkreter Sparplan

Ich würde es so machen:

1. **Du nutzt `/new` nach jedem abgeschlossenen Thema.**
2. **Ich komprimiere lange Sessions früher**, wenn ein Thema weiterläuft.
3. **Ich nutze Subagents/Worker nur mit kleinem Auftrag**, nicht mit vollem Chatverlauf.
4. **OpenClaw bleibt deaktiviert**, ausser du willst explizit einen Speziallauf.
5. **Health-/Datenjobs laufen möglichst script-first oder cron `no_agent=True`**, wenn nur deterministische Daten gesammelt werden.
6. **Memory bleibt knapp.** Unsere Memory ist bei ca. 94%; ich sollte sie nicht weiter vollstopfen.
7. **Für neue grosse Aufgaben:** erst Mini-Briefing, dann Toolarbeit. Nicht “alles nochmal lesen”.

## Meine Empfehlung

**Keine OpenClaw-Reaktivierung.**
**Ja zu mehr Session-Hygiene:** `/new`, Topics/Sessions nach Thema, `/compress` bei langen Arbeitssträngen.

Wenn du willst, kann ich als nächsten Schritt unsere Hermes-Konfiguration gezielt auf Token-Sparen prüfen und dir eine kleine “Safe config change”-Liste geben — z.B. Compression-Parameter, Toolset-Reduktion, Cronjobs, Memory-Limits und Topic-Setup.

Explanation:
**Improving context management**

I'm thinking that if the local Qwen context is smaller than GPT-5.5, I might lose important context. It seems like Qwen via Tailscale could be operating with a 3.6 agent context, but I'm not completely sure about that.

To ensure consistency in deterministic jobs like morning briefings, I should use cron no_agent scripts. When asking questions, I’ll provide short context explicitly instead of relying on past references and will attach only relevant files or images. For simple, non-current questions, I might request, "nur kurz, keine Recherche, keine Tools."


Ja gerne


hermes-agent

---
name: hermes-agent
description: "Configure, extend, or contribute to Hermes Agent."
version: 2.1.0
author: Hermes Agent + Teknium
license: MIT
metadata:
  hermes:
    tags: [hermes, setup, configuration, multi-agent, spawning, cli, gateway, development]
    homepage: https://github.com/NousResearch/hermes-agent
    related_skills: [claude-code, codex, opencode]
---

# Hermes Agent

Hermes Agent is an open-source AI agent framework by Nous Research that runs in your terminal, messaging platforms, and IDEs. It belongs to the same category as Claude Code (Anthropic), Codex (OpenAI), and OpenClaw — autonomous coding and task-execution agents that use tool calling to interact with your system. Hermes works with any LLM provider (OpenRouter, Anthropic, OpenAI, DeepSeek, local models, and 15+ others) and runs on Linux, macOS, and WSL.

What makes Hermes different:

- **Self-improving through skills** — Hermes learns from experience by saving reusable procedures as skills. When it solves a complex problem, discovers a workflow, or gets corrected, it can persist that knowledge as a skill document that loads into future sessions. Skills accumulate over time, making the agent better at your specific tasks and environment.
- **Persistent memory across sessions** — remembers who you are, your preferences, environment details, and lessons learned. Pluggable memory backends (built-in, Honcho, Mem0, and more) let you choose how memory works.
- **Multi-platform gateway** — the same agent runs on Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Email, and 10+ other platforms with full tool access, not just chat.
- **Provider-agnostic** — swap models and providers mid-workflow without changing anything else. Credential pools rotate across multiple API keys automatically.
- **Profiles** — run multiple independent Hermes instances with isolated configs, sessions, skills, and memory.
- **Extensible** — plugins, MCP servers, custom tools, webhook triggers, cron scheduling, and the full Python ecosystem.

People use Hermes for software development, research, system administration, data analysis, content creation, home automation, and anything else that benefits from an AI agent with persistent context and full system access.

**This skill helps you work with Hermes Agent effectively** — setting it up, configuring features, spawning additional agent instances, troubleshooting issues, finding the right commands and settings, and understanding how the system works when you need to extend or contribute to it.

**Docs:** https://hermes-agent.nousresearch.com/docs/

## Quick Start

```bash
# Install
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

# Interactive chat (default)
hermes

# Single query
hermes chat -q "What is the capital of France?"

# Setup wizard
hermes setup

# Change model/provider
hermes model

# Check health
hermes doctor
```

---

## CLI Reference

### Global Flags

```
hermes [flags] [command]

  --version, -V             Show version
  --resume, -r SESSION      Resume session by ID or title
  --continue, -c [NAME]     Resume by name, or most recent session
  --worktree, -w            Isolated git worktree mode (parallel agents)
  --skills, -s SKILL        Preload skills (comma-separate or repeat)
  --profile, -p NAME        Use a named profile
  --yolo                    Skip dangerous command approval
  --pass-session-id         Include session ID in system prompt
```

No subcommand defaults to `chat`.

### Chat

```
hermes chat [flags]
  -q, --query TEXT          Single query, non-interactive
  -m, --model MODEL         Model (e.g. anthropic/claude-sonnet-4)
  -t, --toolsets LIST       Comma-separated toolsets
  --provider PROVIDER       Force provider (openrouter, anthropic, nous, etc.)
  -v, --verbose             Verbose output
  -Q, --quiet               Suppress banner, spinner, tool previews
  --checkpoints             Enable filesystem checkpoints (/rollback)
  --source TAG              Session source tag (default: cli)
```

### Configuration

```
hermes setup [section]      Interactive wizard (model|terminal|gateway|tools|agent)
hermes model                Interactive model/provider picker
hermes config               View current config
hermes config edit          Open config.yaml in $EDITOR
hermes config set KEY VAL   Set a config value
hermes config path          Print config.yaml path
hermes config env-path      Print .env path
hermes config check         Check for missing/outdated config
hermes config migrate       Update config with new options
hermes login [--provider P] OAuth login (nous, openai-codex)
hermes logout               Clear stored auth
hermes doctor [--fix]       Check dependencies and config
hermes status [--all]       Show component status
```

### Tools & Skills

```
hermes tools                Interactive tool enable/disable (curses UI)
hermes tools list           Show all tools and status
hermes tools enable NAME    Enable a toolset
hermes tools disable NAME   Disable a toolset

hermes skills list          List installed skills
hermes skills search QUERY  Search the skills hub
hermes skills install ID    Install a skill (ID can be a hub identifier OR a direct https://…/SKILL.md URL; pass --name to override when frontmatter has no name)
hermes skills inspect ID    Preview without installing
hermes skills config        Enable/disable skills per platform
hermes skills check         Check for updates
hermes skills update        Update outdated skills
hermes skills uninstall N   Remove a hub skill
hermes skills publish PATH  Publish to registry
hermes skills browse        Browse all available skills
hermes skills tap add REPO  Add a GitHub repo as skill source
```

### MCP Servers

```
hermes mcp serve            Run Hermes as an MCP server
hermes mcp add NAME         Add an MCP server (--url or --command)
hermes mcp remove NAME      Remove an MCP server
hermes mcp list             List configured servers
hermes mcp test NAME        Test connection
hermes mcp configure NAME   Toggle tool selection
```

### Gateway (Messaging Platforms)

```
hermes gateway run          Start gateway foreground
hermes gateway install      Install as background service
hermes gateway start/stop   Control the service
hermes gateway restart      Restart the service
hermes gateway status       Check status
hermes gateway setup        Configure platforms
```

Supported platforms: Telegram, Discord, Slack, WhatsApp, Signal, Email, SMS, Matrix, Mattermost, Home Assistant, DingTalk, Feishu, WeCom, BlueBubbles (iMessage), Weixin (WeChat), API Server, Webhooks. Open WebUI connects via the API Server adapter.

Platform docs: https://hermes-agent.nousresearch.com/docs/user-guide/messaging/

**Telegram setup:** See `references/telegram-gateway-setup.md` for the complete step-by-step configuration workflow.

### Sessions

```
hermes sessions list        List recent sessions
hermes sessions browse      Interactive picker
hermes sessions export OUT  Export to JSONL
hermes sessions rename ID T Rename a session
hermes sessions delete ID   Delete a session
hermes sessions prune       Clean up old sessions (--older-than N days)
hermes sessions stats       Session store statistics
```

### Cron Jobs

```
hermes cron list            List jobs (--all for disabled)
hermes cron create SCHED    Create: '30m', 'every 2h', '0 9 * * *'
hermes cron edit ID         Edit schedule, prompt, delivery
hermes cron pause/resume ID Control job state
hermes cron run ID          Trigger on next tick
hermes cron remove ID       Delete a job
hermes cron status          Scheduler status
```

### Webhooks

```
hermes webhook subscribe N  Create route at /webhooks/<name>
hermes webhook list         List subscriptions
hermes webhook remove NAME  Remove a subscription
hermes webhook test NAME    Send a test POST
```

### Profiles

```
hermes profile list         List all profiles
hermes profile create NAME  Create (--clone, --clone-all, --clone-from)
hermes profile use NAME     Set sticky default
hermes profile delete NAME  Delete a profile
hermes profile show NAME    Show details
hermes profile alias NAME   Manage wrapper scripts
hermes profile rename A B   Rename a profile
hermes profile export NAME  Export to tar.gz
hermes profile import FILE  Import from archive
```

### Credential Pools

```
hermes auth add             Interactive credential wizard
hermes auth list [PROVIDER] List pooled credentials
hermes auth remove P INDEX  Remove by provider + index
hermes auth reset PROVIDER  Clear exhaustion status
```

### Other

```
hermes insights [--days N]  Usage analytics
hermes update               Update to latest version
hermes pairing list/approve/revoke  DM authorization
hermes plugins list/install/remove  Plugin management
hermes honcho setup/status  Honcho memory integration (requires honcho plugin)
hermes memory setup/status/off  Memory provider config
hermes completion bash|zsh  Shell completions
hermes acp                  ACP server (IDE integration)
hermes claw migrate         Migrate from OpenClaw
hermes uninstall            Uninstall Hermes
```

---

## Slash Commands (In-Session)

Type these during an interactive chat session. New commands land fairly
often; if something below looks stale, run `/help` in-session for the
authoritative list or see the [live slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands).
The registry of record is `hermes_cli/commands.py` — every consumer
(autocomplete, Telegram menu, Slack mapping, `/help`) derives from it.

### Session Control
```
/new (/reset)        Fresh session
/clear               Clear screen + new session (CLI)
/retry               Resend last message
/undo                Remove last exchange
/title [name]        Name the session
/compress            Manually compress context
/stop                Kill background processes
/rollback [N]        Restore filesystem checkpoint
/snapshot [sub]      Create or restore state snapshots of Hermes config/state (CLI)
/background <prompt> Run prompt in background
/queue <prompt>      Queue for next turn
/steer <prompt>      Inject a message after the next tool call without interrupting
/agents (/tasks)     Show active agents and running tasks
/resume [name]       Resume a named session
/goal [text|sub]     Set a standing goal Hermes works on across turns until achieved
                     (subcommands: status, pause, resume, clear)
/redraw              Force a full UI repaint (CLI)
```

### Configuration
```
/config              Show config (CLI)
/model [name]        Show or change model
/personality [name]  Set personality
/reasoning [level]   Set reasoning (none|minimal|low|medium|high|xhigh|show|hide)
/verbose             Cycle: off → new → all → verbose
/voice [on|off|tts]  Voice mode
/yolo                Toggle approval bypass
/busy [sub]          Control what Enter does while Hermes is working (CLI)
                     (subcommands: queue, steer, interrupt, status)
/indicator [style]   Pick the TUI busy-indicator style (CLI)
                     (styles: kaomoji, emoji, unicode, ascii)
/footer [on|off]     Toggle gateway runtime-metadata footer on final replies
/skin [name]         Change theme (CLI)
/statusbar           Toggle status bar (CLI)
```

### Tools & Skills
```
/tools               Manage tools (CLI)
/toolsets            List toolsets (CLI)
/skills              Search/install skills (CLI)
/skill <name>        Load a skill into session
/reload-skills       Re-scan ~/.hermes/skills/ for added/removed skills
/reload              Reload .env variables into the running session (CLI)
/reload-mcp          Reload MCP servers
/cron                Manage cron jobs (CLI)
/curator [sub]       Background skill maintenance (status, run, pin, archive, …)
/kanban [sub]        Multi-profile collaboration board (tasks, links, comments)
/plugins             List plugins (CLI)
```

### Gateway
```
/approve             Approve a pending command (gateway)
/deny                Deny a pending command (gateway)
/restart             Restart gateway (gateway)
/sethome             Set current chat as home channel (gateway)
/update              Update Hermes to latest (gateway)
/topic [sub]         Enable or inspect Telegram DM topic sessions (gateway)
/platforms (/gateway) Show platform connection status (gateway)
```

### Utility
```
/branch (/fork)      Branch the current session
/fast                Toggle priority/fast processing
/browser             Open CDP browser connection
/history             Show conversation history (CLI)
/save                Save conversation to file (CLI)
/copy [N]            Copy the last assistant response to clipboard (CLI)
/paste               Attach clipboard image (CLI)
/image               Attach local image file (CLI)
```

### Info
```
/help                Show commands
/commands [page]     Browse all commands (gateway)
/usage               Token usage
/insights [days]     Usage analytics
/gquota              Show Google Gemini Code Assist quota usage (CLI)
/status              Session info (gateway)
/profile             Active profile info
/debug               Upload debug report (system info + logs) and get shareable links
```

### Exit
```
/quit (/exit, /q)    Exit CLI
```

---

## Key Paths & Config

```
~/.hermes/config.yaml       Main configuration
~/.hermes/.env              API keys and secrets
$HERMES_HOME/skills/        Installed skills
~/.hermes/sessions/         Session transcripts
~/.hermes/logs/             Gateway and error logs
~/.hermes/auth.json         OAuth tokens and credential pools
~/.hermes/hermes-agent/     Source code (if git-installed)
```

Profiles use `~/.hermes/profiles/<name>/` with the same layout.

### Config Sections

Edit with `hermes config edit` or `hermes config set section.key value`.

| Section | Key options |
|---------|-------------|
| `model` | `default`, `provider`, `base_url`, `api_key`, `context_length` |
| `agent` | `max_turns` (90), `tool_use_enforcement` |
| `terminal` | `backend` (local/docker/ssh/modal), `cwd`, `timeout` (180) |
| `compression` | `enabled`, `threshold` (0.50), `target_ratio` (0.20) |
| `display` | `skin`, `tool_progress`, `show_reasoning`, `show_cost` |
| `stt` | `enabled`, `provider` (local/groq/openai/mistral) |
| `tts` | `provider` (edge/elevenlabs/openai/minimax/mistral/neutts) |
| `memory` | `memory_enabled`, `user_profile_enabled`, `provider` |
| `security` | `tirith_enabled`, `website_blocklist` |
| `delegation` | `model`, `provider`, `base_url`, `api_key`, `max_iterations` (50), `reasoning_effort` |
| `checkpoints` | `enabled`, `max_snapshots` (50) |

Full config reference: https://hermes-agent.nousresearch.com/docs/user-guide/configuration

### Providers

20+ providers supported. Set via `hermes model` or `hermes setup`.

| Provider | Auth | Key env var |
|----------|------|-------------|
| OpenRouter | API key | `OPENROUTER_API_KEY` |
| Anthropic | API key | `ANTHROPIC_API_KEY` |
| Nous Portal | OAuth | `hermes auth` |
| OpenAI Codex | OAuth | `hermes auth` |
| GitHub Copilot | Token | `COPILOT_GITHUB_TOKEN` |
| Google Gemini | API key | `GOOGLE_API_KEY` or `GEMINI_API_KEY` |
| DeepSeek | API key | `DEEPSEEK_API_KEY` |
| xAI / Grok | API key | `XAI_API_KEY` |
| Hugging Face | Token | `HF_TOKEN` |
| Z.AI / GLM | API key | `GLM_API_KEY` |
| MiniMax | API key | `MINIMAX_API_KEY` |
| MiniMax CN | API key | `MINIMAX_CN_API_KEY` |
| Kimi / Moonshot | API key | `KIMI_API_KEY` |
| Alibaba / DashScope | API key | `DASHSCOPE_API_KEY` |
| Xiaomi MiMo | API key | `XIAOMI_API_KEY` |
| Kilo Code | API key | `KILOCODE_API_KEY` |
| AI Gateway (Vercel) | API key | `AI_GATEWAY_API_KEY` |
| OpenCode Zen | API key | `OPENCODE_ZEN_API_KEY` |
| OpenCode Go | API key | `OPENCODE_GO_API_KEY` |
| Qwen OAuth | OAuth | `hermes login --provider qwen-oauth` |
| Custom endpoint | Config | `model.base_url` + `model.api_key` in config.yaml |
| GitHub Copilot ACP | External | `COPILOT_CLI_PATH` or Copilot CLI |

Full provider docs: https://hermes-agent.nousresearch.com/docs/integrations/providers

### Toolsets

Enable/disable via `hermes tools` (interactive) or `hermes tools enable/disable NAME`.

| Toolset | What it provides |
|---------|-----------------|
| `web` | Web search and content extraction |
| `search` | Web search only (subset of `web`) |
| `browser` | Browser automation (Browserbase, Camofox, or local Chromium) |
| `terminal` | Shell commands and process management |
| `file` | File read/write/search/patch |
| `code_execution` | Sandboxed Python execution |
| `vision` | Image analysis |
| `image_gen` | AI image generation |
| `video` | Video analysis and generation |
| `tts` | Text-to-speech |
| `skills` | Skill browsing and management |
| `memory` | Persistent cross-session memory |
| `session_search` | Search past conversations |
| `delegation` | Subagent task delegation |
| `cronjob` | Scheduled task management |
| `clarify` | Ask user clarifying questions |
| `messaging` | Cross-platform message sending |
| `todo` | In-session task planning and tracking |
| `kanban` | Multi-agent work-queue tools (gated to workers) |
| `debugging` | Extra introspection/debug tools (off by default) |
| `safe` | Minimal, low-risk toolset for locked-down sessions |
| `spotify` | Spotify playback and playlist control |
| `homeassistant` | Smart home control (off by default) |
| `discord` | Discord integration tools |
| `discord_admin` | Discord admin/moderation tools |
| `feishu_doc` | Feishu (Lark) document tools |
| `feishu_drive` | Feishu (Lark) drive tools |
| `yuanbao` | Yuanbao integration tools |
| `rl` | Reinforcement learning tools (off by default) |
| `moa` | Mixture of Agents (off by default) |

Full enumeration lives in `toolsets.py` as the `TOOLSETS` dict; `_HERMES_CORE_TOOLS` is the default bundle most platforms inherit from.

Tool changes take effect on `/reset` (new session). They do NOT apply mid-conversation to preserve prompt caching.

---

## Security & Privacy Toggles

Common "why is Hermes doing X to my output / tool calls / commands?" toggles — and the exact commands to change them. Most of these need a fresh session (`/reset` in chat, or start a new `hermes` invocation) because they're read once at startup.

### Secret redaction in tool output

Secret redaction is **off by default** — tool output (terminal stdout, `read_file`, web content, subagent summaries, etc.) passes through unmodified. If the user wants Hermes to auto-mask strings that look like API keys, tokens, and secrets before they enter the conversation context and logs:

```bash
hermes config set security.redact_secrets true       # enable globally
```

**Restart required.** `security.redact_secrets` is snapshotted at import time — toggling it mid-session (e.g. via `export HERMES_REDACT_SECRETS=true` from a tool call) will NOT take effect for the running process. Tell the user to run `hermes config set security.redact_secrets true` in a terminal, then start a new session. This is deliberate — it prevents an LLM from flipping the toggle on itself mid-task.

Disable again with:
```bash
hermes config set security.redact_secrets false
```

### PII redaction in gateway messages

Separate from secret redaction. When enabled, the gateway hashes user IDs and strips phone numbers from the session context before it reaches the model:

```bash
hermes config set privacy.redact_pii true    # enable
hermes config set privacy.redact_pii false   # disable (default)
```

### Command approval prompts

By default (`approvals.mode: manual`), Hermes prompts the user before running shell commands flagged as destructive (`rm -rf`, `git reset --hard`, etc.). The modes are:

- `manual` — always prompt (default)
- `smart` — use an auxiliary LLM to auto-approve low-risk commands, prompt on high-risk
- `off` — skip all approval prompts (equivalent to `--yolo`)

```bash
hermes config set approvals.mode smart       # recommended middle ground
hermes config set approvals.mode off         # bypass everything (not recommended)
```

Per-invocation bypass without changing config:
- `hermes --yolo …`
- `export HERMES_YOLO_MODE=1`

Note: YOLO / `approvals.mode: off` does NOT turn off secret redaction. They are independent.

### Shell hooks allowlist

Some shell-hook integrations require explicit allowlisting before they fire. Managed via `~/.hermes/shell-hooks-allowlist.json` — prompted interactively the first time a hook wants to run.

### Disabling the web/browser/image-gen tools

To keep the model away from network or media tools entirely, open `hermes tools` and toggle per-platform. Takes effect on next session (`/reset`). See the Tools & Skills section above.

---

### Voice & Transcription

### STT (Voice → Text)

Voice messages from messaging platforms are auto-transcribed.

**⚠ Pitfall: faster-whisper must be installed for local STT to work.** The config may show `provider: local` but if `faster-whisper` is not installed in the venv, STT silently fails. Always verify with `pip show faster-whisper` after configuring local STT.

Provider priority (auto-detected):
1. **Local faster-whisper** — free, no API key: `pip install faster-whisper`
2. **Groq Whisper** — free tier: set `GROQ_API_KEY`
3. **OpenAI Whisper** — paid: set `VOICE_TOOLS_OPENAI_KEY`
4. **Mistral Voxtral** — set `MISTRAL_API_KEY`

Config:
```yaml
stt:
  enabled: true
  provider: local        # local, groq, openai, mistral
  local:
    model: small         # tiny, base, small, medium, large-v3 — use 'small' or higher for German
    language: de         # always set explicitly for German — auto-detect is unreliable
```

### Pitfalls
- **faster-whisper must be installed** — config shows `provider: local` but STT silently fails if the package is missing
- **Use `small` model minimum for German** — `base` is too weak
- **Set `language: de` explicitly** — auto-detect is unreliable
- **Swiss German (dialect) is NOT supported** — Whisper transcribes dialect poorly; user should speak Standard German

### TTS (Text → Voice)

| Provider | Env var | Free? |
|----------|---------|-------|
| Edge TTS | None | Yes (default) |
| ElevenLabs | `ELEVENLABS_API_KEY` | Free tier |
| OpenAI | `VOICE_TOOLS_OPENAI_KEY` | Paid |
| MiniMax | `MINIMAX_API_KEY` | Paid |
| Mistral (Voxtral) | `MISTRAL_API_KEY` | Paid |
| NeuTTS (local) | None (`pip install neutts[all]` + `espeak-ng`) | Free |

Voice commands: `/voice on` (voice-to-voice), `/voice tts` (always voice), `/voice off`.

---

## Spawning Additional Hermes Instances

Run additional Hermes processes as fully independent subprocesses — separate sessions, tools, and environments.

### When to Use This vs delegate_task

| | `delegate_task` | Spawning `hermes` process |
|-|-----------------|--------------------------|
| Isolation | Separate conversation, shared process | Fully independent process |
| Duration | Minutes (bounded by parent loop) | Hours/days |
| Tool access | Subset of parent's tools | Full tool access |
| Interactive | No | Yes (PTY mode) |
| Use case | Quick parallel subtasks | Long autonomous missions |

### One-Shot Mode

```
terminal(command="hermes chat -q 'Research GRPO papers and write summary to ~/research/grpo.md'", timeout=300)

# Background for long tasks:
terminal(command="hermes chat -q 'Set up CI/CD for ~/myapp'", background=true)
```

### Interactive PTY Mode (via tmux)

Hermes uses prompt_toolkit, which requires a real terminal. Use tmux for interactive spawning:

```
# Start
terminal(command="tmux new-session -d -s agent1 -x 120 -y 40 'hermes'", timeout=10)

# Wait for startup, then send a message
terminal(command="sleep 8 && tmux send-keys -t agent1 'Build a FastAPI auth service' Enter", timeout=15)

# Read output
terminal(command="sleep 20 && tmux capture-pane -t agent1 -p", timeout=5)

# Send follow-up
terminal(command="tmux send-keys -t agent1 'Add rate limiting middleware' Enter", timeout=5)

# Exit
terminal(command="tmux send-keys -t agent1 '/exit' Enter && sleep 2 && tmux kill-session -t agent1", timeout=10)
```

### Multi-Agent Coordination

```
# Agent A: backend
terminal(command="tmux new-session -d -s backend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t backend 'Build REST API for user management' Enter", timeout=15)

# Agent B: frontend
terminal(command="tmux new-session -d -s frontend -x 120 -y 40 'hermes -w'", timeout=10)
terminal(command="sleep 8 && tmux send-keys -t frontend 'Build React dashboard for user management' Enter", timeout=15)

# Check progress, relay context between them
terminal(command="tmux capture-pane -t backend -p | tail -30", timeout=5)
terminal(command="tmux send-keys -t frontend 'Here is the API schema from the backend agent: ...' Enter", timeout=5)
```

### Session Resume

```
# Resume most recent session
terminal(command="tmux new-session -d -s resumed 'hermes --continue'", timeout=10)

# Resume specific session
terminal(command="tmux new-session -d -s resumed 'hermes --resume 20260225_143052_a1b2c3'", timeout=10)
```

### Tips

- **Prefer `delegate_task` for quick subtasks** — less overhead than spawning a full process
- **Use `-w` (worktree mode)** when spawning agents that edit code — prevents git conflicts
- **Set timeouts** for one-shot mode — complex tasks can take 5-10 minutes
- **Use `hermes chat -q` for fire-and-forget** — no PTY needed
- **Use tmux for interactive sessions** — raw PTY mode has `\r` vs `\n` issues with prompt_toolkit
- **For scheduled tasks**, use the `cronjob` tool instead of spawning — handles delivery and retry

---

## Durable & Background Systems

Four systems run alongside the main conversation loop. Quick reference
here; full developer notes live in `AGENTS.md`, user-facing docs under
`website/docs/user-guide/features/`.

### Delegation (`delegate_task`)

Synchronous subagent spawn — the parent waits for the child's summary
before continuing its own loop. Isolated context + terminal session.

- **Single:** `delegate_task(goal, context, toolsets)`.
- **Batch:** `delegate_task(tasks=[{goal, ...}, ...])` runs children in
  parallel, capped by `delegation.max_concurrent_children` (default 3).
- **Roles:** `leaf` (default; cannot re-delegate) vs `orchestrator`
  (can spawn its own workers, bounded by `delegation.max_spawn_depth`).
- **Not durable.** If the parent is interrupted, the child is
  cancelled. For work that must outlive the turn, use `cronjob` or
  `terminal(background=True, notify_on_complete=True)`.

Config: `delegation.*` in `config.yaml`.

### Cron (scheduled jobs)

Durable scheduler — `cron/jobs.py` + `cron/scheduler.py`. Drive it via
the `cronjob` tool, the `hermes cron` CLI (`list`, `add`, `edit`,
`pause`, `resume`, `run`, `remove`), or the `/cron` slash command.

- **Schedules:** duration (`"30m"`, `"2h"`), "every" phrase
  (`"every monday 9am"`), 5-field cron (`"0 9 * * *"`), or ISO timestamp.
- **Per-job knobs:** `skills`, `model`/`provider` override, `script`
  (pre-run data collection; `no_agent=True` makes the script the whole
  job), `context_from` (chain job A's output into job B), `workdir`
  (run in a specific dir with its `AGENTS.md` / `CLAUDE.md` loaded),
  multi-platform delivery.
- **Invariants:** 3-minute hard interrupt per run, `.tick.lock` file
  prevents duplicate ticks across processes, cron sessions pass
  `skip_memory=True` by default, and cron deliveries are framed with a
  header/footer instead of being mirrored into the target gateway
  session (keeps role alternation intact).

User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/cron

### Curator (skill lifecycle)

Background maintenance for agent-created skills. Tracks usage, marks
idle skills stale, archives stale ones, keeps a pre-run tar.gz backup
so nothing is lost.

- **CLI:** `hermes curator <verb>` — `status`, `run`, `pause`, `resume`,
  `pin`, `unpin`, `archive`, `restore`, `prune`, `backup`, `rollback`.
- **Slash:** `/curator <subcommand>` mirrors the CLI.
- **Scope:** only touches skills with `created_by: "agent"` provenance.
  Bundled + hub-installed skills are off-limits. **Never deletes** —
  max destructive action is archive. Pinned skills are exempt from
  every auto-transition and every LLM review pass.
- **Telemetry:** sidecar at `~/.hermes/skills/.usage.json` holds
  per-skill `use_count`, `view_count`, `patch_count`,
  `last_activity_at`, `state`, `pinned`.

Config: `curator.*` (`enabled`, `interval_hours`, `min_idle_hours`,
`stale_after_days`, `archive_after_days`, `backup.*`).
User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/curator

### Kanban (multi-agent work queue)

Durable SQLite board for multi-profile / multi-worker collaboration.
Users drive it via `hermes kanban <verb>`; dispatcher-spawned workers
see a focused `kanban_*` toolset gated by `HERMES_KANBAN_TASK` so the
schema footprint is zero outside worker processes.

- **CLI verbs (common):** `init`, `create`, `list` (alias `ls`),
  `show`, `assign`, `link`, `unlink`, `comment`, `complete`, `block`,
  `unblock`, `archive`, `tail`. Less common: `watch`, `stats`, `runs`,
  `log`, `dispatch`, `daemon`, `gc`.
- **Worker toolset:** `kanban_show`, `kanban_complete`, `kanban_block`,
  `kanban_heartbeat`, `kanban_comment`, `kanban_create`, `kanban_link`.
- **Dispatcher** runs inside the gateway by default
  (`kanban.dispatch_in_gateway: true`) — reclaims stale claims,
  promotes ready tasks, atomically claims, spawns assigned profiles.
  Auto-blocks a task after ~5 consecutive spawn failures.
- **Isolation:** board is the hard boundary (workers get
  `HERMES_KANBAN_BOARD` pinned in env); tenant is a soft namespace
  within a board for workspace-path + memory-key isolation.

User docs: https://hermes-agent.nousresearch.com/docs/user-guide/features/kanban

---

## Troubleshooting

### Voice not working
1. Check `stt.enabled: true` in config.yaml
2. Verify provider: `pip install faster-whisper` or set API key
3. In gateway: `/restart`. In CLI: exit and relaunch.

### Tool not available
1. `hermes tools` — check if toolset is enabled for your platform
2. Some tools need env vars (check `.env`)
3. `/reset` after enabling tools

### Model/provider issues
1. `hermes doctor` — check config and dependencies
2. `hermes login` — re-authenticate OAuth providers
3. Check `.env` has the right API key
4. **Copilot 403**: `gh auth login` tokens do NOT work for Copilot API. You must use the Copilot-specific OAuth device code flow via `hermes model` → GitHub Copilot.

### Changes not taking effect
- **Tools/skills:** `/reset` starts a new session with updated toolset
- **Config changes:** In gateway: `/restart`. In CLI: exit and relaunch.
- **Code changes:** Restart the CLI or gateway process

### Skills not showing
1. `hermes skills list` — verify installed
2. `hermes skills config` — check platform enablement
3. Load explicitly: `/skill name` or `hermes -s name`

### Gateway issues
Check logs first:
```bash
grep -i "failed to send\|error" ~/.hermes/logs/gateway.log | tail -20
```

Common gateway problems:
- **Gateway dies on SSH logout**: Enable linger: `sudo loginctl enable-linger $USER`
- **Gateway dies on WSL2 close**: WSL2 requires `systemd=true` in `/etc/wsl.conf` for systemd services to work. Without it, gateway falls back to `nohup` (dies when session closes).
- **Gateway crash loop**: Reset the failed state: `systemctl --user reset-failed hermes-gateway`

### Platform-specific issues
- **Discord bot silent**: Must enable **Message Content Intent** in Bot → Privileged Gateway Intents.
- **Slack bot only works in DMs**: Must subscribe to `message.channels` event. Without it, the bot ignores public channels.
- **Windows HTTP 400 "No models provided"**: Config file encoding issue (BOM). Ensure `config.yaml` is saved as UTF-8 without BOM.

### Auxiliary models not working
If `auxiliary` tasks (vision, compression, session_search) fail silently, the `auto` provider can't find a backend. Either set `OPENROUTER_API_KEY` or `GOOGLE_API_KEY`, or explicitly configure each auxiliary task's provider:
```bash
hermes config set auxiliary.vision.provider <your_provider>
hermes config set auxiliary.vision.model <model_name>
```

---

## Where to Find Things

| Looking for... | Location |
|----------------|----------|
| Config options | `hermes config edit` or [Configuration docs](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) |
| Available tools | `hermes tools list` or [Tools reference](https://hermes-agent.nousresearch.com/docs/reference/tools-reference) |
| Slash commands | `/help` in session or [Slash commands reference](https://hermes-agent.nousresearch.com/docs/reference/slash-commands) |
| Skills catalog | `hermes skills browse` or [Skills catalog](https://hermes-agent.nousresearch.com/docs/reference/skills-catalog) |
| Provider setup | `hermes model` or [Providers guide](https://hermes-agent.nousresearch.com/docs/integrations/providers) |
| Platform setup | `hermes gateway setup` or [Messaging docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/) |
| MCP servers | `hermes mcp list` or [MCP guide](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) |
| Profiles | `hermes profile list` or [Profiles docs](https://hermes-agent.nousresearch.com/docs/user-guide/profiles) |
| Cron jobs | `hermes cron list` or [Cron docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) |
| Memory | `hermes memory status` or [Memory docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) |
| Env variables | `hermes config env-path` or [Env vars reference](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) |
| CLI commands | `hermes --help` or [CLI reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) |
| Gateway logs | `~/.hermes/logs/gateway.log` |
| Session files | `~/.hermes/sessions/` or `hermes sessions browse` |
| Source code | `~/.hermes/hermes-agent/` |

---

## Contributor Quick Reference

For occasional contributors and PR authors. Full developer docs: https://hermes-agent.nousresearch.com/docs/developer-guide/

### Project Layout

```
hermes-agent/
├── run_agent.py          # AIAgent — core conversation loop
├── model_tools.py        # Tool discovery and dispatch
├── toolsets.py           # Toolset definitions
├── cli.py                # Interactive CLI (HermesCLI)
├── hermes_state.py       # SQLite session store
├── agent/                # Prompt builder, context compression, memory, model routing, credential pooling, skill dispatch
├── hermes_cli/           # CLI subcommands, config, setup, commands
│   ├── commands.py       # Slash command registry (CommandDef)
│   ├── config.py         # DEFAULT_CONFIG, env var definitions
│   └── main.py           # CLI entry point and argparse
├── tools/                # One file per tool
│   └── registry.py       # Central tool registry
├── gateway/              # Messaging gateway
│   └── platforms/        # Platform adapters (telegram, discord, etc.)
├── cron/                 # Job scheduler
├── tests/                # ~3000 pytest tests
└── website/              # Docusaurus docs site
```

Config: `~/.hermes/config.yaml` (settings), `~/.hermes/.env` (API keys).

### Adding a Tool (3 files)

**1. Create `tools/your_tool.py`:**
```python
import json, os
from tools.registry import registry

def check_requirements() -> bool:
    return bool(os.getenv("EXAMPLE_API_KEY"))

def example_tool(param: str, task_id: str = None) -> str:
    return json.dumps({"success": True, "data": "..."})

registry.register(
    name="example_tool",
    toolset="example",
    schema={"name": "example_tool", "description": "...", "parameters": {...}},
    handler=lambda args, **kw: example_tool(
        param=args.get("param", ""), task_id=kw.get("task_id")),
    check_fn=check_requirements,
    requires_env=["EXAMPLE_API_KEY"],
)
```

**2. Add to `toolsets.py`** → `_HERMES_CORE_TOOLS` list.

Auto-discovery: any `tools/*.py` file with a top-level `registry.register()` call is imported automatically — no manual list needed.

All handlers must return JSON strings. Use `get_hermes_home()` for paths, never hardcode `~/.hermes`.

### Adding a Slash Command

1. Add `CommandDef` to `COMMAND_REGISTRY` in `hermes_cli/commands.py`
2. Add handler in `cli.py` → `process_command()`
3. (Optional) Add gateway handler in `gateway/run.py`

All consumers (help text, autocomplete, Telegram menu, Slack mapping) derive from the central registry automatically.

### Agent Loop (High Level)

```
run_conversation():
  1. Build system prompt
  2. Loop while iterations < max:
     a. Call LLM (OpenAI-format messages + tool schemas)
     b. If tool_calls → dispatch each via handle_function_call() → append results → continue
     c. If text response → return
  3. Context compression triggers automatically near token limit
```

### Testing

```bash
python -m pytest tests/ -o 'addopts=' -q   # Full suite
python -m pytest tests/tools/ -q            # Specific area
```

- Tests auto-redirect `HERMES_HOME` to temp dirs — never touch real `~/.hermes/`
- Run full suite before pushing any change
- Use `-o 'addopts='` to clear any baked-in pytest flags

### Commit Conventions

```
type: concise subject line

Optional body.
```

Types: `fix:`, `feat:`, `refactor:`, `docs:`, `chore:`

### Key Rules

- **Never break prompt caching** — don't change context, tools, or system prompt mid-conversation
- **Message role alternation** — never two assistant or two user messages in a row
- Use `get_hermes_home()` from `hermes_constants` for all paths (profile-safe)
- Config values go in `config.yaml`, secrets go in `.env`
- New tools need a `check_fn` so they only appear when requirements are met

To view linked files, call skill_view(name, file_path) where file_path is e.g. 'references/api.md' or 'assets/config.yaml'


terminal

hermes config check && printf '\n--- status ---\n' && hermes status --all

python - <<'PY'
import yaml, pathlib, json
p=pathlib.Path.home()/'.hermes/config.yaml'
d=yaml.safe_load(p.read_text()) or {}
keys=['model','compression','context','prompt_caching','memory','gateway','delegation','agent','toolsets','auxiliary','display','stt','tts','plugins','curator','kanban']
for k in keys:
 if k in d:
  print(f'## {k}')
  print(yaml.safe_dump(d[k], sort_keys=False, allow_unicode=True))
PY