2026-03-05 05:24:55 -08:00
|
|
|
|
---
|
|
|
|
|
|
sidebar_position: 1
|
|
|
|
|
|
title: "Architecture"
|
|
|
|
|
|
description: "Hermes Agent internals — project structure, agent loop, key classes, and design patterns"
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# Architecture
|
|
|
|
|
|
|
|
|
|
|
|
This guide covers the internal architecture of Hermes Agent for developers contributing to the project.
|
|
|
|
|
|
|
|
|
|
|
|
## Project Structure
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
hermes-agent/
|
|
|
|
|
|
├── run_agent.py # AIAgent class — core conversation loop, tool dispatch
|
|
|
|
|
|
├── cli.py # HermesCLI class — interactive TUI, prompt_toolkit
|
|
|
|
|
|
├── model_tools.py # Tool orchestration (thin layer over tools/registry.py)
|
|
|
|
|
|
├── toolsets.py # Tool groupings and presets
|
|
|
|
|
|
├── hermes_state.py # SQLite session database with FTS5 full-text search
|
|
|
|
|
|
├── batch_runner.py # Parallel batch processing for trajectory generation
|
|
|
|
|
|
│
|
|
|
|
|
|
├── agent/ # Agent internals (extracted modules)
|
|
|
|
|
|
│ ├── prompt_builder.py # System prompt assembly (identity, skills, memory)
|
|
|
|
|
|
│ ├── context_compressor.py # Auto-summarization when approaching context limits
|
|
|
|
|
|
│ ├── auxiliary_client.py # Resolves auxiliary OpenAI clients (summarization, vision)
|
|
|
|
|
|
│ ├── display.py # KawaiiSpinner, tool progress formatting
|
|
|
|
|
|
│ ├── model_metadata.py # Model context lengths, token estimation
|
|
|
|
|
|
│ └── trajectory.py # Trajectory saving helpers
|
|
|
|
|
|
│
|
|
|
|
|
|
├── hermes_cli/ # CLI command implementations
|
|
|
|
|
|
│ ├── main.py # Entry point, argument parsing, command dispatch
|
|
|
|
|
|
│ ├── config.py # Config management, migration, env var definitions
|
|
|
|
|
|
│ ├── setup.py # Interactive setup wizard
|
|
|
|
|
|
│ ├── auth.py # Provider resolution, OAuth, Nous Portal
|
|
|
|
|
|
│ ├── models.py # OpenRouter model selection lists
|
|
|
|
|
|
│ ├── banner.py # Welcome banner, ASCII art
|
|
|
|
|
|
│ ├── commands.py # Slash command definitions + autocomplete
|
|
|
|
|
|
│ ├── callbacks.py # Interactive callbacks (clarify, sudo, approval)
|
|
|
|
|
|
│ ├── doctor.py # Diagnostics
|
|
|
|
|
|
│ └── skills_hub.py # Skills Hub CLI + /skills slash command handler
|
|
|
|
|
|
│
|
|
|
|
|
|
├── tools/ # Tool implementations (self-registering)
|
|
|
|
|
|
│ ├── registry.py # Central tool registry (schemas, handlers, dispatch)
|
|
|
|
|
|
│ ├── approval.py # Dangerous command detection + per-session approval
|
|
|
|
|
|
│ ├── terminal_tool.py # Terminal orchestration (sudo, env lifecycle, backends)
|
docs: fix all remaining minor accuracy issues
- updating.md: Note that 'hermes update' auto-handles config migration
- cli.md: Add summary_model to compression config, fix display config
(add personality/compact), remove unverified pastes/ claim
- configuration.md: Add 5 missing config sections (stt, human_delay,
code_execution, delegation, clarify), fix display defaults,
fix reasoning_effort default to empty/unset
- messaging/index.md: Add GATEWAY_ALLOWED_USERS to security section
- skills.md: Add category field to skills_list return value
- mcp.md: Document auto-registered utility tools (resources/prompts)
- architecture.md: Fix file_tools.py reference, base_url default to None,
synchronous agent loop pseudocode
- cli-commands.md: Fix hermes logout description
- environment-variables.md: Add HERMES_QUIET, HERMES_EXEC_ASK,
BROWSER_INACTIVITY_TIMEOUT, GATEWAY_ALLOWED_USERS
Verification scan: 27/27 checks passed, zero issues remaining.
2026-03-05 07:00:51 -08:00
|
|
|
|
│ ├── file_operations.py # File tool implementations (read, write, search, patch)
|
|
|
|
|
|
│ ├── file_tools.py # File tool registration
|
2026-03-05 05:24:55 -08:00
|
|
|
|
│ ├── web_tools.py # web_search, web_extract
|
|
|
|
|
|
│ ├── vision_tools.py # Image analysis via multimodal models
|
|
|
|
|
|
│ ├── delegate_tool.py # Subagent spawning and parallel task execution
|
|
|
|
|
|
│ ├── code_execution_tool.py # Sandboxed Python with RPC tool access
|
|
|
|
|
|
│ ├── session_search_tool.py # Search past conversations
|
|
|
|
|
|
│ ├── cronjob_tools.py # Scheduled task management
|
docs: comprehensive accuracy audit fixes (35+ corrections)
CRITICAL fixes:
- Installation: Remove false prerequisites (installer auto-installs everything except git)
- Tools: Remove non-existent 'web_crawl' tool from tools table
- Memory: Remove non-existent 'read' action (only add/replace/remove exist)
- Code execution: Fix 'search' to 'search_files' in sandbox tools list
- CLI commands: Fix --model/--provider/--toolsets/--verbose as chat subcommand flags
IMPORTANT fixes:
- Installation: Add missing installer features (Node.js, ripgrep, ffmpeg, skills seeding)
- Installation: Add 6 missing package extras to table (mcp, honcho, tts-premium, etc)
- Installation: Fix mkdir to include all directories the installer creates
- Quickstart: Add OpenAI Codex to provider table
- CLI: Fix all 'hermes --flag' to 'hermes chat --flag' across all docs
- Configuration: Remove non-existent --max-turns CLI flag
- Tools: Fix 'search' to 'search_files', add missing 'process' tool
- Skills: Remove skills_categories() (not a registered tool)
- Cron: Remove unsupported 'daily at 9am' schedule format
- TTS: Fix output directory to ~/.hermes/audio_cache/
- Delegation: Clarify depth limit wording
- Architecture: Fix default model, chat() signature, file names
- Contributing: Fix Python requirement from 3.11+ to 3.10+
- CLI reference: Add missing commands (login, tools, sessions subcommands)
- Env vars: Fix TERMINAL_DOCKER_IMAGE default, add HERMES_MODEL
2026-03-05 06:50:22 -08:00
|
|
|
|
│ ├── skills_tool.py # Skill search and load
|
|
|
|
|
|
│ ├── skill_manager_tool.py # Skill management
|
2026-03-05 05:24:55 -08:00
|
|
|
|
│ └── environments/ # Terminal execution backends
|
|
|
|
|
|
│ ├── base.py # BaseEnvironment ABC
|
2026-03-05 11:55:41 -08:00
|
|
|
|
│ ├── local.py, docker.py, ssh.py, singularity.py, modal.py, daytona.py
|
2026-03-05 05:24:55 -08:00
|
|
|
|
│
|
|
|
|
|
|
├── gateway/ # Messaging gateway
|
|
|
|
|
|
│ ├── run.py # GatewayRunner — platform lifecycle, message routing
|
|
|
|
|
|
│ ├── config.py # Platform configuration resolution
|
|
|
|
|
|
│ ├── session.py # Session store, context prompts, reset policies
|
|
|
|
|
|
│ └── platforms/ # Platform adapters
|
|
|
|
|
|
│ ├── telegram.py, discord_adapter.py, slack.py, whatsapp.py
|
|
|
|
|
|
│
|
|
|
|
|
|
├── scripts/ # Installer and bridge scripts
|
|
|
|
|
|
│ ├── install.sh # Linux/macOS installer
|
|
|
|
|
|
│ ├── install.ps1 # Windows PowerShell installer
|
|
|
|
|
|
│ └── whatsapp-bridge/ # Node.js WhatsApp bridge (Baileys)
|
|
|
|
|
|
│
|
|
|
|
|
|
├── skills/ # Bundled skills (copied to ~/.hermes/skills/)
|
docs: update all docs for optional-skills and browse command
Update 7 documentation files to reflect:
- optional-skills/ directory in all project structure trees
- 'hermes skills browse' in all CLI command listings
- '/skills browse' in all slash command references
- Three-tier skill placement (bundled → optional → hub)
- 'official' trust level in trust level tables
- Updated /skills description from 'Search, install...' to 'Browse, search...'
Files updated:
- CONTRIBUTING.md (skill classification, project tree, section title)
- AGENTS.md (project tree, Skills Hub description, source adapters list)
- website/docs/reference/cli-commands.md (CLI table, slash command table)
- website/docs/developer-guide/creating-skills.md (structure, classification, trust)
- website/docs/user-guide/features/skills.md (hub commands, trust table, slash commands)
- website/docs/user-guide/cli.md (slash command description)
- website/docs/developer-guide/architecture.md (project tree)
2026-03-06 01:46:34 -08:00
|
|
|
|
├── optional-skills/ # Official optional skills (discoverable via hub, not activated by default)
|
2026-03-05 05:24:55 -08:00
|
|
|
|
├── environments/ # RL training environments (Atropos integration)
|
|
|
|
|
|
└── tests/ # Test suite
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## Core Loop
|
|
|
|
|
|
|
|
|
|
|
|
The main agent loop lives in `run_agent.py`:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
User message → AIAgent._run_agent_loop()
|
|
|
|
|
|
├── Build system prompt (prompt_builder.py)
|
|
|
|
|
|
├── Build API kwargs (model, messages, tools, reasoning config)
|
|
|
|
|
|
├── Call LLM (OpenAI-compatible API)
|
|
|
|
|
|
├── If tool_calls in response:
|
|
|
|
|
|
│ ├── Execute each tool via registry dispatch
|
|
|
|
|
|
│ ├── Add tool results to conversation
|
|
|
|
|
|
│ └── Loop back to LLM call
|
|
|
|
|
|
├── If text response:
|
|
|
|
|
|
│ ├── Persist session to DB
|
|
|
|
|
|
│ └── Return final_response
|
|
|
|
|
|
└── Context compression if approaching token limit
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
while turns < max_turns:
|
|
|
|
|
|
response = client.chat.completions.create(
|
|
|
|
|
|
model=model,
|
|
|
|
|
|
messages=messages,
|
|
|
|
|
|
tools=tool_schemas,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if response.tool_calls:
|
|
|
|
|
|
for tool_call in response.tool_calls:
|
docs: fix all remaining minor accuracy issues
- updating.md: Note that 'hermes update' auto-handles config migration
- cli.md: Add summary_model to compression config, fix display config
(add personality/compact), remove unverified pastes/ claim
- configuration.md: Add 5 missing config sections (stt, human_delay,
code_execution, delegation, clarify), fix display defaults,
fix reasoning_effort default to empty/unset
- messaging/index.md: Add GATEWAY_ALLOWED_USERS to security section
- skills.md: Add category field to skills_list return value
- mcp.md: Document auto-registered utility tools (resources/prompts)
- architecture.md: Fix file_tools.py reference, base_url default to None,
synchronous agent loop pseudocode
- cli-commands.md: Fix hermes logout description
- environment-variables.md: Add HERMES_QUIET, HERMES_EXEC_ASK,
BROWSER_INACTIVITY_TIMEOUT, GATEWAY_ALLOWED_USERS
Verification scan: 27/27 checks passed, zero issues remaining.
2026-03-05 07:00:51 -08:00
|
|
|
|
result = execute_tool(tool_call)
|
2026-03-05 05:24:55 -08:00
|
|
|
|
messages.append(tool_result_message(result))
|
|
|
|
|
|
turns += 1
|
|
|
|
|
|
else:
|
|
|
|
|
|
return response.content
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## AIAgent Class
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
class AIAgent:
|
|
|
|
|
|
def __init__(
|
|
|
|
|
|
self,
|
docs: comprehensive accuracy audit fixes (35+ corrections)
CRITICAL fixes:
- Installation: Remove false prerequisites (installer auto-installs everything except git)
- Tools: Remove non-existent 'web_crawl' tool from tools table
- Memory: Remove non-existent 'read' action (only add/replace/remove exist)
- Code execution: Fix 'search' to 'search_files' in sandbox tools list
- CLI commands: Fix --model/--provider/--toolsets/--verbose as chat subcommand flags
IMPORTANT fixes:
- Installation: Add missing installer features (Node.js, ripgrep, ffmpeg, skills seeding)
- Installation: Add 6 missing package extras to table (mcp, honcho, tts-premium, etc)
- Installation: Fix mkdir to include all directories the installer creates
- Quickstart: Add OpenAI Codex to provider table
- CLI: Fix all 'hermes --flag' to 'hermes chat --flag' across all docs
- Configuration: Remove non-existent --max-turns CLI flag
- Tools: Fix 'search' to 'search_files', add missing 'process' tool
- Skills: Remove skills_categories() (not a registered tool)
- Cron: Remove unsupported 'daily at 9am' schedule format
- TTS: Fix output directory to ~/.hermes/audio_cache/
- Delegation: Clarify depth limit wording
- Architecture: Fix default model, chat() signature, file names
- Contributing: Fix Python requirement from 3.11+ to 3.10+
- CLI reference: Add missing commands (login, tools, sessions subcommands)
- Env vars: Fix TERMINAL_DOCKER_IMAGE default, add HERMES_MODEL
2026-03-05 06:50:22 -08:00
|
|
|
|
model: str = "anthropic/claude-opus-4.6",
|
2026-03-05 05:24:55 -08:00
|
|
|
|
api_key: str = None,
|
docs: fix all remaining minor accuracy issues
- updating.md: Note that 'hermes update' auto-handles config migration
- cli.md: Add summary_model to compression config, fix display config
(add personality/compact), remove unverified pastes/ claim
- configuration.md: Add 5 missing config sections (stt, human_delay,
code_execution, delegation, clarify), fix display defaults,
fix reasoning_effort default to empty/unset
- messaging/index.md: Add GATEWAY_ALLOWED_USERS to security section
- skills.md: Add category field to skills_list return value
- mcp.md: Document auto-registered utility tools (resources/prompts)
- architecture.md: Fix file_tools.py reference, base_url default to None,
synchronous agent loop pseudocode
- cli-commands.md: Fix hermes logout description
- environment-variables.md: Add HERMES_QUIET, HERMES_EXEC_ASK,
BROWSER_INACTIVITY_TIMEOUT, GATEWAY_ALLOWED_USERS
Verification scan: 27/27 checks passed, zero issues remaining.
2026-03-05 07:00:51 -08:00
|
|
|
|
base_url: str = None, # Resolved internally based on provider
|
2026-03-05 05:24:55 -08:00
|
|
|
|
max_iterations: int = 60,
|
|
|
|
|
|
enabled_toolsets: list = None,
|
|
|
|
|
|
disabled_toolsets: list = None,
|
|
|
|
|
|
verbose_logging: bool = False,
|
|
|
|
|
|
quiet_mode: bool = False,
|
|
|
|
|
|
tool_progress_callback: callable = None,
|
|
|
|
|
|
):
|
|
|
|
|
|
...
|
|
|
|
|
|
|
docs: comprehensive accuracy audit fixes (35+ corrections)
CRITICAL fixes:
- Installation: Remove false prerequisites (installer auto-installs everything except git)
- Tools: Remove non-existent 'web_crawl' tool from tools table
- Memory: Remove non-existent 'read' action (only add/replace/remove exist)
- Code execution: Fix 'search' to 'search_files' in sandbox tools list
- CLI commands: Fix --model/--provider/--toolsets/--verbose as chat subcommand flags
IMPORTANT fixes:
- Installation: Add missing installer features (Node.js, ripgrep, ffmpeg, skills seeding)
- Installation: Add 6 missing package extras to table (mcp, honcho, tts-premium, etc)
- Installation: Fix mkdir to include all directories the installer creates
- Quickstart: Add OpenAI Codex to provider table
- CLI: Fix all 'hermes --flag' to 'hermes chat --flag' across all docs
- Configuration: Remove non-existent --max-turns CLI flag
- Tools: Fix 'search' to 'search_files', add missing 'process' tool
- Skills: Remove skills_categories() (not a registered tool)
- Cron: Remove unsupported 'daily at 9am' schedule format
- TTS: Fix output directory to ~/.hermes/audio_cache/
- Delegation: Clarify depth limit wording
- Architecture: Fix default model, chat() signature, file names
- Contributing: Fix Python requirement from 3.11+ to 3.10+
- CLI reference: Add missing commands (login, tools, sessions subcommands)
- Env vars: Fix TERMINAL_DOCKER_IMAGE default, add HERMES_MODEL
2026-03-05 06:50:22 -08:00
|
|
|
|
def chat(self, message: str) -> str:
|
2026-03-05 05:24:55 -08:00
|
|
|
|
# Main entry point - runs the agent loop
|
|
|
|
|
|
...
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 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/
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Each tool file co-locates its schema, handler, and registration. `model_tools.py` is a thin orchestration layer.
|
|
|
|
|
|
|
|
|
|
|
|
## Key Design Patterns
|
|
|
|
|
|
|
|
|
|
|
|
### Self-Registering Tools
|
|
|
|
|
|
|
|
|
|
|
|
Each tool file calls `registry.register()` at import time. `model_tools.py` triggers discovery by importing all tool modules.
|
|
|
|
|
|
|
|
|
|
|
|
### Toolset Grouping
|
|
|
|
|
|
|
|
|
|
|
|
Tools are grouped into toolsets (`web`, `terminal`, `file`, `browser`, etc.) that can be enabled/disabled per platform.
|
|
|
|
|
|
|
|
|
|
|
|
### Session Persistence
|
|
|
|
|
|
|
|
|
|
|
|
All conversations are stored in SQLite (`hermes_state.py`) with full-text search. JSON logs go to `~/.hermes/sessions/`.
|
|
|
|
|
|
|
|
|
|
|
|
### Ephemeral Injection
|
|
|
|
|
|
|
|
|
|
|
|
System prompts and prefill messages are injected at API call time, never persisted to the database or logs.
|
|
|
|
|
|
|
|
|
|
|
|
### Provider Abstraction
|
|
|
|
|
|
|
|
|
|
|
|
The agent works with any OpenAI-compatible API. Provider resolution happens at init time (Nous Portal OAuth, OpenRouter API key, or custom endpoint).
|
|
|
|
|
|
|
|
|
|
|
|
### Conversation Format
|
|
|
|
|
|
|
|
|
|
|
|
Messages follow the OpenAI format:
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
messages = [
|
|
|
|
|
|
{"role": "system", "content": "You are a helpful assistant..."},
|
|
|
|
|
|
{"role": "user", "content": "Search for Python tutorials"},
|
|
|
|
|
|
{"role": "assistant", "content": None, "tool_calls": [...]},
|
|
|
|
|
|
{"role": "tool", "tool_call_id": "...", "content": "..."},
|
|
|
|
|
|
{"role": "assistant", "content": "Here's what I found..."},
|
|
|
|
|
|
]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## CLI Architecture
|
|
|
|
|
|
|
|
|
|
|
|
The interactive CLI (`cli.py`) uses:
|
|
|
|
|
|
|
|
|
|
|
|
- **Rich** — Welcome banner and styled panels
|
|
|
|
|
|
- **prompt_toolkit** — Fixed input area with history, `patch_stdout`, slash command autocomplete
|
|
|
|
|
|
- **KawaiiSpinner** — Animated kawaii faces during API calls; clean activity feed for tool results
|
|
|
|
|
|
|
|
|
|
|
|
Key UX behaviors:
|
|
|
|
|
|
|
|
|
|
|
|
- Thinking spinner shows animated kawaii face + verb (`(⌐■_■) deliberating...`)
|
|
|
|
|
|
- Tool execution results appear as `┊ {emoji} {verb} {detail} {duration}`
|
|
|
|
|
|
- Prompt shows `⚕ ❯` when working, `❯` when idle
|
docs: fix all remaining minor accuracy issues
- updating.md: Note that 'hermes update' auto-handles config migration
- cli.md: Add summary_model to compression config, fix display config
(add personality/compact), remove unverified pastes/ claim
- configuration.md: Add 5 missing config sections (stt, human_delay,
code_execution, delegation, clarify), fix display defaults,
fix reasoning_effort default to empty/unset
- messaging/index.md: Add GATEWAY_ALLOWED_USERS to security section
- skills.md: Add category field to skills_list return value
- mcp.md: Document auto-registered utility tools (resources/prompts)
- architecture.md: Fix file_tools.py reference, base_url default to None,
synchronous agent loop pseudocode
- cli-commands.md: Fix hermes logout description
- environment-variables.md: Add HERMES_QUIET, HERMES_EXEC_ASK,
BROWSER_INACTIVITY_TIMEOUT, GATEWAY_ALLOWED_USERS
Verification scan: 27/27 checks passed, zero issues remaining.
2026-03-05 07:00:51 -08:00
|
|
|
|
- Multi-line paste support with automatic formatting
|
2026-03-05 05:24:55 -08:00
|
|
|
|
|
|
|
|
|
|
## Messaging Gateway Architecture
|
|
|
|
|
|
|
|
|
|
|
|
The gateway (`gateway/run.py`) uses `GatewayRunner` to:
|
|
|
|
|
|
|
|
|
|
|
|
1. Connect to all configured platforms
|
|
|
|
|
|
2. Route messages through per-chat session stores
|
|
|
|
|
|
3. Dispatch to AIAgent instances
|
|
|
|
|
|
4. Run the cron scheduler (ticks every 60s)
|
|
|
|
|
|
5. Handle interrupts and tool progress notifications
|
|
|
|
|
|
|
|
|
|
|
|
Each platform adapter conforms to `BasePlatformAdapter`.
|
|
|
|
|
|
|
|
|
|
|
|
## Configuration System
|
|
|
|
|
|
|
|
|
|
|
|
- `~/.hermes/config.yaml` — All settings
|
|
|
|
|
|
- `~/.hermes/.env` — API keys and secrets
|
|
|
|
|
|
- `_config_version` in `DEFAULT_CONFIG` — Bumped when required fields are added, triggers migration prompts
|