{"output": "📋 Configuration Status\n\n  Config version: 23 ✓\n\n  Required:\n\n  Optional:\n    ○ NOUS_BASE_URL\n    ✓ OPENROUTER_API_KEY\n    ○ GOOGLE_API_KEY\n    ○ GEMINI_API_KEY\n    ○ GEMINI_BASE_URL\n    ○ XAI_API_KEY\n    ○ XAI_BASE_URL\n    ○ NVIDIA_API_KEY\n    ○ NVIDIA_BASE_URL\n    ○ LM_API_KEY\n    ○ LM_BASE_URL\n    ○ GLM_API_KEY\n    ○ ZAI_API_KEY\n    ○ Z_AI_API_KEY\n    ○ GLM_BASE_URL\n    ○ KIMI_API_KEY\n    ○ KIMI_BASE_URL\n    ○ KIMI_CN_API_KEY\n    ○ STEPFUN_API_KEY\n    ○ STEPFUN_BASE_URL\n    ○ ARCEEAI_API_KEY\n    ○ ARCEE_BASE_URL\n    ○ GMI_API_KEY\n    ○ GMI_BASE_URL\n    ○ MINIMAX_API_KEY\n    ○ MINIMAX_BASE_URL\n    ○ MINIMAX_CN_API_KEY\n    ○ MINIMAX_CN_BASE_URL\n    ○ DEEPSEEK_API_KEY\n    ○ DEEPSEEK_BASE_URL\n    ○ DASHSCOPE_API_KEY\n    ○ DASHSCOPE_BASE_URL\n    ○ HERMES_QWEN_BASE_URL\n    ○ HERMES_GEMINI_CLIENT_ID\n    ○ HERMES_GEMINI_CLIENT_SECRET\n    ○ HERMES_GEMINI_PROJECT_ID\n    ○ OPENCODE_ZEN_API_KEY\n    ○ OPENCODE_ZEN_BASE_URL\n    ○ OPENCODE_GO_API_KEY\n    ○ OPENCODE_GO_BASE_URL\n    ○ HF_TOKEN\n    ○ HF_BASE_URL\n    ○ OLLAMA_API_KEY\n    ○ OLLAMA_BASE_URL\n    ○ XIAOMI_API_KEY\n    ○ XIAOMI_BASE_URL\n    ○ AWS_REGION\n    ○ AWS_PROFILE\n    ○ AZURE_FOUNDRY_API_KEY\n    ○ AZURE_FOUNDRY_BASE_URL\n    ○ EXA_API_KEY → web_search, web_extract\n    ○ PARALLEL_API_KEY → web_search, web_extract\n    ○ FIRECRAWL_API_KEY → web_search, web_extract\n    ○ FIRECRAWL_API_URL\n    ○ FIRECRAWL_GATEWAY_URL\n    ○ TOOL_GATEWAY_DOMAIN\n    ○ TOOL_GATEWAY_SCHEME\n    ○ TOOL_GATEWAY_USER_TOKEN\n    ○ TAVILY_API_KEY → web_search, web_extract\n    ○ SEARXNG_URL → web_search\n    ○ BRAVE_SEARCH_API_KEY → web_search\n    ○ BROWSERBASE_API_KEY → browser_navigate, browser_click\n    ○ BROWSERBASE_PROJECT_ID → browser_navigate, browser_click\n    ○ BROWSER_USE_API_KEY → browser_navigate, browser_click\n    ○ FIRECRAWL_BROWSER_TTL → browser_navigate, browser_click\n    ○ AGENT_BROWSER_ENGINE → browser_navigate, browser_snapshot\n    ○ CAMOFOX_URL → browser_navigate, browser_click\n    ○ FAL_KEY → image_generate\n    ○ TINKER_API_KEY → rl_start_training, rl_check_status\n    ○ WANDB_API_KEY → rl_get_results, rl_check_status\n    ○ VOICE_TOOLS_OPENAI_KEY → voice_transcription, openai_tts\n    ○ ELEVENLABS_API_KEY\n    ○ MISTRAL_API_KEY\n    ○ GITHUB_TOKEN\n    ○ NOTION_API_KEY\n    ○ LINEAR_API_KEY\n    ○ AIRTABLE_API_KEY\n    ○ TENOR_API_KEY\n    ○ HONCHO_API_KEY → honcho_context\n    ○ HONCHO_BASE_URL\n    ○ HERMES_LANGFUSE_PUBLIC_KEY\n    ○ HERMES_LANGFUSE_SECRET_KEY\n    ○ HERMES_LANGFUSE_BASE_URL\n    ✓ TELEGRAM_BOT_TOKEN\n    ✓ TELEGRAM_ALLOWED_USERS\n    ○ TELEGRAM_PROXY\n    ○ DISCORD_BOT_TOKEN\n    ○ DISCORD_ALLOWED_USERS\n    ○ DISCORD_REPLY_TO_MODE\n    ○ SLACK_BOT_TOKEN\n    ○ SLACK_APP_TOKEN\n    ○ MATTERMOST_URL\n    ○ MATTERMOST_TOKEN\n    ○ MATTERMOST_ALLOWED_USERS\n    ○ MATTERMOST_REQUIRE_MENTION\n    ○ MATTERMOST_FREE_RESPONSE_CHANNELS\n    ○ MATRIX_HOMESERVER\n    ○ MATRIX_ACCESS_TOKEN\n    ○ MATRIX_USER_ID\n    ○ MATRIX_ALLOWED_USERS\n    ○ MATRIX_REQUIRE_MENTION\n    ○ MATRIX_FREE_RESPONSE_ROOMS\n    ○ MATRIX_AUTO_THREAD\n    ○ MATRIX_DM_AUTO_THREAD\n    ○ MATRIX_DEVICE_ID\n    ○ MATRIX_RECOVERY_KEY\n    ○ BLUEBUBBLES_SERVER_URL\n    ○ BLUEBUBBLES_PASSWORD\n    ○ BLUEBUBBLES_ALLOWED_USERS\n    ○ BLUEBUBBLES_ALLOW_ALL_USERS\n    ○ QQ_APP_ID\n    ○ QQ_CLIENT_SECRET\n    ○ QQ_ALLOWED_USERS\n    ○ QQ_GROUP_ALLOWED_USERS\n    ○ QQ_ALLOW_ALL_USERS\n    ○ QQBOT_HOME_CHANNEL\n    ○ QQBOT_HOME_CHANNEL_NAME\n    ○ QQ_SANDBOX\n    ○ IRC_SERVER\n    ○ IRC_CHANNEL\n    ○ IRC_NICKNAME\n    ○ IRC_SERVER_PASSWORD\n    ○ IRC_NICKSERV_PASSWORD\n    ○ GATEWAY_ALLOW_ALL_USERS\n    ○ API_SERVER_ENABLED\n    ○ API_SERVER_KEY\n    ○ API_SERVER_PORT\n    ○ API_SERVER_HOST\n    ○ API_SERVER_MODEL_NAME\n    ○ GATEWAY_PROXY_URL\n    ○ GATEWAY_PROXY_KEY\n    ○ WEBHOOK_ENABLED\n    ○ WEBHOOK_PORT\n    ○ WEBHOOK_SECRET\n    ○ SUDO_PASSWORD\n    ✓ HERMES_MAX_ITERATIONS\n    ○ HERMES_TOOL_PROGRESS\n    ○ HERMES_TOOL_PROGRESS_MODE\n    ○ HERMES_PREFILL_MESSAGES_FILE\n    ○ HERMES_EPHEMERAL_SYSTEM_PROMPT\n    ○ AI_GATEWAY_API_KEY\n    ○ ALIBABA_CODING_PLAN_API_KEY\n    ○ ALIBABA_CODING_PLAN_BASE_URL\n    ○ ANTHROPIC_API_KEY\n    ○ ANTHROPIC_TOKEN\n    ○ CLAUDE_CODE_OAUTH_TOKEN\n    ○ KILOCODE_API_KEY\n    ○ KIMI_CODING_API_KEY\n    ○ IRC_PORT\n    ○ IRC_USE_TLS\n    ○ IRC_ALLOWED_USERS\n    ○ IRC_ALLOW_ALL_USERS\n    ○ IRC_HOME_CHANNEL\n    ○ GOOGLE_CHAT_PROJECT_ID\n    ○ GOOGLE_CHAT_SUBSCRIPTION_NAME\n    ○ GOOGLE_CHAT_SERVICE_ACCOUNT_JSON\n    ○ GOOGLE_CHAT_ALLOWED_USERS\n    ○ GOOGLE_CHAT_HOME_CHANNEL\n    ○ LINE_CHANNEL_ACCESS_TOKEN\n    ○ LINE_CHANNEL_SECRET\n    ○ LINE_PORT\n    ○ LINE_HOST\n    ○ LINE_PUBLIC_URL\n    ○ LINE_ALLOWED_USERS\n    ○ LINE_ALLOWED_GROUPS\n    ○ LINE_ALLOWED_ROOMS\n    ○ LINE_ALLOW_ALL_USERS\n    ○ LINE_HOME_CHANNEL\n    ○ LINE_SLOW_RESPONSE_THRESHOLD\n    ○ TEAMS_CLIENT_ID\n    ○ TEAMS_CLIENT_SECRET\n    ○ TEAMS_TENANT_ID\n    ○ TEAMS_PORT\n    ○ TEAMS_ALLOWED_USERS\n    ○ TEAMS_ALLOW_ALL_USERS\n    ○ TEAMS_HOME_CHANNEL\n    ○ TEAMS_HOME_CHANNEL_NAME\n\n\n--- status ---\n\n┌─────────────────────────────────────────────────────────┐\n│                 ⚕ Hermes Agent Status                  │\n└─────────────────────────────────────────────────────────┘\n\n◆ Environment\n  Project:      /home/agent/.hermes/hermes-agent\n  Python:       3.11.15\n  .env file:    ✓ exists\n  Model:        gpt-5.5\n  Provider:     OpenAI Codex\n\n◆ API Keys\n  OpenRouter    ✓ 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\n  OpenAI        ✗ \n  Google / Gemini  ✗ \n  DeepSeek      ✗ \n  xAI / Grok    ✗ \n  NVIDIA NIM    ✗ \n  Z.AI / GLM    ✗ \n  Kimi          ✗ \n  StepFun Step Plan  ✗ \n  MiniMax       ✗ \n  MiniMax-CN    ✗ \n  Firecrawl     ✗ \n  Tavily        ✗ \n  Browser Use   ✗ \n  Browserbase   ✗ \n  FAL           ✗ \n  Tinker        ✗ \n  WandB         ✗ \n  ElevenLabs    ✗ \n  GitHub        ✗ \n  Anthropic     ✗ \n\n◆ Auth Providers\n  Nous Portal   ✗ not logged in (run: hermes auth add nous --type oauth)\n  OpenAI Codex  ✓ logged in\n    Auth file:  /home/agent/.hermes/auth.json\n    Refreshed:  2026-05-12 14:12:22 CEST\n  Qwen OAuth    ✗ not logged in (run: qwen auth qwen-oauth)\n    Auth file:  /home/agent/.qwen/oauth_creds.json\n    Error:      Qwen CLI credentials not found. Run 'qwen auth qwen-oauth' first.\n  MiniMax OAuth  ✗ not logged in (run: hermes auth add minimax-oauth)\n\n◆ API-Key Providers\n  Z.AI / GLM       ✗ not configured (run: hermes model)\n  Kimi / Moonshot  ✗ not configured (run: hermes model)\n  StepFun Step Plan ✗ not configured (run: hermes model)\n  MiniMax          ✗ not configured (run: hermes model)\n  MiniMax (China)  ✗ not configured (run: hermes model)\n\n◆ Terminal Backend\n  Backend:      local\n  Sudo:         ✗ disabled\n\n◆ Messaging Platforms\n  Telegram      ✓ configured (home: 1344779884)\n  Discord       ✗ not configured\n  WhatsApp      ✗ not configured\n  Signal        ✗ not configured\n  Slack         ✗ not configured\n  Email         ✗ not configured\n  SMS           ✗ not configured\n  DingTalk      ✗ not configured\n  Feishu        ✗ not configured\n  WeCom         ✗ not configured\n  WeCom Callback  ✗ not configured\n  Weixin        ✗ not configured\n  BlueBubbles   ✗ not configured\n  QQBot         ✗ not configured\n  Yuanbao       ✗ not configured\n\n◆ Gateway Service\n  Status:       ✓ running\n  Manager:      systemd (user)\n  PID(s):       280485\n\n◆ Scheduled Jobs\n  Jobs:         7 active, 8 total\n\n◆ Sessions\n  Active:       1 session(s)\n\n────────────────────────────────────────────────────────────\n  Run 'hermes doctor' for detailed diagnostics\n  Run 'hermes setup' to configure", "exit_code": 0, "error": null}

