Hermes Agent is a production-grade, open-source AI-powered CLI assistant and multi-platform agent built by Nous Research. It provides a unified interface for interacting with large language models through a terminal REPL, a messaging gateway spanning 19 platforms, a web dashboard, IDE integration via the Agent Communication Protocol, and an OpenAI-compatible API server. The system is designed for both interactive use and autonomous operation, with scheduled tasks, batch processing, and delegated sub-agents.
The architecture is modular: a central AIAgent orchestrator manages conversation state, tool dispatch, context compression, and memory, while pluggable terminal backends (local, Docker, SSH, Modal, Singularity, Daytona) execute commands in isolated environments. The gateway layer adapts the agent to messaging platforms including Telegram, Discord, Slack, Matrix, WhatsApp, Signal, Email, SMS, and others. A plugin system supports memory providers and context engines, and a skills framework provides reusable prompt-driven capabilities.
This guide covers architecture, configuration, deployment, operations, security, and developer internals for system administrators and contributors working with Hermes Agent v0.9.0.
1. Architecture Overview
System Architecture
┌─────────────────────────────────┐
│ Entry Points │
│ cli.py hermes_cli/main.py │
│ gateway/run.py acp/__main__ │
└──────────┬──────────────────────┘
│
┌──────────▼──────────────────────┐
│ AIAgent Orchestrator │
│ (run_agent.py) │
│ ┌─────────────────────────┐ │
│ │ prompt_builder │ │
│ │ context_compressor │ │
│ │ memory_manager │ │
│ │ error_classifier │ │
│ │ credential_pool │ │
│ │ smart_model_routing │ │
│ │ anthropic_adapter │ │
│ │ auxiliary_client │ │
│ └─────────────────────────┘ │
└──────────┬──────────────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌──────────▼────────┐ ┌─────────▼─────────┐ ┌────────▼────────┐
│ Tool Registry │ │ Gateway Layer │ │ Cron Scheduler │
│ (model_tools.py) │ │ (gateway/run.py) │ │ (cron/scheduler)│
└──────────┬─────────┘ └─────────┬──────────┘ └─────────────────┘
│ │
┌──────────▼─────────┐ ┌────────▼──────────────────────────┐
│ Terminal Backends │ │ Platform Adapters (19) │
│ ┌───────────────┐ │ │ Telegram Discord Slack Matrix │
│ │ Local │ │ │ WhatsApp Signal Email SMS │
│ │ Docker │ │ │ Mattermost HASS DingTalk │
│ │ SSH │ │ │ Feishu WeCom Weixin QQ │
│ │ Modal │ │ │ BlueBubbles API Server │
│ │ Singularity │ │ │ Copilot (ACP) │
│ │ Daytona │ │ └───────────────────────────────────┘
│ └───────────────┘ │
│ Browser Providers │ ┌───────────────────────────────────┐
│ ┌───────────────┐ │ │ Web Dashboard (React/Vite) │
│ │ Browserbase │ │ │ ACP Adapter (IDE integration) │
│ │ BrowserUse │ │ │ MCP Server Mode │
│ │ Firecrawl │ │ │ Skills Engine │
│ └───────────────┘ │ │ Memory / Plugin System │
└────────────────────┘ └───────────────────────────────────┘
Component Inventory
| Component | Path | Role |
|---|---|---|
| AIAgent Orchestrator | run_agent.py |
Core agent loop: conversation management, tool dispatch, context compression, delegation |
| Agent Support Modules | agent/ (30 files) |
Anthropic adapter, prompt builder, context compressor, credential pool, error classifier, memory, routing, display |
| CLI Layer | hermes_cli/ (48 files) |
CLI subcommands, auth, config, profiles, plugins, gateway management, web server, skills hub |
| Gateway Core | gateway/ (15 files) |
Multi-platform messaging gateway: config, runner, delivery, hooks, pairing, channel directory |
| Platform Adapters | gateway/platforms/ (24 files) |
19 platform-specific messaging adapters |
| Tool Registry | tools/ |
Tool implementations, toolsets, browser providers |
| Terminal Backends | tools/environments/ (11 files) |
6 backends: local, Docker, SSH, Modal, ManagedModal, Singularity, Daytona |
| Cron Scheduler | cron/ (3 files) |
Scheduled task management and execution |
| Plugin System | plugins/ |
Memory providers, context engine, extensible plugin architecture |
| ACP Adapter | acp_adapter/ (9 files) |
Agent Communication Protocol for IDE integration |
| Web Dashboard | web/ |
React 19 / Vite 7 frontend for browser-based interaction |
| Documentation Site | website/ |
Docusaurus 3.9 documentation site |
| Session Store | hermes_state.py |
SQLite-based session persistence |
| Batch Runner | batch_runner.py |
Parallel batch processing with checkpointing |
| Skills | skills/, optional-skills/ |
100+ bundled skill definitions |
| Training Environments | environments/ |
Atropos RL training, benchmarks (TerminalBench2, TBLite, YC-Bench) |
Technology Stack
| Technology | Version | Purpose |
|---|---|---|
| Python | 3.10+ | Core runtime |
| Node.js | 20+ | Browser tools, WhatsApp bridge |
| OpenAI SDK | Latest | LLM provider interface |
| prompt_toolkit | Latest | Interactive REPL |
| rich | Latest | Terminal formatting and display |
| fire | Latest | CLI framework |
| httpx | Latest | Async HTTP client |
| tenacity | Latest | Retry logic |
| pydantic | Latest | Data validation |
| aiohttp | Latest | Async web server (gateway API) |
| React | 19 | Web dashboard frontend |
| Vite | 7 | Frontend build tooling |
| Tailwind CSS | 4 | Dashboard styling |
| Docusaurus | 3.9 | Documentation site |
| SQLite | WAL mode | Session and state persistence |
Data Flow
User Message
│
▼
prompt_builder ──► System prompt + skills + context files + memory + SOUL.md
│
▼
LLM Provider (OpenRouter / Anthropic / Nous / Codex / Ollama / Direct)
│
▼
Tool Dispatch (model_tools.py)
│
├──► Terminal execution (local / Docker / SSH / Modal / Singularity / Daytona)
├──► Browser interaction (Browserbase / BrowserUse / Firecrawl)
├──► File operations (read / write / search / glob)
└──► Web requests, memory, delegation
│
▼
Response Display (agent/display.py, rich formatting)
│
▼
Context Compression (if token count > threshold)
2. System Requirements
Runtime Dependencies
| Dependency | Version | Required | Purpose |
|---|---|---|---|
| Python | 3.10+ | Yes | Core runtime |
| pip | Latest | Yes | Package management |
| Git | Latest | Yes | Repository operations, self-update |
| Node.js | 20+ | No | Browser tools, WhatsApp bridge |
| ffmpeg | Latest | No | Voice mode audio processing |
| Docker | Latest | No | Docker terminal backend |
| SSH client | Latest | No | SSH terminal backend |
| Ollama | Latest | No | Local model inference |
Install Extras
pip install hermes-agent # Core
pip install hermes-agent[all] # All optional dependencies
pip install hermes-agent[web] # Web dashboard
pip install hermes-agent[voice] # Voice input/output
pip install hermes-agent[mcp] # MCP server mode
pip install hermes-agent[bedrock] # AWS Bedrock adapter
pip install hermes-agent[yc-bench] # YC-Bench environment
Platform-Specific Notes
| Platform | Notes |
|---|---|
| Linux | Primary development target. Full feature support. |
| macOS | Full support. Homebrew formula available in packaging/homebrew/. |
| Windows | Requires Git Bash for terminal operations. Native cmd/PowerShell not fully supported. |
| WSL | Fully supported under Windows Subsystem for Linux. |
| Termux (Android) | Supported with caveats; limited terminal backend options. |
| NixOS | flake.nix included in repository root for Nix-based installation. |
Hardware
No GPU required for the agent itself. Any modern CPU and 2+ GB RAM suffice. GPU is only relevant when running local models through Ollama or similar inference backends. Browser tools may benefit from additional memory depending on page complexity.
3. Configuration Reference
Important
Configuration is resolved in a strict precedence order: environment variables > config.yaml > legacy files > hardcoded defaults. Environment variables always win.
3.1 Config Files
| File | Location | Purpose |
|---|---|---|
config.yaml |
~/.hermes/config.yaml |
Primary configuration file |
.env |
~/.hermes/.env |
Secrets and environment variable overrides |
SOUL.md |
~/.hermes/SOUL.md |
System prompt personality customization |
auth.json |
~/.hermes/auth.json |
Credential store (file-locked) |
gateway.json |
~/.hermes/gateway.json |
Legacy gateway config (merged into config.yaml) |
jobs.json |
~/.hermes/cron/jobs.json |
Scheduled task definitions |
.hermes.md |
Project root | Per-project context file |
HERMES.md |
Project root | Per-project context file (alternative name) |
AGENTS.md |
Project root | Per-project agent instructions |
3.2 Config YAML Structure
Full annotated ~/.hermes/config.yaml:
# ── Model Configuration ──
model:
default: "" # Model name (e.g., anthropic/claude-sonnet-4)
base_url: "" # Custom OpenAI-compatible endpoint URL
provider: "auto" # Provider: auto|openrouter|anthropic|nous|codex|ollama|direct
# ── Terminal Backend ──
terminal:
backend: "local" # Backend: local|docker|ssh|modal|singularity|daytona
cwd: "." # Working directory for terminal sessions
timeout: 60 # Per-command timeout in seconds
lifetime_seconds: 300 # Terminal session lifetime before recycling
docker_image: "nikolaik/python-nodejs:python3.11-nodejs20" # Docker image
docker_forward_env: [] # Env vars to forward into Docker container
docker_volumes: [] # Volume mounts (host:container format)
docker_mount_cwd_to_workspace: false # Mount host CWD into container /workspace
singularity_image: "" # Singularity/Apptainer image path
modal_image: "" # Modal cloud image
daytona_image: "" # Daytona workspace image
ssh_host: "" # SSH backend hostname
ssh_user: "" # SSH backend username
ssh_port: 22 # SSH backend port
ssh_key: "" # SSH private key path
container_cpu: "" # CPU limit for container backends
container_memory: "" # Memory limit for container backends
container_disk: "" # Disk limit for container backends
container_persistent: "" # Persistent storage mount
sandbox_dir: "" # Sandboxed working directory
persistent_shell: "" # Maintain shell state between commands
sudo_password: "" # Sudo password for privilege escalation
# ── Browser Configuration ──
browser:
inactivity_timeout: 120 # Close browser after N seconds idle
record_sessions: false # Record browser sessions for replay
# ── Context Compression ──
compression:
enabled: true # Enable automatic context compression
threshold: 0.50 # Compress when usage exceeds this fraction of context window
# ── Smart Model Routing ──
smart_model_routing:
enabled: false # Route simple queries to cheaper model
max_simple_chars: 160 # Max character count for "simple" classification
max_simple_words: 28 # Max word count for "simple" classification
cheap_model: # Target model for simple queries
model: ""
base_url: ""
api_key: ""
# ── Agent Behavior ──
agent:
max_turns: 90 # Maximum conversation turns before stopping
verbose: false # Verbose agent logging
system_prompt: "" # Override default system prompt
prefill_messages_file: "" # JSON file with pre-seeded conversation
reasoning_effort: "" # Thinking budget: none|minimal|low|medium|high|xhigh
service_tier: "" # API tier: normal|fast|priority
personalities: # Named personality presets
default: {}
concise: {}
creative: {}
# ── Display Settings ──
display:
compact: false # Compact output formatting
resume_display: "full" # Session resume display: full|summary|none
show_reasoning: false # Show model reasoning/thinking tokens
streaming: true # Stream responses token-by-token
busy_input_mode: "interrupt" # Behavior when input arrives mid-generation
skin: "default" # Display skin/theme
# ── Clarification ──
clarify:
timeout: 120 # Timeout for clarification prompts (seconds)
# ── Code Execution ──
code_execution:
timeout: 300 # Maximum code execution time (seconds)
max_tool_calls: 50 # Maximum tool calls per turn
# ── Auxiliary Models ──
auxiliary:
vision: # Vision model for image analysis
provider: "auto"
model: ""
base_url: ""
api_key: ""
web_extract: # Model for web content extraction
provider: "auto"
model: ""
base_url: ""
api_key: ""
approval: # Model for approval/review workflows
provider: "auto"
model: ""
base_url: ""
api_key: ""
# ── Delegation ──
delegation:
max_iterations: 45 # Max iterations for delegated sub-agents
default_toolsets: ["terminal", "file", "web"] # Toolsets available to delegates
model: "" # Override model for delegates
provider: "" # Override provider for delegates
base_url: "" # Override endpoint for delegates
api_key: "" # Override API key for delegates
3.3 Environment Variables
Core
| Variable | Purpose | Default |
|---|---|---|
HERMES_HOME |
Data directory | ~/.hermes |
HERMES_QUIET |
Suppress non-essential output | unset |
HERMES_DEV |
Development mode (extra logging) | unset |
HERMES_MANAGED |
Running in managed/container mode | unset |
HERMES_YOLO_MODE |
Skip all confirmation prompts | unset |
HERMES_REDACT_SECRETS |
Enable secret redaction in output | unset |
HERMES_MAX_ITERATIONS |
Override max agent turns | 90 |
HERMES_RESTART_DRAIN_TIMEOUT |
Gateway drain timeout on restart (seconds) | unset |
Model / Provider
| Variable | Purpose |
|---|---|
OPENROUTER_API_KEY |
OpenRouter API key |
OPENROUTER_BASE_URL |
OpenRouter endpoint override |
OPENAI_API_KEY |
OpenAI API key |
OPENAI_BASE_URL |
OpenAI-compatible endpoint override |
ANTHROPIC_API_KEY |
Anthropic API key |
ANTHROPIC_TOKEN |
Anthropic OAuth/setup token (alternative to API key) |
CLAUDE_CODE_OAUTH_TOKEN |
Claude Code OAuth token |
NOUS_INFERENCE_BASE_URL |
Nous Portal inference endpoint |
AI_GATEWAY_API_KEY |
AI Gateway API key |
AI_GATEWAY_BASE_URL |
AI Gateway base URL |
OLLAMA_BASE_URL |
Ollama endpoint URL |
OLLAMA_API_KEY |
Ollama Cloud API key |
CUSTOM_API_KEY |
Custom provider API key |
Terminal
| Variable | Purpose |
|---|---|
TERMINAL_ENV |
Terminal environment type |
TERMINAL_CWD |
Working directory override |
TERMINAL_TIMEOUT |
Command timeout override |
TERMINAL_SSH_HOST |
SSH backend host |
TERMINAL_SSH_USER |
SSH backend user |
TERMINAL_SSH_PORT |
SSH backend port |
TERMINAL_SSH_KEY |
SSH backend key path |
TERMINAL_DOCKER_IMAGE |
Docker image override |
TERMINAL_DOCKER_FORWARD_ENV |
Env vars to forward to Docker |
TERMINAL_DOCKER_VOLUMES |
Volume mounts for Docker |
Browser
| Variable | Purpose |
|---|---|
BROWSER_CDP_URL |
Chrome DevTools Protocol URL |
BROWSER_USE_API_KEY |
BrowserUse service key |
BROWSERBASE_API_KEY |
Browserbase service key |
BROWSERBASE_PROJECT_ID |
Browserbase project ID |
FIRECRAWL_API_KEY |
Firecrawl service key |
Gateway Platform Credentials
| Variable | Purpose |
|---|---|
TELEGRAM_BOT_TOKEN |
Telegram bot token |
TELEGRAM_ALLOWED_USERS |
Comma-separated allowed user IDs |
DISCORD_BOT_TOKEN |
Discord bot token |
DISCORD_ALLOWED_USERS |
Comma-separated allowed user IDs |
SLACK_BOT_TOKEN |
Slack bot OAuth token |
SLACK_APP_TOKEN |
Slack app-level token (Socket Mode) |
SLACK_ALLOWED_USERS |
Comma-separated allowed user IDs |
SIGNAL_HTTP_URL |
Signal REST API URL |
SIGNAL_ACCOUNT |
Signal account identifier |
MATRIX_HOMESERVER |
Matrix server URL |
MATRIX_USER_ID |
Matrix user ID |
MATRIX_PASSWORD |
Matrix password |
MATRIX_ACCESS_TOKEN |
Matrix access token |
MATTERMOST_URL |
Mattermost server URL |
MATTERMOST_TOKEN |
Mattermost bot token |
EMAIL_IMAP_HOST |
IMAP server hostname |
EMAIL_SMTP_HOST |
SMTP server hostname |
EMAIL_ADDRESS |
Email account address |
EMAIL_PASSWORD |
Email account password |
TWILIO_ACCOUNT_SID |
Twilio account SID |
TWILIO_AUTH_TOKEN |
Twilio auth token |
TWILIO_PHONE_NUMBER |
Twilio phone number |
SMS_INSECURE_NO_SIGNATURE |
Disable Twilio webhook signature validation (testing only) |
HASS_URL |
Home Assistant URL |
HASS_TOKEN |
Home Assistant long-lived token |
DINGTALK_CLIENT_ID |
DingTalk client ID |
DINGTALK_CLIENT_SECRET |
DingTalk client secret |
FEISHU_APP_ID |
Feishu/Lark app ID |
FEISHU_APP_SECRET |
Feishu/Lark app secret |
WECOM_BOT_ID |
WeCom bot ID (bot mode) |
WECOM_SECRET |
WeCom bot secret (bot mode) |
WECOM_CALLBACK_CORP_ID |
WeCom corp ID (callback mode) |
WECOM_CALLBACK_CORP_SECRET |
WeCom corp secret (callback mode) |
WECOM_CALLBACK_AGENT_ID |
WeCom agent ID (callback mode) |
WECOM_CALLBACK_TOKEN |
WeCom callback verification token |
WECOM_CALLBACK_ENCODING_AES_KEY |
WeCom callback AES encryption key |
WEIXIN_ACCOUNT_ID |
Weixin account ID |
WEIXIN_TOKEN |
Weixin token |
WEIXIN_BASE_URL |
Weixin iLink Bot API base URL |
QQ_APP_ID |
QQ bot app ID |
QQ_CLIENT_SECRET |
QQ bot client secret |
BLUEBUBBLES_SERVER_URL |
BlueBubbles server URL |
BLUEBUBBLES_PASSWORD |
BlueBubbles server password |
WHATSAPP_ENABLED |
Enable WhatsApp bridge |
WHATSAPP_ALLOWED_USERS |
Comma-separated allowed WhatsApp users |
WHATSAPP_FREE_RESPONSE_CHATS |
Chats where Hermes responds without mention |
WHATSAPP_REQUIRE_MENTION |
Require mention to respond (default: false) |
Gateway Behavior
| Variable | Purpose |
|---|---|
SESSION_IDLE_MINUTES |
Idle timeout before session reset |
SESSION_RESET_HOUR |
Hour (0-23) for daily session reset |
WEBHOOK_SECRET |
HMAC secret for webhook validation |
API_SERVER_PORT |
API server listen port (default: 8642) |
API_SERVER_HOST |
API server bind address |
GATEWAY_ALLOW_ALL_USERS |
Allow all users without pairing (dangerous) |
Memory
| Variable | Purpose |
|---|---|
HONCHO_BASE_URL |
Honcho memory service URL |
HONCHO_API_KEY |
Honcho API key |
HONCHO_ENVIRONMENT |
Honcho environment (production default) |
HONCHO_TIMEOUT |
Honcho request timeout |
HINDSIGHT_API_KEY |
Hindsight Cloud API key |
HINDSIGHT_LLM_API_KEY |
LLM API key for Hindsight local mode |
HINDSIGHT_API_URL |
Hindsight API endpoint override |
HINDSIGHT_MODE |
Hindsight mode (cloud, local_embedded, local_external) |
Display
| Variable | Purpose |
|---|---|
NO_COLOR |
Disable colored output |
TERM |
Terminal type for capability detection |
3.4 CLI Flags
Main Command (hermes)
| Flag | Short | Purpose |
|---|---|---|
--quiet |
-q |
Suppress non-essential output |
--model |
-m |
Override model name |
--task |
-t |
Non-interactive: run single task and exit |
--source |
-s |
Source directory to operate on |
--verbose |
-v |
Enable verbose logging |
--quick-task |
-Q |
Minimal context task |
--resume |
-r |
Resume previous session |
--continue |
-c |
Continue last session |
--workspace |
-w |
Set working directory |
--checkpoints |
Enable conversation checkpoints | |
--max-turns |
Override max conversation turns | |
--yolo |
Skip all confirmation prompts | |
--pass-session-id |
Provide explicit session ID | |
--image |
Attach image to initial prompt |
Gateway Commands
| Flag | Purpose |
|---|---|
--config |
Path to gateway config file |
--verbose |
Verbose gateway logging |
--replace |
Replace existing gateway instance |
--system |
Install as system-level service |
--all |
Apply to all platforms |
--deep |
Deep health check |
--force |
Force operation without confirmation |
--run-as-user |
Run gateway service as specified user |
Auth Commands
| Flag | Purpose |
|---|---|
--provider |
Auth provider name |
--portal-url |
OAuth portal URL |
--inference-url |
Inference endpoint URL |
--client-id |
OAuth client ID |
--scope |
OAuth scope |
--no-browser |
Manual auth flow (no browser launch) |
--timeout |
Auth flow timeout |
--ca-bundle |
CA certificate bundle path |
--insecure |
Skip TLS verification |
4. Deployment & Scaling
Docker
The repository includes a Dockerfile and docker/entrypoint.sh for containerized deployment.
docker build -t hermes-agent .
docker run -it \
-e ANTHROPIC_API_KEY=sk-ant-... \
-e HERMES_HOME=/opt/data \
-v ~/.hermes:/opt/data \
hermes-agent
Note
The entrypoint script handles privilege dropping (via
HERMES_UID/HERMES_GID), virtual environment activation, directory creation, and skill synchronization automatically.HERMES_HOMEdefaults to/opt/datainside the container.
Key Docker behaviors:
- Security:
cap-drop ALLwith selective add-back ofDAC_OVERRIDE,CHOWN,FOWNER no-new-privilegesenforced- PID limit of 256
- Non-root execution via UID/GID mapping
Gateway as System Service
Install the gateway as a persistent systemd service:
# User-level service
hermes gateway install
# System-level service (requires root)
hermes gateway install --system
# Non-root execution
hermes gateway install --run-as-user hermes
Once installed, the gateway starts automatically on boot and restarts on failure. Manage with standard systemctl commands or hermes gateway start/stop/restart/status.
Nix
A flake.nix is provided for NixOS and nix-darwin users:
nix develop # Enter development shell
nix build # Build package
nix run .#hermes # Run directly
Homebrew
A Homebrew formula is available in packaging/homebrew/:
brew install --formula ./packaging/homebrew/hermes-agent.rb
Batch Processing
batch_runner.py enables parallel dataset processing for training data generation and evaluation:
- Configurable parallelism
- Automatic checkpointing for resumability
- Per-item tool call statistics
- Trajectory saving for analysis
- Example configs in
datagen-config-examples/
hermes batch --config datagen-config-examples/example.yaml
5. Operations
Gateway Management
hermes gateway start # Start all configured platforms
hermes gateway stop # Graceful shutdown
hermes gateway restart # Restart with drain period
hermes gateway status # Show running platforms
hermes gateway status --deep # Deep health check (connectivity test)
Tip
Set
HERMES_RESTART_DRAIN_TIMEOUTto control how long the gateway waits for in-flight messages to complete before restarting. This prevents message loss during rolling restarts.
Platform-specific management:
hermes gateway pair telegram # Generate pairing code for Telegram
hermes gateway unpair telegram <user> # Remove paired user
hermes gateway mirror add # Configure cross-platform message mirroring
hermes gateway channels # List active channels
Session Management
Sessions are stored in SQLite (WAL mode) via SessionDB in hermes_state.py.
hermes sessions list # List all sessions
hermes sessions browse <id> # Browse session conversation
hermes sessions search "query" # Full-text search across sessions
hermes sessions export <id> # Export session as JSON
hermes sessions delete <id> # Delete specific session
hermes sessions prune --before 30d # Remove sessions older than 30 days
hermes sessions rename <id> "name" # Rename a session
hermes sessions analytics # Cross-session behavioral analytics
Session key format: agent:main:{platform}:{chat_type}:{chat_id}
Cron Operations
Note
Cron jobs support per-job model and provider overrides, a grace window system for missed executions, and a script parameter for injecting dynamic context at execution time.
hermes cron list # List all scheduled jobs
hermes cron create # Create new job interactively
hermes cron edit <id> # Edit existing job
hermes cron pause <id> # Pause job
hermes cron resume <id> # Resume paused job
hermes cron run <id> # Run job immediately
hermes cron remove <id> # Delete job
hermes cron status # Scheduler status
hermes cron tick # Manual tick (check and run due jobs)
Job definitions live in ~/.hermes/cron/jobs.json.
Monitoring & Diagnostics
hermes logs agent # View agent logs
hermes logs errors # View error logs only
hermes logs gateway # View gateway logs
hermes logs agent -f # Follow (tail) logs
hermes logs agent --level ERROR # Filter by level
hermes logs agent --since 1h # Filter by time
hermes logs agent --component gateway # Filter by component
hermes doctor # Run diagnostic checks
hermes debug # Generate paste-able debug report
hermes status # System status overview
Backup & Restore
hermes backup # Full backup (zip archive)
hermes backup --quick # Snapshot of critical files only (config, auth, sessions)
hermes import <zipfile> # Restore from backup
Tip
Schedule regular backups via
hermes cron createwith the backup command. The--quickflag is suitable for frequent snapshots while the full backup captures sessions, skills, and plugins.
Updates
hermes update # Pull latest from git, auto-stash local changes
The update command automatically stashes local modifications, pulls changes, restores stashed files, and restarts the gateway if it was running.
6. Performance
Context Compression
The ContextCompressor (agent/context_compressor.py) automatically manages conversation context to prevent exceeding model token limits.
Algorithm:
- Monitor token usage against context window size
- When usage exceeds threshold (default: 50% of context limit), trigger compression
- Prune old tool results first (largest token savings)
- Protect head of conversation (system prompt, initial context)
- Protect tail (~20K tokens of recent context)
- Summarize middle section via LLM call
- Replace original messages with compressed version
Configure via:
compression:
enabled: true
threshold: 0.50 # Trigger at 50% context usage
Manual compression: use the /compress slash command in the REPL.
Smart Model Routing
Routes simple, short queries to a cheaper/faster model to reduce cost and latency.
smart_model_routing:
enabled: true
max_simple_chars: 160
max_simple_words: 28
cheap_model:
model: "anthropic/claude-haiku-3"
base_url: ""
api_key: ""
Classification: messages under both the character and word thresholds, containing no code blocks or complex formatting, are routed to the cheap model.
Prompt Caching
The Anthropic adapter (agent/anthropic_adapter.py) adds cache_control markers to system prompts and long context blocks. Gateway sessions benefit from per-session agent caching, which maximizes cache hit rates for repeated conversations.
Thinking Budget (Anthropic Models)
Reasoning effort controls the thinking budget for Anthropic models:
| Level | Budget |
|---|---|
none |
Thinking disabled |
minimal |
Minimal thinking |
low |
~4K thinking tokens |
medium |
~8K thinking tokens |
high |
~16K thinking tokens |
xhigh |
~32K thinking tokens |
For Claude 4.6, the adapter supports adaptive thinking (model self-selects budget). For older models, the budget is set explicitly.
Set via config or CLI:
agent:
reasoning_effort: "medium"
7. Security
Warning
The gateway exposes your agent to external messaging platforms. Always configure per-platform allowed users and never set
GATEWAY_ALLOW_ALL_USERS=truein production.
Secret Redaction
Enable HERMES_REDACT_SECRETS to scrub API keys, tokens, and passwords from agent output and logs. The agent/redact.py module performs pattern-based redaction.
Caution
Issue #11009 documents a race condition where config is not fully applied before the redact module is imported. Secrets in very early startup output may not be redacted. Set the environment variable before process launch rather than relying on config.yaml.
Credential Store
Credentials are stored in ~/.hermes/auth.json with file-level advisory locking to prevent corruption from concurrent access.
The CredentialPool (agent/credential_pool.py) manages multiple API keys per provider with configurable rotation strategies:
| Strategy | Behavior |
|---|---|
fill-first |
Use primary key until rate-limited, then next |
round-robin |
Cycle through keys sequentially |
least-used |
Route to key with lowest usage count |
random |
Random key selection per request |
Gateway Security
DM Pairing System:
- 8-character alphanumeric pairing codes
- 1-hour code expiry
- Rate limiting on pairing attempts
- Account lockout after 5 failed attempts
- Pairing file permissions set to
chmod 0600
Per-Platform Access Control:
Each platform adapter supports an allowed-users list via environment variable (e.g., TELEGRAM_ALLOWED_USERS, DISCORD_ALLOWED_USERS).
SSRF Protection:
Media download functions in base.py, feishu.py, wecom.py, weixin.py, qqbot.py, and slack.py include SSRF protection against internal network access via URL validation.
Prompt Injection Detection
Context files (.hermes.md, HERMES.md, AGENTS.md) are scanned on load for:
- Invisible unicode characters (zero-width spaces, homoglyphs)
- Data exfiltration patterns (encoded URLs, base64 payloads)
- System prompt override attempts
File Access Control
- Sensitive credential files (
auth.json,.env, SSH keys) are blocked from context file attachment - Path traversal patterns are rejected
- Workspace boundary enforcement prevents reads outside the designated project directory
Docker Security
When using the Docker terminal backend:
cap-drop ALLremoves all Linux capabilities- Only
DAC_OVERRIDE,CHOWN,FOWNERare added back no-new-privilegesflag prevents privilege escalation- PID limit of 256 constrains fork bombs
Webhook Security
Inbound webhooks require HMAC signature validation via the WEBHOOK_SECRET environment variable. The SMS_INSECURE_NO_SIGNATURE flag disables Twilio signature validation for local testing only.
Warning
Never set
SMS_INSECURE_NO_SIGNATUREin production. This completely disables webhook authentication for the SMS/Twilio adapter, allowing anyone to inject messages.
Web Dashboard Security
- Binds to
localhostonly by default --insecureflag required to bind to non-localhost addresses- Session-token authentication
- Rate-limited secret reveal endpoints
8. Developer Internals
Repository Structure
hermes-agent/
├── cli.py # Legacy CLI entry point
├── run_agent.py # AIAgent orchestrator (~3600 lines)
├── model_tools.py # Tool registry dispatcher
├── toolsets.py # Composable tool groups
├── toolset_distributions.py # Probabilistic sampling for batch
├── batch_runner.py # Parallel batch processing
├── hermes_constants.py # Shared constants
├── hermes_logging.py # Centralized logging
├── hermes_state.py # SessionDB (SQLite)
├── hermes_time.py # Timezone handling
├── mcp_serve.py # MCP server mode
├── mini_swe_runner.py # Minimal SWE runner
├── trajectory_compressor.py # Trajectory compression
├── utils.py # Utilities
├── agent/ # Agent support modules (30 files)
│ ├── anthropic_adapter.py # Anthropic API adapter
│ ├── auxiliary_client.py # Auxiliary model client
│ ├── context_compressor.py # Context window compression
│ ├── prompt_builder.py # System prompt assembly
│ ├── model_metadata.py # Model capability registry
│ ├── display.py # Output formatting
│ ├── error_classifier.py # Error categorization
│ ├── credential_pool.py # Multi-key rotation
│ ├── rate_limit_tracker.py # Rate limit tracking
│ ├── usage_pricing.py # Token cost calculation
│ ├── smart_model_routing.py # Simple query routing
│ ├── memory_manager.py # Memory operations
│ ├── trajectory.py # Conversation trajectory
│ ├── skill_commands.py # Skill dispatch
│ ├── insights.py # Behavioral analytics
│ ├── bedrock_adapter.py # AWS Bedrock support
│ ├── copilot_acp_client.py # Copilot ACP client
│ └── redact.py # Secret redaction
├── hermes_cli/ # CLI commands & config (48 files)
│ ├── main.py # CLI router and REPL
│ ├── auth.py # Authentication management
│ ├── config.py # Config file handling
│ ├── profiles.py # Named config profiles
│ ├── plugins.py # Plugin management
│ ├── web_server.py # Web dashboard server
│ ├── skills_hub.py # Skills marketplace
│ ├── mcp_config.py # MCP configuration
│ ├── doctor.py # Diagnostic checks
│ ├── debug.py # Debug report generation
│ └── backup.py # Backup/restore
├── gateway/ # Gateway core (15 files)
│ ├── run.py # GatewayRunner controller
│ ├── config.py # GatewayConfig manager
│ ├── delivery.py # Message delivery pipeline
│ ├── hooks.py # Lifecycle hooks
│ ├── pairing.py # DM pairing system
│ ├── mirror.py # Cross-platform mirroring
│ ├── channel_directory.py # Channel registry
│ ├── display_config.py # Platform display settings
│ ├── status.py # Gateway status tracking
│ └── platforms/ # Platform adapters (24 files)
│ ├── base.py # BasePlatformAdapter ABC
│ ├── telegram.py # Telegram adapter
│ ├── discord_platform.py # Discord adapter
│ ├── slack.py # Slack adapter
│ ├── matrix_platform.py # Matrix adapter
│ ├── whatsapp.py # WhatsApp Cloud API
│ ├── whatsapp_baileys.py # WhatsApp via Baileys
│ ├── signal_platform.py # Signal adapter
│ ├── email_platform.py # Email (IMAP/SMTP)
│ ├── sms.py # SMS via Twilio
│ ├── mattermost.py # Mattermost adapter
│ ├── hass.py # Home Assistant
│ ├── dingtalk.py # DingTalk adapter
│ ├── feishu.py # Feishu/Lark adapter
│ ├── wecom.py # WeCom adapter
│ ├── weixin.py # Weixin adapter
│ ├── qqbot.py # QQ adapter
│ ├── bluebubbles.py # BlueBubbles (iMessage)
│ └── api_server.py # OpenAI-compatible API server
├── tools/ # Tool implementations
│ ├── environments/ # Terminal backends (11 files)
│ │ ├── base.py # BaseEnvironment ABC
│ │ ├── local.py # Local shell execution
│ │ ├── docker_env.py # Docker container
│ │ ├── ssh_env.py # SSH remote execution
│ │ ├── modal_env.py # Modal cloud
│ │ ├── managed_modal_env.py # Managed Modal
│ │ ├── singularity_env.py # Singularity/Apptainer
│ │ └── daytona_env.py # Daytona workspace
│ └── browser_providers/ # Browser cloud providers (5 files)
│ ├── browserbase.py # Browserbase
│ ├── browseruse.py # BrowserUse
│ └── firecrawl.py # Firecrawl
├── cron/ # Scheduler (3 files)
│ ├── scheduler.py # CronScheduler
│ ├── job.py # Job definition
│ └── manager.py # Job CRUD
├── plugins/ # Plugin system
│ ├── memory/ # Memory providers
│ └── context_engine/ # Context engine plugin
├── environments/ # RL training environments
│ ├── benchmarks/ # TBLite, TB2, YC-Bench
│ └── tool_call_parsers/ # Phase 2 parsers
├── acp_adapter/ # ACP for IDE integration (9 files)
├── web/ # React dashboard frontend
├── website/ # Docusaurus docs site
├── skills/ # Bundled skills (100+)
├── optional-skills/ # Optional installable skills
├── docker/ # Docker entrypoint
├── packaging/ # Homebrew formula
├── nix/ # Nix support
├── tests/ # Test suite
└── datagen-config-examples/ # Batch config examples
Module Reference
run_agent.py — AIAgent
The central orchestrator class (~3600 lines). Manages the complete agent lifecycle:
- Conversation loop: message dispatch, response streaming, tool call handling
- Tool dispatch: routes tool calls to registered tool implementations via
model_tools.py - Context management: tracks token usage, triggers compression when threshold exceeded
- Memory: integrates with memory providers for cross-session recall
- Delegation: spawns sub-agents with constrained toolsets and iteration limits
- Session persistence: saves/restores conversation state via
SessionDB - Checkpoint system: periodic conversation snapshots for recovery
Key methods: run(), process_message(), handle_tool_call(), delegate(), compress_context()
Dependencies: agent/*, model_tools, hermes_state, toolsets
agent/anthropic_adapter.py
Adapter for the Anthropic API. Handles:
- Message format conversion (OpenAI format to Anthropic format)
- Prompt caching with
cache_controlmarkers - Thinking budget management (reasoning effort levels)
- Streaming response handling
- Extended thinking token extraction
agent/auxiliary_client.py
Client for auxiliary model calls (vision analysis, web content extraction, approval workflows). Configurable per-task model/provider/endpoint. Falls back through provider chain if primary fails.
agent/context_compressor.py
Implements the ContextCompressor class. Algorithm: monitor token count against context window, prune tool results, protect head and tail (~20K tokens), summarize middle via LLM. Exposes both automatic (threshold-based) and manual (/compress) compression.
agent/prompt_builder.py
Assembles the complete system prompt from components:
- Base system prompt (or custom override)
SOUL.mdpersonality file- Active skills with their instructions
- Context files (
.hermes.md,HERMES.md,AGENTS.md) - Memory context from providers
- Tool descriptions for the active toolset
- Active environment metadata
agent/credential_pool.py
CredentialPool class manages multiple API keys per provider. Supports rotation strategies (fill-first, round-robin, least-used, random). Tracks per-key usage counts and rate limit state. Thread-safe with advisory file locking.
agent/error_classifier.py
Categorizes errors from LLM providers and tool execution into actionable classes: rate limit, authentication failure, context overflow, network error, invalid request, server error, timeout. Used by retry logic in tenacity decorators to determine backoff strategy and whether to rotate credentials.
hermes_cli/main.py
The CLI router. Implements the interactive REPL via prompt_toolkit and routes subcommands (gateway, sessions, cron, auth, config, plugins, skills, doctor, debug, backup, update, etc.) to their respective handler modules. Contains load_cli_config() implementing the full config resolution chain (env > yaml > legacy > defaults).
hermes_cli/auth.py
Authentication management: OAuth flows with browser-based and --no-browser fallback, credential storage in auth.json with file locking, provider-specific login/logout flows, token refresh and expiry tracking.
hermes_cli/config.py
Config file handling: load, save, validate, merge. Implements the multi-layer config resolution chain. Supports hermes config get/set/list/edit/reset subcommands for interactive configuration management.
hermes_cli/profiles.py
Named configuration profiles allowing quick switching between pre-configured sets of model, provider, terminal backend, and behavior settings. Profiles are stored as named sections within the config file.
hermes_cli/plugins.py
Plugin discovery, installation, activation, and lifecycle management. Plugins are Python packages following a defined interface with register() and activate() entry points.
hermes_cli/web_server.py
Serves the React web dashboard. Localhost-only by default, with --insecure override for network access. Handles session-token authentication and proxies API calls to the agent backend.
gateway/run.py — GatewayRunner
The gateway controller. Manages platform adapter lifecycle:
- Loads
GatewayConfig, instantiates configured platform adapters - Starts adapters concurrently via asyncio
- Routes inbound messages to agent sessions (keyed by platform + chat ID)
- Handles graceful shutdown with configurable drain timeout
- Restart support with message draining to prevent loss
gateway/config.py — GatewayConfig
Gateway configuration manager. Merges config sources (config.yaml gateway section, legacy gateway.json, environment variables, CLI flags). Validates platform configurations and resolves credential references. Determines which platforms to activate based on available credentials.
gateway/platforms/base.py — BasePlatformAdapter
Abstract base class defining the interface for all 19 platform adapters:
start()/stop()— adapter lifecycle managementsend_message()— outbound message delivery with platform-native formattingon_message()— inbound message callback registrationhealth_check()— connectivity and credential validation- Media download with SSRF protection (URL validation against internal networks)
- Markdown-to-platform format conversion
tools/environments/base.py — BaseEnvironment
Abstract base class for terminal backends:
execute(command, timeout)— run command, return stdout/stderr/exit_codestart()/stop()— backend lifecycle (container creation, SSH connection, etc.)upload_file()/download_file()— file transfer between host and environmentget_cwd()— current working directory query- Resource limit properties (CPU, memory, disk)
Code Patterns
| Pattern | Where Used | Description |
|---|---|---|
| Filesystem as state machine | Sessions, cron, auth, pairing | State persisted to files; transitions via atomic file operations |
| Atomic file operations | Auth, config, sessions | Write to temp file, then os.replace() for crash safety |
| File-based advisory locks | Credential store, session DB | Cross-process coordination without external lock service |
| Platform adapter pattern | gateway/platforms/ |
BasePlatformAdapter ABC with 19 concrete implementations |
| Multi-layer config resolution | hermes_cli/config.py |
env > config.yaml > legacy > defaults |
| Provider fallback chain | Model routing | OpenRouter > Nous > Codex > Anthropic > Direct |
| Retry with classification | Error handling | error_classifier.py categorizes errors; tenacity retries with strategy-specific backoff |
| Composable toolsets | toolsets.py |
Named groups of tools (terminal, file, web) composed per-session or per-delegation |
Testing
Test structure mirrors the source layout:
tests/
├── agent/ # Agent module unit tests
├── cli/ # Legacy CLI tests
├── hermes_cli/ # CLI command tests
├── gateway/ # Gateway and platform adapter tests
├── run_agent/ # AIAgent orchestrator tests
├── plugins/ # Plugin system tests
├── cron/ # Scheduler tests
├── acp/ # ACP adapter tests
├── environments/ # Terminal backend tests
├── skills/ # Skill tests
├── honcho_plugin/ # Honcho memory plugin tests
├── e2e/ # End-to-end tests
└── integration/ # Integration tests
The test suite uses pytest with heavy mocking (fake HTTP servers, fake platform adapters, mock LLM responses). Run with:
pytest tests/
pytest tests/gateway/ -v # Specific module
pytest tests/ -k "test_pairing" # Pattern match
API Endpoints — Web Dashboard
The web dashboard API server exposes endpoints for the React frontend:
| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Health check |
GET |
/health/detailed |
Detailed health with subsystem status |
GET |
/v1/models |
List available models |
POST |
/v1/chat/completions |
OpenAI-compatible chat completions |
POST |
/v1/responses |
Responses API |
POST |
/v1/runs |
Async run with SSE streaming |
GET |
/api/sessions |
List sessions |
GET |
/api/sessions/:id |
Get session details |
DELETE |
/api/sessions/:id |
Delete session |
POST |
/api/sessions/:id/message |
Send message to session |
GET |
/api/config |
Get current configuration |
PUT |
/api/config |
Update configuration |
GET |
/api/status |
System status |
GET |
/api/skills |
List available skills |
POST |
/api/skills/install |
Install skill |
DELETE |
/api/skills/:name |
Remove skill |
GET |
/api/cron |
List cron jobs |
POST |
/api/cron |
Create cron job |
PUT |
/api/cron/:id |
Update cron job |
DELETE |
/api/cron/:id |
Delete cron job |
POST |
/api/cron/:id/run |
Trigger cron job |
GET |
/api/gateway/status |
Gateway status |
POST |
/api/gateway/start |
Start gateway |
POST |
/api/gateway/stop |
Stop gateway |
GET |
/api/gateway/platforms |
List platforms |
GET |
/api/gateway/paired |
List paired users |
POST |
/api/gateway/pair |
Generate pairing code |
DELETE |
/api/gateway/unpair |
Remove paired user |
GET |
/api/logs |
Fetch logs |
GET |
/api/logs/stream |
SSE log stream |
GET |
/api/plugins |
List plugins |
POST |
/api/plugins/install |
Install plugin |
DELETE |
/api/plugins/:name |
Remove plugin |
GET |
/api/profiles |
List config profiles |
POST |
/api/profiles |
Create profile |
PUT |
/api/profiles/:name |
Update profile |
DELETE |
/api/profiles/:name |
Delete profile |
POST |
/api/profiles/:name/activate |
Activate profile |
GET |
/api/auth |
Auth status |
POST |
/api/auth/login |
Login |
POST |
/api/auth/logout |
Logout |
GET |
/api/analytics |
Session analytics |
POST |
/api/backup |
Create backup |
POST |
/api/import |
Import backup |
GET |
/api/doctor |
Run diagnostics |
GET |
/api/debug |
Debug report |
API Server — OpenAI-Compatible
The API Server adapter (gateway/platforms/api_server.py) provides an OpenAI-compatible REST API on port 8642 (configurable via API_SERVER_PORT):
| Method | Path | Purpose |
|---|---|---|
POST |
/v1/chat/completions |
Chat completions (streaming and non-streaming) |
POST |
/v1/responses |
Responses API format |
GET |
/v1/models |
List available models |
POST |
/v1/runs |
Async run with SSE events |
GET |
/health |
Simple health check |
GET |
/health/detailed |
Detailed subsystem health |
Any OpenAI-compatible frontend (Open WebUI, LobeChat, ChatBox, etc.) can connect by pointing to http://localhost:8642.
9. Integration Points
ACP (Agent Communication Protocol)
For IDE and editor integration (VS Code, JetBrains, Cursor, etc.):
hermes acp # Start ACP server
- JSON-RPC over stdio transport
- Session management (create, resume, list)
- MCP server registration and forwarding
- Tool progress events for UI feedback
- Implementation in
acp_adapter/(9 files)
MCP Server Mode
Run Hermes as an MCP (Model Context Protocol) server for use as a tool provider to other agents:
pip install hermes-agent[mcp]
python -m mcp_serve
Exposes Hermes tools (terminal, file, web, browser) as MCP-compatible tool definitions.
OpenAI-Compatible API
Start the API server for web frontend integration:
hermes gateway start api_server # As gateway platform
# or configure in config.yaml
Supports streaming and non-streaming chat completions, the Responses API format, and async runs with SSE.
Webhook Subscriptions
hermes webhook add deploy-notify \
--prompt "Summarize the deployment changes" \
--events "push,release" \
--url "https://example.com/webhook"
- HMAC-authenticated inbound webhooks (requires
WEBHOOK_SECRET) - Event filtering by type
- Delivery to any configured platform
- Retry on delivery failure
Messaging Platform SDKs
| Platform | SDK / Bridge | Transport |
|---|---|---|
| Node.js bridge via Baileys library | WebSocket | |
| WhatsApp Cloud | Direct API | REST + Webhooks |
| Telegram | python-telegram-bot | Webhook or Long Polling |
| Discord | discord.py | WebSocket + Slash Commands |
| Slack | slack-sdk | Socket Mode + Events API |
| Matrix | matrix-nio | WebSocket, optional E2EE |
| Signal | signal-cli | CLI subprocess |
| Mattermost | API client | WebSocket |
| Home Assistant | REST API | WebSocket |
| DingTalk | DingTalk Open API | Webhook |
| Feishu/Lark | Feishu Open API | Webhook |
| WeCom | WeCom API | Callback |
| Weixin | Weixin MP API | Callback |
| QQ Bot API | WebSocket | |
| BlueBubbles | BlueBubbles API | REST + Polling |
| imaplib / smtplib | IMAP + SMTP | |
| SMS | Twilio API | REST + Webhook |