diff --git a/website/docs/developer-guide/agent-loop.md b/website/docs/developer-guide/agent-loop.md index 24cee51082..a381ea2b9d 100644 --- a/website/docs/developer-guide/agent-loop.md +++ b/website/docs/developer-guide/agent-loop.md @@ -6,7 +6,7 @@ description: "Detailed walkthrough of AIAgent execution, API modes, tools, callb # Agent Loop Internals -The core orchestration engine is `run_agent.py`'s `AIAgent` class — a large file that handles everything from prompt assembly to tool dispatch to provider failover. +The core orchestration engine is the `AIAgent` class. `run_agent.py` is now a thin facade: the loop itself lives in `agent/conversation_loop.py`, each turn phase in `agent/turn_*.py` (iteration prep, API call, API error, overflow, truncation, recovery), constructor wiring in `agent/agent_init.py`, and everything from prompt assembly to tool dispatch to provider failover in focused `agent/*.py` modules mixed into `AIAgent`. ## Core Responsibilities @@ -149,7 +149,7 @@ for each tool_call in response.tool_calls: ### Agent-Level Tools -Some tools are intercepted by `run_agent.py` *before* reaching `handle_function_call()`: +Some tools are intercepted by `agent/tool_executor.py` (called from `agent/conversation_loop.py`) *before* reaching `handle_function_call()`: | Tool | Why intercepted | |------|--------------------| @@ -222,7 +222,10 @@ After each turn: | File | Purpose | |------|---------| -| `run_agent.py` | AIAgent class — the complete agent loop | +| `run_agent.py` | `AIAgent` facade — public entry points; loop and turn phases live in `agent/` | +| `agent/conversation_loop.py` | The agent loop (`run_conversation()` body) | +| `agent/turn_*.py` | Turn phases: iteration_prep, api_call, api_error, overflow, truncation, recovery | +| `agent/tool_executor.py` | Tool-call execution and agent-level tool interception | | `agent/prompt_builder.py` | System prompt assembly from memory, skills, context files, personality | | `agent/context_engine.py` | ContextEngine ABC — pluggable context management | | `agent/context_compressor.py` | Default engine — lossy summarization algorithm | diff --git a/website/docs/developer-guide/architecture.md b/website/docs/developer-guide/architecture.md index 6c1f6cafa4..3640103c3d 100644 --- a/website/docs/developer-guide/architecture.md +++ b/website/docs/developer-guide/architecture.md @@ -52,11 +52,11 @@ This page is the top-level map of Hermes Agent internals. Use it to orient yours ```text hermes-agent/ -├── run_agent.py # AIAgent — core conversation loop (large file) -├── cli.py # HermesCLI — interactive terminal UI (large file) +├── run_agent.py # AIAgent facade — loop lives in agent/conversation_loop.py + agent/turn_*.py +├── cli.py # HermesCLI facade — mixins in hermes_cli/cli_*_mixin.py ├── model_tools.py # Tool discovery, schema collection, dispatch ├── toolsets.py # Tool groupings and platform presets -├── hermes_state.py # SQLite session/state database with FTS5 +├── hermes_state.py # SQLite session/state database facade (+ hermes_state_*.py siblings) ├── hermes_constants.py # HERMES_HOME, profile-aware paths ├── batch_runner.py # Batch trajectory generation │ @@ -76,14 +76,14 @@ hermes-agent/ │ └── trajectory.py # Trajectory saving helpers │ ├── hermes_cli/ # CLI subcommands and setup -│ ├── main.py # Entry point — all `hermes` subcommands (large file) +│ ├── main.py # Entry point — `hermes` subcommands (parsers in subcommands/, main_*.py) │ ├── config.py # DEFAULT_CONFIG, OPTIONAL_ENV_VARS, migration │ ├── commands.py # COMMAND_REGISTRY — central slash command definitions -│ ├── auth.py # PROVIDER_REGISTRY, credential resolution +│ ├── auth.py # PROVIDER_REGISTRY, credential resolution (+ auth_*.py siblings) │ ├── runtime_provider.py # Provider → api_mode + credentials │ ├── models.py # Model catalog, provider model lists │ ├── model_switch.py # /model command logic (CLI + gateway shared) -│ ├── setup.py # Interactive setup wizard (large file) +│ ├── setup.py # Interactive setup wizard (+ setup_*.py siblings) │ ├── skin_engine.py # CLI theming engine │ ├── skills_config.py # hermes skills — enable/disable per platform │ ├── skills_hub.py # /skills slash command @@ -99,17 +99,17 @@ hermes-agent/ │ ├── process_registry.py # Background process management │ ├── file_tools.py # read_file, write_file, patch, search_files │ ├── web_tools.py # web_search, web_extract -│ ├── browser_tool.py # 10 browser automation tools +│ ├── browser_tool.py # Browser automation tools facade (+ browser_tool_*.py siblings) │ ├── code_execution_tool.py # execute_code sandbox │ ├── delegate_tool.py # Subagent delegation -│ ├── mcp_tool.py # MCP client (large file) +│ ├── mcp_tool.py # MCP client facade (+ mcp_tool_*.py siblings) │ ├── credential_files.py # File-based credential passthrough │ ├── env_passthrough.py # Env var passthrough for sandboxes │ ├── ansi_strip.py # ANSI escape stripping │ └── environments/ # Terminal backends (local, docker, ssh, modal, daytona, singularity) │ ├── gateway/ # Messaging platform gateway -│ ├── run.py # GatewayRunner — message dispatch (large file) +│ ├── run.py # GatewayRunner facade — message dispatch (+ run_*.py siblings) │ ├── session.py # SessionStore — conversation persistence │ ├── delivery.py # Outbound message delivery │ ├── pairing.py # DM pairing authorization @@ -191,7 +191,7 @@ If you are new to the codebase: ### Agent Loop -The synchronous orchestration engine (`AIAgent` in `run_agent.py`). Handles provider selection, prompt construction, tool execution, retries, fallback, callbacks, compression, and persistence. Supports three API modes for different provider backends. +The synchronous orchestration engine (`AIAgent`, exposed by the `run_agent.py` facade; the loop lives in `agent/conversation_loop.py` and `agent/turn_*.py`). Handles provider selection, prompt construction, tool execution, retries, fallback, callbacks, compression, and persistence. Supports three API modes for different provider backends. → [Agent Loop Internals](./agent-loop.md) diff --git a/website/docs/developer-guide/codebase-ownership.md b/website/docs/developer-guide/codebase-ownership.md index c6f85d7e1f..5507aafef6 100644 --- a/website/docs/developer-guide/codebase-ownership.md +++ b/website/docs/developer-guide/codebase-ownership.md @@ -18,7 +18,7 @@ Hermes is a large repository, and most contributions touch exactly one subsystem | Plugins system | `plugins/` | [Build a Hermes Plugin](plugins/index.md) | | Skills (bundled & optional) | `skills/`, `optional-skills/` | [Creating Skills](creating-skills.md) | | Cron / scheduled jobs | `cron/` | [Cron Internals](cron-internals.md) | -| Session storage | `hermes_state.py` | [Session Storage](session-storage.md) | +| Session storage | `hermes_state.py`, `hermes_state_*.py` | [Session Storage](session-storage.md) | | Browser stack | `tools/browser_tool.py`, `tools/browser_supervisor.py`, `tools/browser_cdp_tool.py` | [Browser Supervisor](browser-supervisor.md) | | Egress firewall | `agent/proxy_sources/iron_proxy.py` | [Egress Internals](egress-internals.md) | | ACP (IDE integration) | `acp_adapter/` | [ACP Internals](acp-internals.md) | diff --git a/website/docs/developer-guide/context-compression-and-caching.md b/website/docs/developer-guide/context-compression-and-caching.md index 223b802797..a38a9cb5eb 100644 --- a/website/docs/developer-guide/context-compression-and-caching.md +++ b/website/docs/developer-guide/context-compression-and-caching.md @@ -4,7 +4,7 @@ Hermes Agent uses a dual compression system and Anthropic prompt caching to manage context window usage efficiently across long conversations. Source files: `agent/context_engine.py` (ABC), `agent/context_compressor.py` (default engine), -`agent/prompt_caching.py`, `gateway/run.py` (session hygiene), `run_agent.py` (search for `_compress_context`) +`agent/prompt_caching.py`, `gateway/run_turn.py` (session hygiene), `agent/compression_facade.py` (search for `_compress_context`) ## Pluggable Context Engine @@ -53,7 +53,7 @@ Hermes has two separate compression layers that operate independently: ### 1. Gateway Session Hygiene (85% threshold) -Located in `gateway/run.py` (search for `Session hygiene: auto-compress`). This is a **safety net** that +Located in `gateway/run_turn.py` (search for `Session hygiene`). This is a **safety net** that runs before the agent processes a message. It prevents API failures when sessions grow too large between turns (e.g., overnight accumulation in Telegram/Discord). @@ -551,4 +551,4 @@ The CLI shows caching status at startup: ## Context Pressure Warnings -Intermediate context-pressure warnings have been removed (see the iteration-budget block in `run_agent.py`, which notes: "No intermediate pressure warnings — they caused models to 'give up' prematurely on complex tasks"). Compression fires when prompt tokens reach the configured `compression.threshold` (default 50%) with no prior warning step; gateway session hygiene fires as the secondary safety net at 85% of the model's context window. +Intermediate context-pressure warnings have been removed (see the iteration-budget block in `agent/turn_iteration_prep.py`, which notes: "No intermediate pressure warnings — they caused models to 'give up' prematurely on complex tasks"). Compression fires when prompt tokens reach the configured `compression.threshold` (default 50%) with no prior warning step; gateway session hygiene fires as the secondary safety net at 85% of the model's context window. diff --git a/website/docs/developer-guide/egress-internals.md b/website/docs/developer-guide/egress-internals.md index f84160788a..50852a8a36 100644 --- a/website/docs/developer-guide/egress-internals.md +++ b/website/docs/developer-guide/egress-internals.md @@ -22,7 +22,8 @@ hermes_cli/proxy_cli.py Wizard + slash command handlers. status,disable,config}`. Wires the core module into argparse. -hermes_cli/main.py:_dispatch_egress Top-level subparser dispatcher. +hermes_cli/subcommands/egress.py:_dispatch_egress + Top-level subparser dispatcher. dest='egress_command' (intentionally disjoint from the inbound OAuth `hermes proxy` subparser, which uses diff --git a/website/docs/developer-guide/provider-runtime.md b/website/docs/developer-guide/provider-runtime.md index 9cfd90097d..3e2c723a6b 100644 --- a/website/docs/developer-guide/provider-runtime.md +++ b/website/docs/developer-guide/provider-runtime.md @@ -170,7 +170,7 @@ Hermes supports a configured fallback provider chain — a list of `(provider, m 1. **Storage**: `AIAgent.__init__` stores the `fallback_model` dict and sets `_fallback_activated = False`. -2. **Trigger points**: `_try_activate_fallback()` is called from three places in the main retry loop in `run_agent.py`: +2. **Trigger points**: `_try_activate_fallback()` (forwarded to `try_activate_fallback()` in `agent/chat_completion_helpers.py`) is called from three places in the turn phases (`agent/turn_api_error.py`, `agent/turn_response_check.py`, `agent/turn_recovery.py`): - After max retries on invalid API responses (None choices, missing content) - On non-retryable client errors (HTTP 401, 403, 404) - After max retries on transient errors (HTTP 429, 500, 502, 503) @@ -187,7 +187,7 @@ Hermes supports a configured fallback provider chain — a list of `(provider, m 4. **Config flow**: - CLI: reads the fallback chain via `hermes_cli/fallback_config.get_fallback_chain()` → passes to `AIAgent(fallback_model=...)` - - Gateway: `gateway/run.py._load_fallback_model()` reads `config.yaml` → passes to `AIAgent` + - Gateway: `gateway/run_config_loaders.py._load_fallback_model()` reads `config.yaml` → passes to `AIAgent` - Validation: both `provider` and `model` keys must be non-empty, or fallback is disabled ### What does NOT support fallback diff --git a/website/docs/developer-guide/session-storage.md b/website/docs/developer-guide/session-storage.md index 4627b0ffa6..332cc4b618 100644 --- a/website/docs/developer-guide/session-storage.md +++ b/website/docs/developer-guide/session-storage.md @@ -4,7 +4,7 @@ Hermes Agent uses a SQLite database (`~/.hermes/state.db`) to persist session metadata, full message history, and model configuration across CLI and gateway sessions. This replaces the earlier per-session JSONL file approach. -Source file: `hermes_state.py` +Source files: `hermes_state.py` (facade) plus the `hermes_state_*.py` siblings (schema, fts, search, compression, portability, gateway, ...) ## Architecture Overview @@ -42,7 +42,7 @@ Key design decisions: ### Sessions Table -Abridged — see `SCHEMA_SQL` in `hermes_state.py` for the full current column list +Abridged — see `SCHEMA_SQL` in `hermes_state_common.py` (applied by `hermes_state_schema.py`) for the full current column list (which also includes gateway routing metadata such as `session_key`, `chat_id`, `chat_type`, `thread_id`, `display_name`, `origin_json`, `expiry_finalized`, workspace fields `cwd` / `git_branch` / `git_repo_root`, handoff and @@ -142,7 +142,7 @@ The FTS5 table is kept in sync via three triggers that fire on INSERT, UPDATE, and DELETE of the `messages` table. The current triggers are gated on the `fts_rebuild_high_water` / `fts_rebuild_progress` markers in `state_meta` (so a background FTS rebuild can proceed without double-indexing) and cover all three -indexed columns — see `SCHEMA_SQL` in `hermes_state.py` for the exact SQL. +indexed columns — see `SCHEMA_SQL` in `hermes_state_common.py` for the exact SQL. ## Schema Version and Migrations diff --git a/website/docs/developer-guide/trajectory-format.md b/website/docs/developer-guide/trajectory-format.md index fbc4663230..e0fbfb319c 100644 --- a/website/docs/developer-guide/trajectory-format.md +++ b/website/docs/developer-guide/trajectory-format.md @@ -3,7 +3,7 @@ Hermes Agent saves conversation trajectories in ShareGPT-compatible JSONL format for use as training data, debugging artifacts, and reinforcement learning datasets. -Source files: `agent/trajectory.py`, `run_agent.py` (search for `_save_trajectory`), `batch_runner.py` +Source files: `agent/trajectory.py`, `agent/session_persistence.py` (search for `_save_trajectory`), `batch_runner.py` ## File Naming Convention