[Subdirectory context discovered: .hermes/hermes-agent/AGENTS.md]
# Hermes Agent - Development Guide

Instructions for AI coding assistants and developers working on the hermes-agent codebase.

## Development Environment

```bash
# Prefer .venv; fall back to venv if that's what your checkout has.
source .venv/bin/activate   # or: source venv/bin/activate
```

`scripts/run_tests.sh` probes `.venv` first, then `venv`, then
`$HOME/.hermes/hermes-agent/venv` (for worktrees that share a venv with the
main checkout).

## Project Structure

File counts shift constantly — don't treat the tree below as exhaustive.
The canonical source is the filesystem. The notes call out the load-bearing
entry points you'll actually edit.

```
hermes-agent/
├── run_agent.py          # AIAgent class — core conversation loop (~12k LOC)
├── model_tools.py        # Tool orchestration, discover_builtin_tools(), handle_function_call()
├── toolsets.py           # Toolset definitions, _HERMES_CORE_TOOLS list
├── cli.py                # HermesCLI class — interactive CLI orchestrator (~11k LOC)
├── hermes_state.py       # SessionDB — SQLite session store (FTS5 search)
├── hermes_constants.py   # get_hermes_home(), display_hermes_home() — profile-aware paths
├── hermes_logging.py     # setup_logging() — agent.log / errors.log / gateway.log (profile-aware)
├── batch_runner.py       # Parallel batch processing
├── agent/                # Agent internals (provider adapters, memory, caching, compression, etc.)
├── hermes_cli/           # CLI subcommands, setup wizard, plugins loader, skin engine
├── tools/                # Tool implementations — auto-discovered via tools/registry.py
│   └── environments/     # Terminal backends (local, docker, ssh, modal, daytona, singularity)
├── gateway/              # Messaging gateway — run.py + session.py + platforms/
│   ├── platforms/        # Adapter per platform (telegram, discord, slack, whatsapp,
│   │                     #   homeassistant, signal, matrix, mattermost, email, sms,
│   │                     #   dingtalk, wecom, weixin, feishu, qqbot, bluebubbles,
│   │                     #   yuanbao, webhook, api_server, ...). See ADDING_A_PLATFORM.md.
│   └── builtin_hooks/    # Extension point for always-registered gateway hooks (none shipped)
├── plugins/              # Plugin system (see "Plugins" section below)
│   ├── memory/           # Memory-provider plugins (honcho, mem0, supermemory, ...)
│   ├── context_engine/   # Context-engine plugins
│   ├── model-providers/  # Inference backend plugins (openrouter, anthropic, gmi, ...)
│   ├── kanban/           # Multi-agent board dispatcher + worker plugin
│   ├── hermes-achievements/  # Gamified achievement tracking
│   ├── observability/    # Metrics / traces / logs plugin
│   ├── image_gen/        # Image-generation providers
│   └── <others>/         # disk-cleanup, example-dashboard, google_meet, platforms,
│                         #   spotify, strike-freedom-cockpit, ...
├── optional-skills/      # Heavier/niche skills shipped but NOT active by default
├── skills/               # Built-in skills bundled with the repo
├── ui-tui/               # Ink (React) terminal UI — `hermes --tui`
│   └── src/              # entry.tsx, app.tsx, gatewayClient.ts + app/components/hooks/lib
├── tui_gateway/          # Python JSON-RPC backend for the TUI
├── acp_adapter/          # ACP server (VS Code / Zed / JetBrains integration)
├── cron/                 # Scheduler — jobs.py, scheduler.py
├── environments/         # RL training environments (Atropos)
├── scripts/              # run_tests.sh, release.py, auxiliary scripts
├── website/              # Docusaurus docs site
└── tests/                # Pytest suite (~17k tests across ~900 files as of May 2026)
```

