2026-02-02 19:45:42 -08:00
|
|
|
# Hermes Agent - Development Guide
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
Instructions for AI coding assistants and developers working on the hermes-agent codebase.
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
## Development Environment
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-03-08 21:33:10 -07:00
|
|
|
source .venv/bin/activate # ALWAYS activate before running Python
|
2026-02-02 19:45:42 -08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Project Structure
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
hermes-agent/
|
2026-03-08 21:33:10 -07:00
|
|
|
├── run_agent.py # AIAgent class — core conversation loop
|
|
|
|
|
├── model_tools.py # Tool orchestration, _discover_tools(), handle_function_call()
|
|
|
|
|
├── toolsets.py # Toolset definitions, _HERMES_CORE_TOOLS list
|
|
|
|
|
├── cli.py # HermesCLI class — interactive CLI orchestrator
|
|
|
|
|
├── hermes_state.py # SessionDB — SQLite session store (FTS5 search)
|
|
|
|
|
├── agent/ # Agent internals
|
|
|
|
|
│ ├── prompt_builder.py # System prompt assembly
|
2026-02-21 23:17:18 -08:00
|
|
|
│ ├── context_compressor.py # Auto context compression
|
|
|
|
|
│ ├── prompt_caching.py # Anthropic prompt caching
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
│ ├── auxiliary_client.py # Auxiliary LLM client (vision, summarization)
|
2026-03-08 21:33:10 -07:00
|
|
|
│ ├── model_metadata.py # Model context lengths, token estimation
|
|
|
|
|
│ ├── display.py # KawaiiSpinner, tool preview formatting
|
|
|
|
|
│ ├── skill_commands.py # Skill slash commands (shared CLI/gateway)
|
|
|
|
|
│ └── trajectory.py # Trajectory saving helpers
|
|
|
|
|
├── hermes_cli/ # CLI subcommands and setup
|
|
|
|
|
│ ├── main.py # Entry point — all `hermes` subcommands
|
|
|
|
|
│ ├── config.py # DEFAULT_CONFIG, OPTIONAL_ENV_VARS, migration
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
│ ├── commands.py # Slash command definitions + SlashCommandCompleter
|
2026-03-08 21:33:10 -07:00
|
|
|
│ ├── callbacks.py # Terminal callbacks (clarify, sudo, approval)
|
|
|
|
|
│ └── setup.py # Interactive setup wizard
|
|
|
|
|
├── tools/ # Tool implementations (one file per tool)
|
|
|
|
|
│ ├── registry.py # Central tool registry (schemas, handlers, dispatch)
|
|
|
|
|
│ ├── approval.py # Dangerous command detection
|
|
|
|
|
│ ├── terminal_tool.py # Terminal orchestration
|
|
|
|
|
│ ├── process_registry.py # Background process management
|
|
|
|
|
│ ├── file_tools.py # File read/write/search/patch
|
|
|
|
|
│ ├── web_tools.py # Firecrawl search/extract
|
|
|
|
|
│ ├── browser_tool.py # Browserbase browser automation
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
│ ├── code_execution_tool.py # execute_code sandbox
|
2026-03-08 21:33:10 -07:00
|
|
|
│ ├── delegate_tool.py # Subagent delegation
|
|
|
|
|
│ ├── mcp_tool.py # MCP client (~1050 lines)
|
|
|
|
|
│ └── environments/ # Terminal backends (local, docker, ssh, modal, daytona, singularity)
|
|
|
|
|
├── gateway/ # Messaging platform gateway
|
|
|
|
|
│ ├── run.py # Main loop, slash commands, message dispatch
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
│ ├── session.py # SessionStore — conversation persistence
|
2026-03-08 21:33:10 -07:00
|
|
|
│ └── platforms/ # Adapters: telegram, discord, slack, whatsapp, homeassistant, signal
|
|
|
|
|
├── cron/ # Scheduler (jobs.py, scheduler.py)
|
|
|
|
|
├── environments/ # RL training environments (Atropos)
|
|
|
|
|
├── tests/ # Pytest suite (~2500+ tests)
|
2026-02-02 19:45:42 -08:00
|
|
|
└── batch_runner.py # Parallel batch processing
|
|
|
|
|
```
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
**User config:** `~/.hermes/config.yaml` (settings), `~/.hermes/.env` (API keys)
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
## File Dependency Chain
|
|
|
|
|
|
|
|
|
|
```
|
2026-02-21 21:03:40 -08:00
|
|
|
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/
|
2026-02-02 19:45:42 -08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
## AIAgent Class (run_agent.py)
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
class AIAgent:
|
2026-03-08 21:33:10 -07:00
|
|
|
def __init__(self,
|
|
|
|
|
model: str = "anthropic/claude-opus-4.6",
|
|
|
|
|
max_iterations: int = 90,
|
2026-02-02 19:45:42 -08:00
|
|
|
enabled_toolsets: list = None,
|
|
|
|
|
disabled_toolsets: list = None,
|
2026-03-08 21:33:10 -07:00
|
|
|
quiet_mode: bool = False,
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
save_trajectories: bool = False,
|
2026-03-08 21:33:10 -07:00
|
|
|
platform: str = None, # "cli", "telegram", etc.
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
session_id: str = None,
|
|
|
|
|
skip_context_files: bool = False,
|
|
|
|
|
skip_memory: bool = False,
|
2026-03-08 21:33:10 -07:00
|
|
|
# ... plus provider, api_mode, callbacks, routing params
|
|
|
|
|
): ...
|
|
|
|
|
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
def chat(self, message: str) -> str:
|
2026-03-08 21:33:10 -07:00
|
|
|
"""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."""
|
2026-02-02 19:45:42 -08:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Agent Loop
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
The core loop is inside `run_conversation()` — entirely synchronous:
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
```python
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
while api_call_count < self.max_iterations and self.iteration_budget.remaining > 0:
|
2026-03-08 21:33:10 -07:00
|
|
|
response = client.chat.completions.create(model=model, messages=messages, tools=tool_schemas)
|
2026-02-02 19:45:42 -08:00
|
|
|
if response.tool_calls:
|
|
|
|
|
for tool_call in response.tool_calls:
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
result = handle_function_call(tool_call.name, tool_call.args, task_id)
|
2026-02-02 19:45:42 -08:00
|
|
|
messages.append(tool_result_message(result))
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
api_call_count += 1
|
2026-02-02 19:45:42 -08:00
|
|
|
else:
|
|
|
|
|
return response.content
|
|
|
|
|
```
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
Messages follow OpenAI format: `{"role": "system/user/assistant/tool", ...}`. Reasoning content is stored in `assistant_msg["reasoning"]`.
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## CLI Architecture (cli.py)
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
- **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
|
|
|
|
|
- `process_command()` is a method on `HermesCLI` (not in commands.py)
|
|
|
|
|
- Skill slash commands: `agent/skill_commands.py` scans `~/.hermes/skills/`, injects as **user message** (not system prompt) to preserve prompt caching
|
2026-02-28 11:18:50 -08:00
|
|
|
|
2026-02-02 19:45:42 -08:00
|
|
|
### Adding CLI Commands
|
|
|
|
|
|
docs: comprehensive AGENTS.md audit and corrections
Major fixes:
- Default model: claude-sonnet-4.6 → claude-opus-4.6
- max_iterations default: 60 → 90 (also fixed in config.py OPTIONAL_ENV_VARS description)
- chat() signature: chat(user_message, task_id) → chat(message)
- Agent loop: _run_agent_loop() doesn't exist, loop is in run_conversation()
- Removed async/await references (agent is entirely synchronous)
- KawaiiSpinner location: run_agent.py → agent/display.py
- NOUS_API_KEY removed (not used by any tool), replaced with VOICE_TOOLS_OPENAI_KEY
- OPENAI_API_KEY for Whisper → VOICE_TOOLS_OPENAI_KEY
- check_for_missing_config() → check_config_version() + get_missing_env_vars()
- Adding tools: '2 files' → '3 files' (tool + model_tools.py + toolsets.py)
- Venv path: venv/ → .venv/
- Trajectory output path: trajectories/*.jsonl → trajectory_samples.jsonl
- process_command() location clarified (HermesCLI in cli.py, not commands.py)
- REQUIRED_ENV_VARS noted as intentionally empty
- _config_version noted as currently at version 5
New content:
- Project structure: added 40+ missing files across agent/, hermes_cli/, tools/, gateway/
- Full gateway/ directory listing with all modules and platforms/
- Added honcho_integration/, scripts/, tests/ directories
- Added hermes_constants.py, hermes_time.py, trajectory_compressor.py, utils.py
- CLI commands table: added 25+ missing commands (model, login, logout, whatsapp,
skills subsystem, tools, insights, gateway start/stop/restart/status/uninstall,
sessions export/delete/prune/stats, config path/env-path/show)
- Gateway slash commands section with all 20+ commands
- Platform toolsets: added hermes-cli, hermes-slack, hermes-homeassistant, hermes-gateway
- Gateway: added Home Assistant as supported platform
2026-03-08 17:38:05 -07:00
|
|
|
1. Add to `COMMANDS` dict in `hermes_cli/commands.py`
|
2026-03-08 21:33:10 -07:00
|
|
|
2. Add handler in `HermesCLI.process_command()` in `cli.py`
|
|
|
|
|
3. For persistent settings, use `save_config_value()` in `cli.py`
|
Add background process management with process tool, wait, PTY, and stdin support
New process registry and tool for managing long-running background processes
across all terminal backends (local, Docker, Singularity, Modal, SSH).
Process Registry (tools/process_registry.py):
- ProcessSession tracking with rolling 200KB output buffer
- spawn_local() with optional PTY via ptyprocess for interactive CLIs
- spawn_via_env() for non-local backends (runs inside sandbox, never on host)
- Background reader threads per process (Popen stdout or PTY)
- wait() with timeout clamping, interrupt support, and transparent limit reporting
- JSON checkpoint to ~/.hermes/processes.json for gateway crash recovery
- Module-level singleton shared across agent loop, gateway, and RL
Process Tool (model_tools.py):
- 7 actions: list, poll, log, wait, kill, write, submit
- Paired with terminal in all toolsets (CLI, messaging, RL)
- Timeout clamping with transparent notes in response
Terminal Tool Updates (tools/terminal_tool.py):
- Replaced nohup background mode with registry spawn (returns session_id)
- Added workdir parameter for per-command working directory
- Added check_interval parameter for gateway auto-check watchers
- Added pty parameter for interactive CLI tools (Codex, Claude Code)
- Updated TERMINAL_TOOL_DESCRIPTION with full background workflow docs
- Cleanup thread now respects active background processes (won't reap sandbox)
Gateway Integration (gateway/run.py, session.py, config.py):
- Session reset protection: sessions with active processes exempt from reset
- Default idle timeout increased from 2 hours to 24 hours
- from_dict fallback aligned to match (was 120, now 1440)
- session_key env var propagated to process registry for session mapping
- Crash recovery on gateway startup via checkpoint probe
- check_interval watcher: asyncio task polls process, delivers updates to platform
RL Safety (environments/):
- tool_context.py cleanup() kills background processes on episode end
- hermes_base_env.py warns when enabled_toolsets is None (loads all tools)
- Process tool safe in RL via wait() blocking the agent loop
Also:
- Added ptyprocess as optional dependency (in pyproject.toml [pty] extra + [all])
- Fixed pre-existing bug: rl_test_inference missing from TOOL_TO_TOOLSET_MAP
- Updated AGENTS.md with process management docs and project structure
- Updated README.md terminal section with process management overview
2026-02-17 02:51:31 -08:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-02-02 19:45:42 -08:00
|
|
|
## Adding New Tools
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
Requires changes in **3 files**:
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
**1. Create `tools/your_tool.py`:**
|
2026-02-02 19:45:42 -08:00
|
|
|
```python
|
2026-03-08 21:33:10 -07:00
|
|
|
import json, os
|
2026-02-21 21:03:40 -08:00
|
|
|
from tools.registry import registry
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
def check_requirements() -> bool:
|
2026-02-02 19:45:42 -08:00
|
|
|
return bool(os.getenv("EXAMPLE_API_KEY"))
|
|
|
|
|
|
|
|
|
|
def example_tool(param: str, task_id: str = None) -> str:
|
2026-03-08 21:33:10 -07:00
|
|
|
return json.dumps({"success": True, "data": "..."})
|
2026-02-21 21:03:40 -08:00
|
|
|
|
|
|
|
|
registry.register(
|
|
|
|
|
name="example_tool",
|
|
|
|
|
toolset="example",
|
2026-03-08 21:33:10 -07:00
|
|
|
schema={"name": "example_tool", "description": "...", "parameters": {...}},
|
|
|
|
|
handler=lambda args, **kw: example_tool(param=args.get("param", ""), task_id=kw.get("task_id")),
|
|
|
|
|
check_fn=check_requirements,
|
2026-02-21 21:03:40 -08:00
|
|
|
requires_env=["EXAMPLE_API_KEY"],
|
|
|
|
|
)
|
2026-02-02 19:45:42 -08:00
|
|
|
```
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
**2. Add import** in `model_tools.py` `_discover_tools()` list.
|
2026-02-21 21:03:40 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
**3. Add to `toolsets.py`** — either `_HERMES_CORE_TOOLS` (all platforms) or a new toolset.
|
2026-02-21 21:03:40 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
The registry handles schema collection, dispatch, availability checking, and error wrapping. All handlers MUST return a JSON string.
|
2026-02-21 21:03:40 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
**Agent-level tools** (todo, memory): intercepted by `run_agent.py` before `handle_function_call()`. See `todo_tool.py` for the pattern.
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
## Adding Configuration
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
### config.yaml options:
|
|
|
|
|
1. Add to `DEFAULT_CONFIG` in `hermes_cli/config.py`
|
|
|
|
|
2. Bump `_config_version` (currently 5) to trigger migration for existing users
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
### .env variables:
|
|
|
|
|
1. Add to `OPTIONAL_ENV_VARS` in `hermes_cli/config.py` with metadata:
|
2026-02-02 19:45:42 -08:00
|
|
|
```python
|
2026-03-08 21:33:10 -07:00
|
|
|
"NEW_API_KEY": {
|
|
|
|
|
"description": "What it's for",
|
|
|
|
|
"prompt": "Display name",
|
|
|
|
|
"url": "https://...",
|
|
|
|
|
"password": True,
|
|
|
|
|
"category": "tool", # provider, tool, messaging, setting
|
|
|
|
|
},
|
2026-02-02 19:45:42 -08:00
|
|
|
```
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
### Config loaders (two separate systems):
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
| Loader | Used by | Location |
|
|
|
|
|
|--------|---------|----------|
|
|
|
|
|
| `load_cli_config()` | CLI mode | `cli.py` |
|
|
|
|
|
| `load_config()` | `hermes tools`, `hermes setup` | `hermes_cli/config.py` |
|
|
|
|
|
| Direct YAML load | Gateway | `gateway/run.py` |
|
2026-02-02 19:45:42 -08:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
## Important Policies
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
### Prompt Caching Must Not Break
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
Hermes-Agent ensures caching remains valid throughout a conversation. **Do NOT implement changes that would:**
|
|
|
|
|
- Alter past context mid-conversation
|
|
|
|
|
- Change toolsets mid-conversation
|
|
|
|
|
- Reload memories or rebuild system prompts mid-conversation
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
Cache-breaking forces dramatically higher costs. The ONLY time we alter context is during context compression.
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
### Working Directory Behavior
|
|
|
|
|
- **CLI**: Uses current directory (`.` → `os.getcwd()`)
|
|
|
|
|
- **Messaging**: Uses `MESSAGING_CWD` env var (default: home directory)
|
2026-03-08 18:09:18 -07:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-03-07 22:14:21 -08:00
|
|
|
## Known Pitfalls
|
|
|
|
|
|
|
|
|
|
### DO NOT use `simple_term_menu` for interactive menus
|
2026-03-08 21:33:10 -07:00
|
|
|
Rendering bugs in tmux/iTerm2 — ghosting on scroll. Use `curses` (stdlib) instead. See `hermes_cli/tools_config.py` for the pattern.
|
2026-03-07 22:14:21 -08:00
|
|
|
|
|
|
|
|
### DO NOT use `\033[K` (ANSI erase-to-EOL) in spinner/display code
|
2026-03-08 21:33:10 -07:00
|
|
|
Leaks as literal `?[K` text under `prompt_toolkit`'s `patch_stdout`. Use space-padding: `f"\r{line}{' ' * pad}"`.
|
2026-03-07 22:14:21 -08:00
|
|
|
|
|
|
|
|
### `_last_resolved_tool_names` is a process-global in `model_tools.py`
|
2026-03-08 21:33:10 -07:00
|
|
|
When subagents overwrite this global, `execute_code` calls after delegation may fail with missing tool imports. Known bug.
|
2026-03-07 22:14:21 -08:00
|
|
|
|
|
|
|
|
### Tests must not write to `~/.hermes/`
|
2026-03-08 21:33:10 -07:00
|
|
|
The `_isolate_hermes_home` autouse fixture in `tests/conftest.py` redirects `HERMES_HOME` to a temp dir. Never hardcode `~/.hermes/` paths in tests.
|
2026-03-07 22:14:21 -08:00
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
## Testing
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
```bash
|
|
|
|
|
source .venv/bin/activate
|
|
|
|
|
python -m pytest tests/ -q # Full suite (~2500 tests, ~2 min)
|
|
|
|
|
python -m pytest tests/test_model_tools.py -q # Toolset resolution
|
|
|
|
|
python -m pytest tests/test_cli_init.py -q # CLI config loading
|
|
|
|
|
python -m pytest tests/gateway/ -q # Gateway tests
|
|
|
|
|
python -m pytest tests/tools/ -q # Tool-level tests
|
|
|
|
|
```
|
2026-02-02 19:45:42 -08:00
|
|
|
|
2026-03-08 21:33:10 -07:00
|
|
|
Always run the full suite before pushing changes.
|