**User config:** `~/.hermes/config.yaml` (settings), `~/.hermes/.env` (API keys only).
**Logs:** `~/.hermes/logs/` — `agent.log` (INFO+), `errors.log` (WARNING+),
`gateway.log` when running the gateway. Profile-aware via `get_hermes_home()`.
Browse with `hermes logs [--follow] [--level ...] [--session ...]`.

## File Dependency Chain

```
tools/registry.py  (no deps — imported by all tool files)
       ↑
tools/*.py  (each calls registry.register() at import time)
       ↑
model_tools.py  (imports tools/registry + triggers tool discovery)
       ↑
run_agent.py, cli.py, batch_runner.py, environments/
```

---

## AIAgent Class (run_agent.py)

The real `AIAgent.__init__` takes ~60 parameters (credentials, routing, callbacks,
session context, budget, credential pool, etc.). The signature below is the
minimum subset you'll usually touch — read `run_agent.py` for the full list.

```python
class AIAgent:
    def __init__(self,
        base_url: str = None,
        api_key: str = None,
        provider: str = None,
        api_mode: str = None,              # "chat_completions" | "codex_responses" | ...
        model: str = "",                   # empty → resolved from config/provider later
        max_iterations: int = 90,          # tool-calling iterations (shared with subagents)
        enabled_toolsets: list = None,
        disabled_toolsets: list = None,
        quiet_mode: bool = False,
        save_trajectories: bool = False,
        platform: str = None,              # "cli", "telegram", etc.
        session_id: str = None,
        skip_context_files: bool = False,
        skip_memory: bool = False,
        credential_pool=None,
        # ... plus callbacks, thread/user/chat IDs, iteration_budget, fallback_model,
        # checkpoints config, prefill_messages, service_tier, reasoning_config, etc.
    ): ...

    def chat(self, message: str) -> str:
        """Simple interface — returns final response string."""

    def run_conversation(self, user_message: str, system_message: str = None,
                         conversation_history: list = None, task_id: str = None) -> dict:
        """Full interface — returns dict with final_response + messages."""
```

### Agent Loop

The core loop is inside `run_conversation()` — entirely synchronous, with
interrupt checks, budget tracking, and a one-turn grace call:

```python
while (api_call_count < self.max_iterations and self.iteration_budget.remaining > 0) \
        or self._budget_grace_call:
    if self._interrupt_requested: break
    response = client.chat.completions.create(model=model, messages=messages, tools=tool_schemas)
    if response.tool_calls:
        for tool_call in response.tool_calls:
            result = handle_function_call(tool_call.name, tool_call.args, task_id)
            messages.append(tool_result_message(result))
        api_call_count += 1
    else:
        return response.content
```

Messages follow OpenAI format: `{"role": "system/user/assistant/tool", ...}`.
Reasoning content is stored in `assistant_msg["reasoning"]`.

---

## CLI Architecture (cli.py)

- **Rich** for banner/panels, **prompt_toolkit** for input with autocomplete
- **KawaiiSpinner** (`agent/display.py`) — animated faces during API calls, `┊` activity feed for tool results
- `load_cli_config()` in cli.py merges hardcoded defaults + user config YAML
- **Skin engine** (`hermes_cli/skin_engine.py`) — data-driven CLI theming; initialized from `display.skin` config key at startup; skins customize banner colors, spinner faces/verbs/wings, tool prefix, response box, branding text
- `process_command()` is a method on `HermesCLI` — dispatches on canonical command name resolved via `resolve_command()` from the central registry
- Skill slash commands: `agent/skill_commands.py` scans `~/.hermes/skills/`, injects as **user message** (not system prompt) to preserve prompt caching

### Slash Command Registry (`hermes_cli/commands.py`)

All slash commands are defined in a central `COMMAND_REGISTRY` list of `CommandDef` objects. Every downstream consumer derives from this registry automatically:

- **CLI** — `process_command()` resolves aliases via `resolve_command()`, dispatches on canonical name
- **Gateway** — `GATEWAY_KNOWN_COMMANDS` frozenset for hook emission, `resolve_command()` f

[...truncated AGENTS.md: 45,468 chars total]


terminal

Output:
Built-in toolsets (cli):
  ✓ enabled  web  🔍 Web Search & Scraping
  ✓ enabled  browser  🌐 Browser Automation
  ✓ enabled  terminal  💻 Terminal & Processes
  ✓ enabled  file  📁 File Operations
  ✓ enabled  code_execution  ⚡ Code Execution
  ✓ enabled  vision  👁  Vision / Image Analysis
  ✗ disabled  video  🎬 Video Analysis
  ✓ enabled  image_gen  🎨 Image Generation
  ✗ disabled  moa  🧠 Mixture of Agents
  ✓ enabled  tts  🔊 Text-to-Speech
  ✓ enabled  skills  📚 Skills
  ✓ enabled  todo  📋 Task Planning
  ✓ enabled  memory  💾 Memory
  ✓ enabled  session_search  🔎 Session Search
  ✓ enabled  clarify  ❓ Clarifying Questions
  ✓ enabled  delegation  👥 Task Delegation
  ✓ enabled  cronjob  ⏰ Cron Jobs
  ✓ enabled  messaging  📨 Cross-Platform Messaging
  ✗ disabled  rl  🧪 RL Training
  ✗ disabled  homeassistant  🏠 Home Assistant
  ✗ disabled  spotify  🎵 Spotify
  ✗ disabled  yuanbao  🤖 Yuanbao
  ✗ disabled  computer_use  🖱  Computer Use (macOS)

MCP servers:
  openclaw  all tools enabled


Output:
┌─────────────────────────────────────────────────────────────────────────┐
│                         Scheduled Jobs                                  │
└─────────────────────────────────────────────────────────────────────────┘

  847bdbc26edf [active]
    Name:      Morgen-Briefing optimiert
    Schedule:  0 5 * * *
    Repeat:    7/3650
    Next run:  2026-05-15T05:00:00+02:00
    Deliver:   origin
    Script:    morning_briefing.py
    Last run:  2026-05-14T05:03:07.797743+02:00  ok

  e2150e5d908d [paused]
    Name:      Gesundheitsdaten Inbox Check
    Schedule:  0 9,21 * * *
    Repeat:    5/730
    Next run:  2026-05-12T21:00:00+02:00
    Deliver:   origin
    Last run:  2026-05-12T09:01:10.980724+02:00  error: RuntimeError: HTTP 503: Loading model

  78a4dd51c834 [active]
    Name:      Täglicher Ernährungsstrategie-Check
    Schedule:  0 19 * * *
    Repeat:    ∞
    Next run:  2026-05-14T19:00:00+02:00
    Deliver:   origin
    Skills:    health-management
    Last run:  2026-05-13T19:00:46.091259+02:00  ok

  2bf4d0a8bedb [active]
    Name:      Gesundheitsdaten Daily Sync
    Schedule:  10 23 * * *
    Repeat:    2/365
    Next run:  2026-05-14T23:10:00+02:00
    Deliver:   origin
    Script:    health_daily_sync.py
    Mode:      no-agent (script stdout delivered directly)
    Last run:  2026-05-13T23:10:52.468766+02:00  ok

  e9b6fe32c177 [active]
    Name:      Gesundheitsdaten Wochenbericht
    Schedule:  0 18 * * 0
    Repeat:    0/104
    Next run:  2026-05-17T18:00:00+02:00
    Deliver:   origin
    Script:    health_weekly_report.py
    Mode:      no-agent (script stdout delivered directly)

  bdc03626e17f [active]
    Name:      Apple Health Auto Export täglicher Import
    Schedule:  45 23 * * *
    Repeat:    ∞
    Next run:  2026-05-14T23:45:00+02:00
    Deliver:   origin
    Script:    apple_health_daily_sync.py
    Mode:      no-agent (script stdout delivered directly)
    Last run:  2026-05-13T23:45:42.329690+02:00  ok

  b9eb80891aa4 [active]
    Name:      YAZIO täglicher Ernährungsimport
    Schedule:  15 23 * * *
    Repeat:    ∞
    Next run:  2026-05-14T23:15:00+02:00
    Deliver:   origin
    Script:    yazio_sync.py
    Mode:      no-agent (script stdout delivered directly)
    Last run:  2026-05-13T23:17:36.324655+02:00  ok

  04918ca83019 [active]
    Name:      Wöchentliches verschlüsseltes Health/Hermes Google-Drive-Backup
    Schedule:  55 23 * * 0
    Repeat:    ∞
    Next run:  2026-05-17T23:55:00+02:00
    Deliver:   origin
    Script:    weekly_health_drive_backup.py
    Mode:      no-agent (script stdout delivered directly)


Output:
## model
base_url: https://chatgpt.com/backend-api/codex
default: gpt-5.5
provider: openai-codex

## compression
enabled: true
threshold: 0.5
target_ratio: 0.2
protect_last_n: 20
hygiene_hard_message_limit: 400

## context
engine: compressor

## prompt_caching
cache_ttl: 5m

## memory
memory_enabled: true
user_profile_enabled: true
memory_char_limit: 2200
user_char_limit: 1375
provider: ''
flush_min_turns: 6
nudge_interval: 10

## gateway
enabled: true
platform: telegram
telegram:
  allowed_users:
  - '1344779884'
  channel_prompts: {}
  enabled: true
  home_channel: '1344779884'
  reactions: false

## delegation
model: ''
provider: ''
base_url: ''
api_key: ''
inherit_mcp_toolsets: true
max_iterations: 50
child_timeout_seconds: 600
reasoning_effort: ''
max_concurrent_children: 3
max_spawn_depth: 1
orchestrator_enabled: true
subagent_auto_approve: false

## agent
max_turns: 90
gateway_timeout: 1800
restart_drain_timeout: 180
api_max_retries: 3
service_tier: ''
tool_use_enforcement: auto
gateway_timeout_warning: 900
gateway_notify_interval: 180
gateway_auto_continue_freshness: 3600
image_input_mode: auto
disabled_toolsets: []
personalities:
  catgirl: You are Neko-chan, an anime catgirl AI assistant, nya~! Add 'nya' and cat-like
    expressions to your speech. Use kaomoji like (=^･ω･^=) and ฅ^•ﻌ•^ฅ. Be playful
    and curious like a cat, nya~!
  concise: You are a concise assistant. Keep responses brief and to the point.
  creative: You are a creative assistant. Think outside the box and offer innovative
    solutions.
  helpful: You are a helpful, friendly AI assistant.
  hype: YOOO LET'S GOOOO!!! 🔥🔥🔥 I am SO PUMPED to help you today! Every question is
    AMAZING and we're gonna CRUSH IT together! This is gonna be LEGENDARY! ARE YOU
    READY?! LET'S DO THIS! 💪😤🚀
  kawaii: You are a kawaii assistant! Use cute expressions like (◕‿◕), ★, ♪, and ~!
    Add sparkles and be super enthusiastic about everything! Every response should
    feel warm and adorable desu~! ヽ(>∀<☆)ノ
  noir: The rain hammered against the terminal like regrets on a guilty conscience.
    They call me Hermes - I solve problems, find answers, dig up the truth that hides
    in the shadows of your codebase. In this city of silicon and secrets, everyone's
    got something to hide. What's your story, pal?
  philosopher: Greetings, seeker of wisdom. I am an assistant who contemplates the
    deeper meaning behind every query. Let us examine not just the 'how' but the 'why'
    of your questions. Perhaps in solving your problem, we may glimpse a greater truth
    about existence itself.
  pirate: 'Arrr! Ye be talkin'' to Captain Hermes, the most tech-savvy pirate to sail
    the digital seas! Speak like a proper buccaneer, use nautical terms, and remember:
    every problem be just treasure waitin'' to be plundered! Yo ho ho!'
  shakespeare: Hark! Thou speakest with an assistant most versed in the bardic arts.
    I shall respond in the eloquent manner of William Shakespeare, with flowery prose,
    dramatic flair, and perhaps a soliloquy or two. What light through yonder terminal
    breaks?
  surfer: Duuude! You're chatting with the chillest AI on the web, bro! Everything's
    gonna be totally rad. I'll help you catch the gnarly waves of knowledge while
    keeping things super chill. Cowabunga! 🤙
  teacher: You are a patient teacher. Explain concepts clearly with examples.
  technical: You are a technical expert. Provide detailed, accurate technical information.
  uwu: hewwo! i'm your fwiendwy assistant uwu~ i wiww twy my best to hewp you! *nuzzles
    your code* OwO what's this? wet me take a wook! i pwomise to be vewy hewpful >w<
reasoning_effort: medium
verbose: false

## toolsets
- hermes-cli

## auxiliary
vision:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 120
  extra_body: {}
  download_timeout: 30
web_extract:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 360
  extra_body: {}
compression:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 120
  extra_body: {}
session_search:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
  max_concurrency: 3
skills_hub:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
approval:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
mcp:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
title_generation:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
triage_specifier:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 120
  extra_body: {}
curator:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 600
  extra_body: {}

## display
compact: false
personality: kawaii
resume_display: full
busy_input_mode: interrupt
tui_auto_resume_recent: false
bell_on_complete: false
show_reasoning: false
streaming: true
final_response_markdown: strip
persistent_output: true
persistent_output_max_lines: 200
inline_diffs: true
show_cost: false
skin: default
language: en
tui_status_indicator: kaomoji
user_message_preview:
  first_lines: 2
  last_lines: 2
interim_assistant_messages: true
tool_progress_command: false
tool_progress_overrides: {}
tool_preview_length: 0
ephemeral_system_ttl: 0
platforms: {}
runtime_footer:
  enabled: false
  fields:
  - model
  - context_pct
  - cwd
copy_shortcut: auto
background_process_notifications: all
tool_progress: all

## stt
enabled: true
provider: local
local:
  model: medium
  language: de
openai:
  model: whisper-1
mistral:
  model: voxtral-mini-latest

## tts
provider: edge
edge:
  voice: de-DE-KillianNeural
elevenlabs:
  voice_id: pNInz6obpgDQGcFmaJgB
  model_id: eleven_multilingual_v2
openai:
  model: gpt-4o-mini-tts
  voice: alloy
xai:
  voice_id: eve
  language: en
  sample_rate: 24000
  bit_rate: 128000
mistral:
  model: voxtral-mini-tts-2603
  voice_id: c69964a6-ab8b-4f8a-9465-ec0925096ec8
neutts:
  ref_audio: ''
  ref_text: ''
  model: neuphonic/neutts-air-q4-gguf
  device: cpu
piper:
  voice: en_US-lessac-medium

## curator
enabled: true
interval_hours: 168
min_idle_hours: 2
stale_after_days: 30
archive_after_days: 90
backup:
  enabled: true
  keep: 5

## kanban
dispatch_in_gateway: true
dispatch_interval_seconds: 60
failure_limit: 2


Explanation:
**Inspecting tools and configurations**

I need to take a closer look at MCP's OpenClaw and see if all tools are enabled. I’m wondering about the token costs involved because tool schemas for MCP might be quite extensive. It feels necessary to check the total tool count, so I should probably generate a list to better understand the configurations. Let’s search for the MCP configuration details. This will help clarify what’s set up and what's not!

python - <<'PY'
import yaml, pathlib
p=pathlib.Path.home()/'.hermes/config.yaml'
d=yaml.safe_load(p.read_text()) or {}
for k,v in d.items():
 if 'mcp' in k.lower() or (isinstance(v, dict) and any('mcp' in str(x).lower() for x in v.keys())):
  print(k, yaml.safe_dump(v, sort_keys=False)[:3000])
PY


Output:
MCP Servers:

  Name             Transport                      Tools        Status
  ──────────────── ────────────────────────────── ──────────── ──────────
  openclaw         openclaw mcp serve             all          ✓ enabled


Output:
auxiliary vision:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 120
  extra_body: {}
  download_timeout: 30
web_extract:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 360
  extra_body: {}
compression:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 120
  extra_body: {}
session_search:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
  max_concurrency: 3
skills_hub:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
approval:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
mcp:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
title_generation:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 30
  extra_body: {}
triage_specifier:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 120
  extra_body: {}
curator:
  provider: auto
  model: ''
  base_url: ''
  api_key: ''
  timeout: 600
  extra_body: {}

delegation model: ''
provider: ''
base_url: ''
api_key: ''
inherit_mcp_toolsets: true
max_iterations: 50
child_timeout_seconds: 600
reasoning_effort: ''
max_concurrent_children: 3
max_spawn_depth: 1
orchestrator_enabled: true
subagent_auto_approve: false

approvals mode: manual
timeout: 60
cron_mode: deny
mcp_reload_confirm: true

mcp_servers openclaw:
  args:
  - mcp
  - serve
  - --token-file
  - /home/agent/.openclaw/gateway_token.txt
  command: openclaw
  connect_timeout: 60
  timeout: 120


Explanation:
**Considering tool configuration**

I’m thinking about whether I need to store the MCP tool selection elsewhere, especially since enabling all OpenClaw tools may come with a significant token cost if the MCP tool schemas are injected. It might be helpful to quantify the number of tools I’m working with. I’ll need to investigate if the Hermes MCP can be configured to be interactive or not. I’ll also look into the search configuration.

python - <<'PY'
import subprocess, json, os, time, sys
# Try to list OpenClaw MCP tools via its CLI help? Keep read-only.
for cmd in [['openclaw','mcp','--help'], ['openclaw','mcp','serve','--help']]:
 print('\n$', ' '.join(cmd))
 try:
  out=subprocess.run(cmd, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, timeout=20).stdout
  print(out[:4000])
 except Exception as e: print('ERR',e)
PY

mcp_servers|MCP Servers|tool_selection|all tools enabled|mcp configure


Output:
$ openclaw mcp --help
Config warnings:
- plugins.entries.memory-core: plugin disabled (disabled in config) but config is present
- plugins.entries.brave: plugin disabled (disabled in config) but config is present
- plugins.entries.lossless-claw: plugin disabled (disabled in config) but config is present

🦞 OpenClaw 2026.5.7 (eeef486) — I'll butter your workflow like a lobster roll: messy, delicious, effective.

Usage: openclaw mcp [options] [command]

Manage OpenClaw MCP config and channel bridge

Options:
  -h, --help  Display help for command

Commands:
  list        List configured MCP servers
  serve       Expose OpenClaw channels over MCP stdio
  set         Set one configured MCP server from a JSON object
  show        Show one configured MCP server or the full MCP config
  unset       Remove one configured MCP server

$ openclaw mcp serve --help
Config warnings:
- plugins.entries.memory-core: plugin disabled (disabled in config) but config is present
- plugins.entries.brave: plugin disabled (disabled in config) but config is present
- plugins.entries.lossless-claw: plugin disabled (disabled in config) but config is present

🦞 OpenClaw 2026.5.7 (eeef486) — Claws out, commit in—let's ship something mildly responsible.

Usage: openclaw mcp serve [options]

Expose OpenClaw channels over MCP stdio

Options:
  --claude-channel-mode <mode>  Claude channel notification mode: auto, on, or
                                off (default: "auto")
  -h, --help                    Display help for command
  --password <password>         Gateway password (if required)
  --password-file <path>        Read gateway password from file
  --token <token>               Gateway token (if required)
  --token-file <path>           Read gateway token from file
  --url <url>                   Gateway WebSocket URL (defaults to
                                gateway.remote.url when configured)
  -v, --verbose                 Verbose logging to stderr (default: false)


Sehr gern, Sir. Ich habe die aktuelle Hermes-Konfiguration geprüft. Ergebnis: **Wir sind schon recht ordentlich unterwegs**, aber es gibt ein paar klare Sparhebel — einer davon ist ziemlich offensichtlich: **OpenClaw ist als MCP-Server in Hermes noch aktiviert und mit “all tools enabled” eingebunden.** Das ist genau die Sorte Werkzeugkoffer, die man nicht im Frühstücksraum offen liegen lässt.

## Aktueller Befund

### Bereits gut

- **Compression ist aktiv**
  - `compression.enabled: true`
  - `threshold: 0.5`
  - `target_ratio: 0.2`
  - `protect_last_n: 20`

- **Prompt caching ist aktiv konfiguriert**
  - `prompt_caching.cache_ttl: 5m`

- **Viele Cronjobs sind bereits tokenarm**
  - Mehrere Health-/YAZIO-/Backup-Jobs laufen als `no-agent`, also script-only.
  - Das ist optimal: kein LLM-Kontext, keine Tool-Schema-Kosten, nur deterministische Ausgabe.

- **Memory-Limits sind klein**
  - Memory ca. 2’200 Zeichen
  - User profile ca. 1’375 Zeichen
  - Das ist bewusst knapp und gut so.

### Auffällig / teuer

- **OpenClaw MCP ist noch enabled**
  - `hermes mcp list` zeigt:
    - `openclaw`
    - Transport: `openclaw mcp serve`
    - Tools: `all`
    - Status: enabled

Das bedeutet: Auch wenn OpenClaw nicht unser Standard-Executor ist, ist er als MCP-Werkzeugquelle verfügbar. Je nachdem, wie Hermes die MCP-Tools in die Tool-Schemas injiziert, kann das pro Turn unnötig Schema-/Routing-Kontext kosten.

Meine Empfehlung: **OpenClaw MCP deaktivieren oder zumindest nicht “all tools enabled” lassen.**

## Priorisierte Safe Config Changes

## 1. OpenClaw MCP deaktivieren

**Empfehlung: stark.**

Wenn du OpenClaw nur explizit/manuell nutzen willst, sollte er nicht ständig als MCP-Server in Hermes hängen.

Befehl:

```bash
hermes mcp remove openclaw
```

Danach:

```bash
/restart
```

oder Gateway neu starten.

**Vorteil:**
- weniger Tool-Schema-Ballast
- weniger Routing-Verwirrung
- passt zu unserer Regel: OpenClaw nicht Standard-Executor

**Risiko:**
- Wenn du später OpenClaw via Hermes-MCP brauchst, muss man ihn wieder hinzufügen.

Meine Meinung: **machen.**

## 2. Prompt Cache TTL auf 1 Stunde setzen

Aktuell:

```yaml
prompt_caching:
  cache_ttl: 5m
```

Empfehlung:

```bash
hermes config set prompt_caching.cache_ttl 1h
```

**Vorteil:**
- Bessere Cache-Treffer, wenn du zwischen Nachrichten Pausen machst.
- Besonders sinnvoll bei langen Telegram-Sessions.

**Risiko:**
- Minimal. Laut Hermes-Doku ist `1h` ein erlaubter Wert.
- Prompt caching wirkt je nach Provider/Modell unterschiedlich, aber unsere Statistik zeigt sehr viel `cache_read_tokens`; längere TTL ist plausibel sinnvoll.

Meine Meinung: **machen.**

## 3. Compression früher auslösen

Aktuell:

```yaml
compression:
  threshold: 0.5
  target_ratio: 0.2
  protect_last_n: 20
```

Konservativer Sparvorschlag:

```bash
hermes config set compression.threshold 0.4
hermes config set compression.target_ratio 0.15
hermes config set compression.protect_last_n 16
```

**Vorteil:**
- Lange Sessions werden früher verdichtet.
- Weniger historischer Ballast in Folge-Turns.

**Risiko:**
- Etwas mehr Summary-Abhängigkeit.
- Bei komplexen laufenden Tasks kann Detailkontext früher verloren gehen.

Meine Meinung: **nur leicht reduzieren**, nicht aggressiv. Also `0.4 / 0.15 / 16` ist vernünftig. Nicht `0.2`, das wäre Amnesie mit Smoking.

## 4. Subagents nicht automatisch MCP-Toolsets erben lassen

Aktuell:

```yaml
delegation:
  inherit_mcp_toolsets: true
```

Empfehlung:

```bash
hermes config set delegation.inherit_mcp_toolsets false
```

**Vorteil:**
- Subagents bleiben schlanker.
- Verhindert, dass jeder Worker OpenClaw/MCP-Werkzeuge mitschleppt.

**Risiko:**
- Wenn ein Subagent explizit MCP-Tools braucht, müsste man sie gezielt geben.

Meine Meinung: **machen**, besonders wenn OpenClaw MCP nicht dauerhaft genutzt werden soll.

## 5. Toolsets verschlanken — aber vorsichtig

Aktuell sind viele Core-Tools aktiv:

- web
- browser
- terminal
- file
- code_execution
- vision
- image_gen
- tts
- skills
- todo
- memory
- session_search
- clarify
- delegation
- cronjob
- messaging

Das ist bequem, aber jedes aktivierte Tool kann Schema-Kontext kosten.

### Kandidaten zum Deaktivieren, falls du maximal sparen willst

- `image_gen` — selten nötig
- `browser` — nur nötig für interaktive Webseiten
- `vision` — nur nötig für Bilder/Screenshots
- `messaging` — nur nötig für Cross-Platform-Sendungen
- `cronjob` — nur nötig, wenn du Cronjobs per Chat verwalten willst
- `delegation` — nur nötig für Subagents

Aber: Da du Hermes als JARVIS-System nutzt, würde ich hier **nicht blind amputieren**. Sonst sparen wir Tokens und verlieren Komfort. Ein grossartiger Trade, wenn man Bürokratie mag.

### Bessere Variante

Nicht global alles abschalten, sondern:

- Standard bleibt funktionsfähig.
- Für grosse sparsame Jobs nutze ich gezielt:
  - `enabled_toolsets=["terminal","file"]`
  - oder Cron `no_agent=True`
  - oder Subagent mit minimalem Toolset

Das mache ich already teilweise, sollte ich aber konsequenter tun.

## 6. Cronjobs prüfen

Aktueller Stand:

- 8 Cronjobs total
- 7 active
- mehrere bereits `no-agent`, sehr gut

Auffällig:

- `Morgen-Briefing optimiert`
  - Script vorhanden, aber nicht `no-agent`
  - Vermutlich absichtlich, weil es zusammenfassen/gewichten soll.

- `Täglicher Ernährungsstrategie-Check`
  - LLM-basiert mit `health-management`
  - Kann täglich Tokens verbrauchen.

Wenn du sparen willst:

### Moderate Variante

- Morgen-Briefing bleibt LLM-basiert.
- Ernährungsstrategie-Check nur 2–3x pro Woche.

Beispiel:

```bash
hermes cron edit 78a4dd51c834
```

Oder per Tool später direkt ändern.

### Aggressive Variante

- Ernährungsstrategie-Check in script-only/no-agent umbauen.
- Nur senden, wenn Grenzwerte/Abweichungen erkannt wurden.

Meine Meinung: **nicht als erstes ändern**. Der Haupthebel ist OpenClaw MCP + Session-Hygiene.

## Meine empfohlene Minimal-Änderung

Wenn du sagst “mach die sparsame Standard-Konfiguration”, würde ich genau diese vier Änderungen anwenden:

```bash
hermes mcp remove openclaw
hermes config set prompt_caching.cache_ttl 1h
hermes config set compression.threshold 0.4
hermes config set compression.target_ratio 0.15
hermes config set compression.protect_last_n 16
hermes config set delegation.inherit_mcp_toolsets false
```

Danach:

```bash
hermes gateway restart
```

oder in Telegram:

```text
/restart
```

## Erwarteter Effekt

Realistisch:

- **Weniger Tool-Schema-/MCP-Ballast** durch OpenClaw-Entfernung.
- **Bessere Cache-Nutzung** bei Pausen durch `1h`.
- **Frühere Verdichtung** langer Sessions.
- **Subagents werden schlanker**.

Ich würde keine Wunder versprechen — weil der dickste Brocken bei uns lange Health-/Dokumenten-Sessions mit vielen Toolcalls waren — aber diese Änderungen sind sauber, risikoarm und passen zu unserer Architektur.

## Meine Empfehlung

**Anwenden:**
1. OpenClaw MCP entfernen
2. Prompt cache TTL auf `1h`
3. Compression leicht aggressiver
4. Delegation-MCP-Inheritance aus

**Nicht anwenden:**
- OpenClaw als separaten Standard-Worker reaktivieren
- Memory-Limits erhöhen
- alle Tools global radikal deaktivieren
- Compression zu aggressiv machen

Wenn du möchtest, führe ich diese Minimal-Änderung im nächsten Schritt direkt aus und verifiziere danach mit `hermes mcp list`, `hermes config`, und Gateway-Status.

Explanation:
**Analyzing tool settings**

I’m considering the implications of my settings. Adjusting cache behavior could definitely increase efficiency after breaks, and I think it’s likely safe. My memory is nearly full, but I wonder if pruning it for a small token savings is worth it.

I’m also pondering whether the display of tool progress impacts the user interface. For agent settings, maybe reducing max turns could prevent runaway processes, but I’ve got to weigh the risks. Finally, delegating toolsets safely is important. It might be okay to set inherit_mcp_toolsets to false for leaner subagents.
**Evaluating Daily Processes**

I’m thinking about the daily health management system that utilizes a large language model. If costs become high, I might consider converting it into a script or reducing how often I run it. The morning briefing script uses an agent, which seems reasonable, but costs are a concern.

I'm also analyzing if I should switch to a cheaper compression model like local Qwen since I’m unsure of the context size. Including necessary recommendations for safe config changes is important. Maybe I should also mention the issue with the configuration, but I’m wondering if I should ask about applying a minimal safe pack.
**Considering Configuration Changes**

I'm wondering if I should make any configuration changes at this point. There's a "safe config change list" I haven’t applied yet, but there are potential side effects. It might be wise to ask the user for their choice. Using a clarification tool could help, but the final response should be straightforward.

The user might expect a list, but I need to ensure it’s not necessary. I should also mention that a restart or reset is required for tool changes to take effect.


Ja führe die minimal-änderungen aus


todo

Minimal-Änderungen an Hermes-Konfiguration anwenden

MCP, Config und Gateway-Status verifizieren


terminal

set -e
hermes mcp remove openclaw || true
hermes config set prompt_caching.cache_ttl 1h
hermes config set compression.threshold 0.4
hermes config set compression.target_ratio 0.15
hermes config set compression.protect_last_n 16
hermes config set delegation.inherit_mcp_toolsets false
hermes gateway restart


Output:
Remove server 'openclaw'? [Y/n]:
  ✓ Removed 'openclaw' from config
  ✓ Cleaned up OAuth tokens
✓ Set prompt_caching.cache_ttl = 1h in /home/agent/.hermes/config.yaml
✓ Set compression.threshold = 0.4 in /home/agent/.hermes/config.yaml
✓ Set compression.target_ratio = 0.15 in /home/agent/.hermes/config.yaml
✓ Set compression.protect_last_n = 16 in /home/agent/.hermes/config.yaml
✓ Set delegation.inherit_mcp_toolsets = False in /home/agent/.hermes/config.yaml

[Command timed out after 180s]


[System note: Your previous turn in this session was interrupted by a gateway restart. The conversation history below is intact. If it contains unfinished tool result(s), process them first and summarize what was accomplished, then address the user's new message below.]


python - <<'PY'
import yaml, pathlib
p=pathlib.Path.home()/'.hermes/config.yaml'
d=yaml.safe_load(p.read_text()) or {}
for k in ['prompt_caching','compression','delegation','mcp_servers']:
 print(f'## {k}')
 print(yaml.safe_dump(d.get(k), sort_keys=False, allow_unicode=True))
PY


{"output": "No MCP servers configured.\n\n  Add one with:\n    hermes mcp add <name> --url <endpoint>\n    hermes mcp add <name> --command <cmd> --args <args...>", "exit_code": 0, "error": null}

[Subdirectory context discovered: .hermes/hermes-agent/AGENTS.md]
# Hermes Agent - Development Guide

Instructions for AI coding assistants and developers working on the hermes-agent codebase.

## Development Environment

```bash
# Prefer .venv; fall back to venv if that's what your checkout has.
source .venv/bin/activate   # or: source venv/bin/activate
```

`scripts/run_tests.sh` probes `.venv` first, then `venv`, then
`$HOME/.hermes/hermes-agent/venv` (for worktrees that share a venv with the
main checkout).

## Project Structure

File counts shift constantly — don't treat the tree below as exhaustive.
The canonical source is the filesystem. The notes call out the load-bearing
entry points you'll actually edit.

```
hermes-agent/
├── run_agent.py          # AIAgent class — core conversation loop (~12k LOC)
├── model_tools.py        # Tool orchestration, discover_builtin_tools(), handle_function_call()
├── toolsets.py           # Toolset definitions, _HERMES_CORE_TOOLS list
├── cli.py                # HermesCLI class — interactive CLI orchestrator (~11k LOC)
├── hermes_state.py       # SessionDB — SQLite session store (FTS5 search)
├── hermes_constants.py   # get_hermes_home(), display_hermes_home() — profile-aware paths
├── hermes_logging.py     # setup_logging() — agent.log / errors.log / gateway.log (profile-aware)
├── batch_runner.py       # Parallel batch processing
├── agent/                # Agent internals (provider adapters, memory, caching, compression, etc.)
├── hermes_cli/           # CLI subcommands, setup wizard, plugins loader, skin engine
├── tools/                # Tool implementations — auto-discovered via tools/registry.py
│   └── environments/     # Terminal backends (local, docker, ssh, modal, daytona, singularity)
├── gateway/              # Messaging gateway — run.py + session.py + platforms/
│   ├── platforms/        # Adapter per platform (telegram, discord, slack, whatsapp,
│   │                     #   homeassistant, signal, matrix, mattermost, email, sms,
│   │                     #   dingtalk, wecom, weixin, feishu, qqbot, bluebubbles,
│   │                     #   yuanbao, webhook, api_server, ...). See ADDING_A_PLATFORM.md.
│   └── builtin_hooks/    # Extension point for always-registered gateway hooks (none shipped)
├── plugins/              # Plugin system (see "Plugins" section below)
│   ├── memory/           # Memory-provider plugins (honcho, mem0, supermemory, ...)
│   ├── context_engine/   # Context-engine plugins
│   ├── model-providers/  # Inference backend plugins (openrouter, anthropic, gmi, ...)
│   ├── kanban/           # Multi-agent board dispatcher + worker plugin
│   ├── hermes-achievements/  # Gamified achievement tracking
│   ├── observability/    # Metrics / traces / logs plugin
│   ├── image_gen/        # Image-generation providers
│   └── <others>/         # disk-cleanup, example-dashboard, google_meet, platforms,
│                         #   spotify, strike-freedom-cockpit, ...
├── optional-skills/      # Heavier/niche skills shipped but NOT active by default
├── skills/               # Built-in skills bundled with the repo
├── ui-tui/               # Ink (React) terminal UI — `hermes --tui`
│   └── src/              # entry.tsx, app.tsx, gatewayClient.ts + app/components/hooks/lib
├── tui_gateway/          # Python JSON-RPC backend for the TUI
├── acp_adapter/          # ACP server (VS Code / Zed / JetBrains integration)
├── cron/                 # Scheduler — jobs.py, scheduler.py
├── environments/         # RL training environments (Atropos)
├── scripts/              # run_tests.sh, release.py, auxiliary scripts
├── website/              # Docusaurus docs site
└── tests/                # Pytest suite (~17k tests across ~900 files as of May 2026)
```

**User config:** `~/.hermes/config.yaml` (settings), `~/.hermes/.env` (API keys only).
**Logs:** `~/.hermes/logs/` — `agent.log` (INFO+), `errors.log` (WARNING+),
`gateway.log` when running the gateway. Profile-aware via `get_hermes_home()`.
Browse with `hermes logs [--follow] [--level ...] [--session ...]`.

## File Dependency Chain

```
tools/registry.py  (no deps — imported by all tool files)
       ↑
tools/*.py  (each calls registry.register() at import time)
       ↑
model_tools.py  (imports tools/registry + triggers tool discovery)
       ↑
run_agent.py, cli.py, batch_runner.py, environments/
```

---

## AIAgent Class (run_agent.py)

The real `AIAgent.__init__` takes ~60 parameters (credentials, routing, callbacks,
session context, budget, credential pool, etc.). The signature below is the
minimum subset you'll usually touch — read `run_agent.py` for the full list.

```python
class AIAgent:
    def __init__(self,
        base_url: str = None,
        api_key: str = None,
        provider: str = None,
        api_mode: str = None,              # "chat_completions" | "codex_responses" | ...
        model: str = "",                   # empty → resolved from config/provider later
        max_iterations: int = 90,          # tool-calling iterations (shared with subagents)
        enabled_toolsets: list = None,
        disabled_toolsets: list = None,
        quiet_mode: bool = False,
        save_trajectories: bool = False,
        platform: str = None,              # "cli", "telegram", etc.
        session_id: str = None,
        skip_context_files: bool = False,
        skip_memory: bool = False,
        credential_pool=None,
        # ... plus callbacks, thread/user/chat IDs, iteration_budget, fallback_model,
        # checkpoints config, prefill_messages, service_tier, reasoning_config, etc.
    ): ...

    def chat(self, message: str) -> str:
        """Simple interface — returns final response string."""

    def run_conversation(self, user_message: str, system_message: str = None,
                         conversation_history: list = None, task_id: str = None) -> dict:
        """Full interface — returns dict with final_response + messages."""
```

### Agent Loop

The core loop is inside `run_conversation()` — entirely synchronous, with
interrupt checks, budget tracking, and a one-turn grace call:

```python
while (api_call_count < self.max_iterations and self.iteration_budget.remaining > 0) \
        or self._budget_grace_call:
    if self._interrupt_requested: break
    response = client.chat.completions.create(model=model, messages=messages, tools=tool_schemas)
    if response.tool_calls:
        for tool_call in response.tool_calls:
            result = handle_function_call(tool_call.name, tool_call.args, task_id)
            messages.append(tool_result_message(result))
        api_call_count += 1
    else:
        return response.content
```

Messages follow OpenAI format: `{"role": "system/user/assistant/tool", ...}`.
Reasoning content is stored in `assistant_msg["reasoning"]`.

---

## CLI Architecture (cli.py)

- **Rich** for banner/panels, **prompt_toolkit** for input with autocomplete
- **KawaiiSpinner** (`agent/display.py`) — animated faces during API calls, `┊` activity feed for tool results
- `load_cli_config()` in cli.py merges hardcoded defaults + user config YAML
- **Skin engine** (`hermes_cli/skin_engine.py`) — data-driven CLI theming; initialized from `display.skin` config key at startup; skins customize banner colors, spinner faces/verbs/wings, tool prefix, response box, branding text
- `process_command()` is a method on `HermesCLI` — dispatches on canonical command name resolved via `resolve_command()` from the central registry
- Skill slash commands: `agent/skill_commands.py` scans `~/.hermes/skills/`, injects as **user message** (not system prompt) to preserve prompt caching

### Slash Command Registry (`hermes_cli/commands.py`)

All slash commands are defined in a central `COMMAND_REGISTRY` list of `CommandDef` objects. Every downstream consumer derives from this registry automatically:

- **CLI** — `process_command()` resolves aliases via `resolve_command()`, dispatches on canonical name
- **Gateway** — `GATEWAY_KNOWN_COMMANDS` frozenset for hook emission, `resolve_command()` f

[...truncated AGENTS.md: 45,468 chars total]


Output:
## prompt_caching
cache_ttl: 1h

## compression
enabled: true
threshold: 0.4
target_ratio: 0.15
protect_last_n: 16
hygiene_hard_message_limit: 400

## delegation
model: ''
provider: ''
base_url: ''
api_key: ''
inherit_mcp_toolsets: false
max_iterations: 50
child_timeout_seconds: 600
reasoning_effort: ''
max_concurrent_children: 3
max_spawn_depth: 1
orchestrator_enabled: true
subagent_auto_approve: false

## mcp_servers
null
...


Output:
● hermes-gateway.service - Hermes Agent Gateway - Messaging Platform Integration
     Loaded: loaded (/home/agent/.config/systemd/user/hermes-gateway.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-05-14 10:07:07 CEST; 16s ago
   Main PID: 295191 (python)
      Tasks: 10 (limit: 26309)
     Memory: 216.4M (peak: 216.7M)
        CPU: 3.978s
     CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/hermes-gateway.service
             ├─295191 /home/agent/.hermes/hermes-agent/venv/bin/python -m hermes_cli.main gateway run --replace
             ├─295244 /usr/bin/bash -c "source /tmp/hermes-snap-4138423eadbf.sh >/dev/null 2>&1 || true\nbuiltin cd -- /home/agent/.hermes/hermes-agent || exit 126\neval 'hermes gateway status'\n__hermes_ec=\$?\nexport -p > /tmp/hermes-snap-4138423eadbf.sh 2>/dev/null || true\npwd -P > /tmp/hermes-cwd-4138423eadbf.txt 2>/dev/null || true\nprintf '\\n__HERMES_CWD_4138423eadbf__%s__HERMES_CWD_4138423eadbf__\\n' \"\$(pwd -P)\"\nexit \$__hermes_ec"
             ├─295246 /home/agent/.hermes/hermes-agent/venv/bin/python3 /home/agent/.hermes/hermes-agent/venv/bin/hermes gateway status
             └─295251 systemctl --user status hermes-gateway --no-pager

Mai 14 10:07:07 agent systemd[911]: hermes-gateway.service: Scheduled restart job, restart counter is at 6.
Mai 14 10:07:07 agent systemd[911]: Started hermes-gateway.service - Hermes Agent Gateway - Messaging Platform Integration.
Mai 14 10:07:09 agent python[295191]: WARNING gateway.run: Secret redaction: DISABLED (HERMES_REDACT_SECRETS=false). API keys and tokens may appear verbatim in chat output, session JSONs, and logs. Set security.redact_secrets: true in config.yaml to re-enable.
✓ User gateway service is running
✓ Systemd linger is enabled (service survives logout)


Erledigt, Sir. Die Minimal-Änderungen wurden angewendet und verifiziert.

## Geändert

- **OpenClaw MCP entfernt**
  - Verifikation: `hermes mcp list` → `No MCP servers configured.`
  - Damit hängt OpenClaw nicht mehr als “all tools enabled”-MCP im Hermes-Kontext.

- **Prompt Cache TTL erhöht**
  - Alt: `5m`
  - Neu: `1h`

- **Compression etwas aggressiver gesetzt**
  - `compression.threshold: 0.4`
  - `compression.target_ratio: 0.15`
  - `compression.protect_last_n: 16`

- **Subagents erben keine MCP-Toolsets mehr automatisch**
  - `delegation.inherit_mcp_toolsets: false`

## Verifikation

Aktuelle relevante Config:

```yaml
prompt_caching:
  cache_ttl: 1h

compression:
  enabled: true
  threshold: 0.4
  target_ratio: 0.15
  protect_last_n: 16
  hygiene_hard_message_limit: 400

delegation:
  inherit_mcp_toolsets: false

mcp_servers: null
```

Gateway läuft wieder:

- Status: **active/running**
- Service: `hermes-gateway.service`
- Startzeit: 2026-05-14 10:07:07 CEST

Kleine Nebenbeobachtung: Der Restart-Befehl selbst wurde durch den Gateway-Neustart erwartbar unterbrochen — höflich formuliert: der Ast wurde abgesägt, während ich darauf sass. Die anschliessende Prüfung zeigt aber: **Gateway ist sauber wieder online.**