feat: add documentation website (Docusaurus)
- 25 documentation pages covering Getting Started, User Guide, Developer Guide, and Reference - Docusaurus with custom amber/gold theme matching the landing page branding - GitHub Actions workflow to deploy landing page + docs to GitHub Pages - Landing page at root, docs at /docs/ on hermes-agent.nousresearch.com - Content extracted and restructured from existing repo docs (README, AGENTS.md, CONTRIBUTING.md, docs/) - Auto-deploy on push to main when website/ or landingpage/ changes
This commit is contained in:
60
.github/workflows/deploy-site.yml
vendored
Normal file
60
.github/workflows/deploy-site.yml
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
name: Deploy Site
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'website/**'
|
||||
- 'landingpage/**'
|
||||
- '.github/workflows/deploy-site.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
concurrency:
|
||||
group: pages
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deploy.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: website/package-lock.json
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
working-directory: website
|
||||
|
||||
- name: Build Docusaurus
|
||||
run: npm run build
|
||||
working-directory: website
|
||||
|
||||
- name: Stage deployment
|
||||
run: |
|
||||
mkdir -p _site/docs
|
||||
# Landing page at root
|
||||
cp -r landingpage/* _site/
|
||||
# Docusaurus at /docs/
|
||||
cp -r website/build/* _site/docs/
|
||||
# CNAME so GitHub Pages keeps the custom domain between deploys
|
||||
echo "hermes-agent.nousresearch.com" > _site/CNAME
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: _site
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deploy
|
||||
uses: actions/deploy-pages@v4
|
||||
20
website/.gitignore
vendored
Normal file
20
website/.gitignore
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# Dependencies
|
||||
/node_modules
|
||||
|
||||
# Production
|
||||
/build
|
||||
|
||||
# Generated files
|
||||
.docusaurus
|
||||
.cache-loader
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
41
website/README.md
Normal file
41
website/README.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Website
|
||||
|
||||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
|
||||
## Local Development
|
||||
|
||||
```bash
|
||||
yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
## Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```bash
|
||||
USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```bash
|
||||
GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||
8
website/docs/developer-guide/_category_.json
Normal file
8
website/docs/developer-guide/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Developer Guide",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Contribute to Hermes Agent — architecture, tools, skills, and more."
|
||||
}
|
||||
}
|
||||
208
website/docs/developer-guide/adding-tools.md
Normal file
208
website/docs/developer-guide/adding-tools.md
Normal file
@@ -0,0 +1,208 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: "Adding Tools"
|
||||
description: "How to add a new tool to Hermes Agent — schemas, handlers, registration, and toolsets"
|
||||
---
|
||||
|
||||
# Adding Tools
|
||||
|
||||
Before writing a tool, ask yourself: **should this be a [skill](creating-skills.md) instead?**
|
||||
|
||||
Make it a **Skill** when the capability can be expressed as instructions + shell commands + existing tools (arXiv search, git workflows, Docker management, PDF processing).
|
||||
|
||||
Make it a **Tool** when it requires end-to-end integration with API keys, custom processing logic, binary data handling, or streaming (browser automation, TTS, vision analysis).
|
||||
|
||||
## Overview
|
||||
|
||||
Adding a tool touches **3 files**:
|
||||
|
||||
1. **`tools/your_tool.py`** — handler, schema, check function, `registry.register()` call
|
||||
2. **`toolsets.py`** — add tool name to `_HERMES_CORE_TOOLS` (or a specific toolset)
|
||||
3. **`model_tools.py`** — add `"tools.your_tool"` to the `_discover_tools()` list
|
||||
|
||||
## Step 1: Create the Tool File
|
||||
|
||||
Every tool file follows the same structure:
|
||||
|
||||
```python
|
||||
# tools/weather_tool.py
|
||||
"""Weather Tool -- look up current weather for a location."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# --- Availability check ---
|
||||
|
||||
def check_weather_requirements() -> bool:
|
||||
"""Return True if the tool's dependencies are available."""
|
||||
return bool(os.getenv("WEATHER_API_KEY"))
|
||||
|
||||
|
||||
# --- Handler ---
|
||||
|
||||
def weather_tool(location: str, units: str = "metric") -> str:
|
||||
"""Fetch weather for a location. Returns JSON string."""
|
||||
api_key = os.getenv("WEATHER_API_KEY")
|
||||
if not api_key:
|
||||
return json.dumps({"error": "WEATHER_API_KEY not configured"})
|
||||
try:
|
||||
# ... call weather API ...
|
||||
return json.dumps({"location": location, "temp": 22, "units": units})
|
||||
except Exception as e:
|
||||
return json.dumps({"error": str(e)})
|
||||
|
||||
|
||||
# --- Schema ---
|
||||
|
||||
WEATHER_SCHEMA = {
|
||||
"name": "weather",
|
||||
"description": "Get current weather for a location.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"description": "City name or coordinates (e.g. 'London' or '51.5,-0.1')"
|
||||
},
|
||||
"units": {
|
||||
"type": "string",
|
||||
"enum": ["metric", "imperial"],
|
||||
"description": "Temperature units (default: metric)",
|
||||
"default": "metric"
|
||||
}
|
||||
},
|
||||
"required": ["location"]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# --- Registration ---
|
||||
|
||||
from tools.registry import registry
|
||||
|
||||
registry.register(
|
||||
name="weather",
|
||||
toolset="weather",
|
||||
schema=WEATHER_SCHEMA,
|
||||
handler=lambda args, **kw: weather_tool(
|
||||
location=args.get("location", ""),
|
||||
units=args.get("units", "metric")),
|
||||
check_fn=check_weather_requirements,
|
||||
requires_env=["WEATHER_API_KEY"],
|
||||
)
|
||||
```
|
||||
|
||||
### Key Rules
|
||||
|
||||
:::danger Important
|
||||
- Handlers **MUST** return a JSON string (via `json.dumps()`), never raw dicts
|
||||
- Errors **MUST** be returned as `{"error": "message"}`, never raised as exceptions
|
||||
- The `check_fn` is called when building tool definitions — if it returns `False`, the tool is silently excluded
|
||||
- The `handler` receives `(args: dict, **kwargs)` where `args` is the LLM's tool call arguments
|
||||
:::
|
||||
|
||||
## Step 2: Add to a Toolset
|
||||
|
||||
In `toolsets.py`, add the tool name:
|
||||
|
||||
```python
|
||||
# If it should be available on all platforms (CLI + messaging):
|
||||
_HERMES_CORE_TOOLS = [
|
||||
...
|
||||
"weather", # <-- add here
|
||||
]
|
||||
|
||||
# Or create a new standalone toolset:
|
||||
"weather": {
|
||||
"description": "Weather lookup tools",
|
||||
"tools": ["weather"],
|
||||
"includes": []
|
||||
},
|
||||
```
|
||||
|
||||
## Step 3: Add Discovery Import
|
||||
|
||||
In `model_tools.py`, add the module to the `_discover_tools()` list:
|
||||
|
||||
```python
|
||||
def _discover_tools():
|
||||
_modules = [
|
||||
...
|
||||
"tools.weather_tool", # <-- add here
|
||||
]
|
||||
```
|
||||
|
||||
This import triggers the `registry.register()` call at the bottom of your tool file.
|
||||
|
||||
## Async Handlers
|
||||
|
||||
If your handler needs async code, mark it with `is_async=True`:
|
||||
|
||||
```python
|
||||
async def weather_tool_async(location: str) -> str:
|
||||
async with aiohttp.ClientSession() as session:
|
||||
...
|
||||
return json.dumps(result)
|
||||
|
||||
registry.register(
|
||||
name="weather",
|
||||
toolset="weather",
|
||||
schema=WEATHER_SCHEMA,
|
||||
handler=lambda args, **kw: weather_tool_async(args.get("location", "")),
|
||||
check_fn=check_weather_requirements,
|
||||
is_async=True, # registry calls _run_async() automatically
|
||||
)
|
||||
```
|
||||
|
||||
The registry handles async bridging transparently — you never call `asyncio.run()` yourself.
|
||||
|
||||
## Handlers That Need task_id
|
||||
|
||||
Tools that manage per-session state receive `task_id` via `**kwargs`:
|
||||
|
||||
```python
|
||||
def _handle_weather(args, **kw):
|
||||
task_id = kw.get("task_id")
|
||||
return weather_tool(args.get("location", ""), task_id=task_id)
|
||||
|
||||
registry.register(
|
||||
name="weather",
|
||||
...
|
||||
handler=_handle_weather,
|
||||
)
|
||||
```
|
||||
|
||||
## Agent-Loop Intercepted Tools
|
||||
|
||||
Some tools (`todo`, `memory`, `session_search`, `delegate_task`) need access to per-session agent state. These are intercepted by `run_agent.py` before reaching the registry. The registry still holds their schemas, but `dispatch()` returns a fallback error if the intercept is bypassed.
|
||||
|
||||
## Optional: Setup Wizard Integration
|
||||
|
||||
If your tool requires an API key, add it to `hermes_cli/config.py`:
|
||||
|
||||
```python
|
||||
OPTIONAL_ENV_VARS = {
|
||||
...
|
||||
"WEATHER_API_KEY": {
|
||||
"description": "Weather API key for weather lookup",
|
||||
"prompt": "Weather API key",
|
||||
"url": "https://weatherapi.com/",
|
||||
"tools": ["weather"],
|
||||
"password": True,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## Checklist
|
||||
|
||||
- [ ] Tool file created with handler, schema, check function, and registration
|
||||
- [ ] Added to appropriate toolset in `toolsets.py`
|
||||
- [ ] Discovery import added to `model_tools.py`
|
||||
- [ ] Handler returns JSON strings, errors returned as `{"error": "..."}`
|
||||
- [ ] Optional: API key added to `OPTIONAL_ENV_VARS` in `hermes_cli/config.py`
|
||||
- [ ] Optional: Added to `toolset_distributions.py` for batch processing
|
||||
- [ ] Tested with `hermes chat -q "Use the weather tool for London"`
|
||||
215
website/docs/developer-guide/architecture.md
Normal file
215
website/docs/developer-guide/architecture.md
Normal file
@@ -0,0 +1,215 @@
|
||||
---
|
||||
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)
|
||||
│ ├── file_operations.py # read_file, write_file, search, patch
|
||||
│ ├── 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
|
||||
│ ├── skill_tools.py # Skill search, load, manage
|
||||
│ └── environments/ # Terminal execution backends
|
||||
│ ├── base.py # BaseEnvironment ABC
|
||||
│ ├── local.py, docker.py, ssh.py, singularity.py, modal.py
|
||||
│
|
||||
├── 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/)
|
||||
├── 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:
|
||||
result = await execute_tool(tool_call)
|
||||
messages.append(tool_result_message(result))
|
||||
turns += 1
|
||||
else:
|
||||
return response.content
|
||||
```
|
||||
|
||||
## AIAgent Class
|
||||
|
||||
```python
|
||||
class AIAgent:
|
||||
def __init__(
|
||||
self,
|
||||
model: str = "anthropic/claude-sonnet-4",
|
||||
api_key: str = None,
|
||||
base_url: str = "https://openrouter.ai/api/v1",
|
||||
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,
|
||||
):
|
||||
...
|
||||
|
||||
def chat(self, user_message: str, task_id: str = None) -> str:
|
||||
# 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
|
||||
- Pasting 5+ lines auto-saves to `~/.hermes/pastes/` and collapses
|
||||
|
||||
## 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
|
||||
231
website/docs/developer-guide/contributing.md
Normal file
231
website/docs/developer-guide/contributing.md
Normal file
@@ -0,0 +1,231 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: "Contributing"
|
||||
description: "How to contribute to Hermes Agent — dev setup, code style, PR process"
|
||||
---
|
||||
|
||||
# Contributing
|
||||
|
||||
Thank you for contributing to Hermes Agent! This guide covers setting up your dev environment, understanding the codebase, and getting your PR merged.
|
||||
|
||||
## Contribution Priorities
|
||||
|
||||
We value contributions in this order:
|
||||
|
||||
1. **Bug fixes** — crashes, incorrect behavior, data loss
|
||||
2. **Cross-platform compatibility** — Windows, macOS, different Linux distros
|
||||
3. **Security hardening** — shell injection, prompt injection, path traversal
|
||||
4. **Performance and robustness** — retry logic, error handling, graceful degradation
|
||||
5. **New skills** — broadly useful ones (see [Creating Skills](creating-skills.md))
|
||||
6. **New tools** — rarely needed; most capabilities should be skills
|
||||
7. **Documentation** — fixes, clarifications, new examples
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
|
||||
| Requirement | Notes |
|
||||
|-------------|-------|
|
||||
| **Git** | With `--recurse-submodules` support |
|
||||
| **Python 3.11+** | uv will install it if missing |
|
||||
| **uv** | Fast Python package manager ([install](https://docs.astral.sh/uv/)) |
|
||||
| **Node.js 18+** | Optional — needed for browser tools and WhatsApp bridge |
|
||||
|
||||
### Clone and Install
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
|
||||
cd hermes-agent
|
||||
|
||||
# Create venv with Python 3.11
|
||||
uv venv venv --python 3.11
|
||||
export VIRTUAL_ENV="$(pwd)/venv"
|
||||
|
||||
# Install with all extras (messaging, cron, CLI menus, dev tools)
|
||||
uv pip install -e ".[all,dev]"
|
||||
uv pip install -e "./mini-swe-agent"
|
||||
uv pip install -e "./tinker-atropos"
|
||||
|
||||
# Optional: browser tools
|
||||
npm install
|
||||
```
|
||||
|
||||
### Configure for Development
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
|
||||
cp cli-config.yaml.example ~/.hermes/config.yaml
|
||||
touch ~/.hermes/.env
|
||||
|
||||
# Add at minimum an LLM provider key:
|
||||
echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env
|
||||
```
|
||||
|
||||
### Run
|
||||
|
||||
```bash
|
||||
# Symlink for global access
|
||||
mkdir -p ~/.local/bin
|
||||
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
|
||||
|
||||
# Verify
|
||||
hermes doctor
|
||||
hermes chat -q "Hello"
|
||||
```
|
||||
|
||||
### Run Tests
|
||||
|
||||
```bash
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
- **PEP 8** with practical exceptions (no strict line length enforcement)
|
||||
- **Comments**: Only when explaining non-obvious intent, trade-offs, or API quirks
|
||||
- **Error handling**: Catch specific exceptions. Use `logger.warning()`/`logger.error()` with `exc_info=True` for unexpected errors
|
||||
- **Cross-platform**: Never assume Unix (see below)
|
||||
|
||||
## Cross-Platform Compatibility
|
||||
|
||||
Hermes runs on Linux, macOS, and Windows. Critical rules:
|
||||
|
||||
### 1. `termios` and `fcntl` are Unix-only
|
||||
|
||||
Always catch both `ImportError` and `NotImplementedError`:
|
||||
|
||||
```python
|
||||
try:
|
||||
from simple_term_menu import TerminalMenu
|
||||
menu = TerminalMenu(options)
|
||||
idx = menu.show()
|
||||
except (ImportError, NotImplementedError):
|
||||
# Fallback: numbered menu for Windows
|
||||
for i, opt in enumerate(options):
|
||||
print(f" {i+1}. {opt}")
|
||||
idx = int(input("Choice: ")) - 1
|
||||
```
|
||||
|
||||
### 2. File encoding
|
||||
|
||||
Windows may save `.env` files in `cp1252`:
|
||||
|
||||
```python
|
||||
try:
|
||||
load_dotenv(env_path)
|
||||
except UnicodeDecodeError:
|
||||
load_dotenv(env_path, encoding="latin-1")
|
||||
```
|
||||
|
||||
### 3. Process management
|
||||
|
||||
`os.setsid()`, `os.killpg()`, and signal handling differ on Windows:
|
||||
|
||||
```python
|
||||
import platform
|
||||
if platform.system() != "Windows":
|
||||
kwargs["preexec_fn"] = os.setsid
|
||||
```
|
||||
|
||||
### 4. Path separators
|
||||
|
||||
Use `pathlib.Path` instead of string concatenation with `/`.
|
||||
|
||||
### 5. Shell commands in installers
|
||||
|
||||
If you change `scripts/install.sh`, check if the equivalent change is needed in `scripts/install.ps1`.
|
||||
|
||||
## Security Considerations
|
||||
|
||||
Hermes has terminal access. Security matters.
|
||||
|
||||
### Existing Protections
|
||||
|
||||
| Layer | Implementation |
|
||||
|-------|---------------|
|
||||
| **Sudo password piping** | Uses `shlex.quote()` to prevent shell injection |
|
||||
| **Dangerous command detection** | Regex patterns in `tools/approval.py` with user approval flow |
|
||||
| **Cron prompt injection** | Scanner blocks instruction-override patterns |
|
||||
| **Write deny list** | Protected paths resolved via `os.path.realpath()` to prevent symlink bypass |
|
||||
| **Skills guard** | Security scanner for hub-installed skills |
|
||||
| **Code execution sandbox** | Child process runs with API keys stripped |
|
||||
| **Container hardening** | Docker: all capabilities dropped, no privilege escalation, PID limits |
|
||||
|
||||
### Contributing Security-Sensitive Code
|
||||
|
||||
- Always use `shlex.quote()` when interpolating user input into shell commands
|
||||
- Resolve symlinks with `os.path.realpath()` before access control checks
|
||||
- Don't log secrets
|
||||
- Catch broad exceptions around tool execution
|
||||
- Test on all platforms if your change touches file paths or processes
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
### Branch Naming
|
||||
|
||||
```
|
||||
fix/description # Bug fixes
|
||||
feat/description # New features
|
||||
docs/description # Documentation
|
||||
test/description # Tests
|
||||
refactor/description # Code restructuring
|
||||
```
|
||||
|
||||
### Before Submitting
|
||||
|
||||
1. **Run tests**: `pytest tests/ -v`
|
||||
2. **Test manually**: Run `hermes` and exercise the code path you changed
|
||||
3. **Check cross-platform impact**: Consider Windows and macOS
|
||||
4. **Keep PRs focused**: One logical change per PR
|
||||
|
||||
### PR Description
|
||||
|
||||
Include:
|
||||
- **What** changed and **why**
|
||||
- **How to test** it
|
||||
- **What platforms** you tested on
|
||||
- Reference any related issues
|
||||
|
||||
### Commit Messages
|
||||
|
||||
We use [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
```
|
||||
<type>(<scope>): <description>
|
||||
```
|
||||
|
||||
| Type | Use for |
|
||||
|------|---------|
|
||||
| `fix` | Bug fixes |
|
||||
| `feat` | New features |
|
||||
| `docs` | Documentation |
|
||||
| `test` | Tests |
|
||||
| `refactor` | Code restructuring |
|
||||
| `chore` | Build, CI, dependency updates |
|
||||
|
||||
Scopes: `cli`, `gateway`, `tools`, `skills`, `agent`, `install`, `whatsapp`, `security`
|
||||
|
||||
Examples:
|
||||
```
|
||||
fix(cli): prevent crash in save_config_value when model is a string
|
||||
feat(gateway): add WhatsApp multi-user session isolation
|
||||
fix(security): prevent shell injection in sudo password piping
|
||||
```
|
||||
|
||||
## Reporting Issues
|
||||
|
||||
- Use [GitHub Issues](https://github.com/NousResearch/hermes-agent/issues)
|
||||
- Include: OS, Python version, Hermes version (`hermes version`), full error traceback
|
||||
- Include steps to reproduce
|
||||
- Check existing issues before creating duplicates
|
||||
- For security vulnerabilities, please report privately
|
||||
|
||||
## Community
|
||||
|
||||
- **Discord**: [discord.gg/NousResearch](https://discord.gg/NousResearch)
|
||||
- **GitHub Discussions**: For design proposals and architecture discussions
|
||||
- **Skills Hub**: Upload specialized skills and share with the community
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree that your contributions will be licensed under the [MIT License](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE).
|
||||
140
website/docs/developer-guide/creating-skills.md
Normal file
140
website/docs/developer-guide/creating-skills.md
Normal file
@@ -0,0 +1,140 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: "Creating Skills"
|
||||
description: "How to create skills for Hermes Agent — SKILL.md format, guidelines, and publishing"
|
||||
---
|
||||
|
||||
# Creating Skills
|
||||
|
||||
Skills are the preferred way to add new capabilities to Hermes Agent. They're easier to create than tools, require no code changes to the agent, and can be shared with the community.
|
||||
|
||||
## Should it be a Skill or a Tool?
|
||||
|
||||
Make it a **Skill** when:
|
||||
- The capability can be expressed as instructions + shell commands + existing tools
|
||||
- It wraps an external CLI or API that the agent can call via `terminal` or `web_extract`
|
||||
- It doesn't need custom Python integration or API key management baked into the agent
|
||||
- Examples: arXiv search, git workflows, Docker management, PDF processing, email via CLI tools
|
||||
|
||||
Make it a **Tool** when:
|
||||
- It requires end-to-end integration with API keys, auth flows, or multi-component configuration
|
||||
- It needs custom processing logic that must execute precisely every time
|
||||
- It handles binary data, streaming, or real-time events
|
||||
- Examples: browser automation, TTS, vision analysis
|
||||
|
||||
## Skill Directory Structure
|
||||
|
||||
Bundled skills live in `skills/` organized by category:
|
||||
|
||||
```
|
||||
skills/
|
||||
├── research/
|
||||
│ └── arxiv/
|
||||
│ ├── SKILL.md # Required: main instructions
|
||||
│ └── scripts/ # Optional: helper scripts
|
||||
│ └── search_arxiv.py
|
||||
├── productivity/
|
||||
│ └── ocr-and-documents/
|
||||
│ ├── SKILL.md
|
||||
│ ├── scripts/
|
||||
│ └── references/
|
||||
└── ...
|
||||
```
|
||||
|
||||
## SKILL.md Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-skill
|
||||
description: Brief description (shown in skill search results)
|
||||
version: 1.0.0
|
||||
author: Your Name
|
||||
license: MIT
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [Category, Subcategory, Keywords]
|
||||
related_skills: [other-skill-name]
|
||||
---
|
||||
|
||||
# Skill Title
|
||||
|
||||
Brief intro.
|
||||
|
||||
## When to Use
|
||||
Trigger conditions — when should the agent load this skill?
|
||||
|
||||
## Quick Reference
|
||||
Table of common commands or API calls.
|
||||
|
||||
## Procedure
|
||||
Step-by-step instructions the agent follows.
|
||||
|
||||
## Pitfalls
|
||||
Known failure modes and how to handle them.
|
||||
|
||||
## Verification
|
||||
How the agent confirms it worked.
|
||||
```
|
||||
|
||||
## Skill Guidelines
|
||||
|
||||
### No External Dependencies
|
||||
|
||||
Prefer stdlib Python, curl, and existing Hermes tools (`web_extract`, `terminal`, `read_file`). If a dependency is needed, document installation steps in the skill.
|
||||
|
||||
### Progressive Disclosure
|
||||
|
||||
Put the most common workflow first. Edge cases and advanced usage go at the bottom. This keeps token usage low for common tasks.
|
||||
|
||||
### Include Helper Scripts
|
||||
|
||||
For XML/JSON parsing or complex logic, include helper scripts in `scripts/` — don't expect the LLM to write parsers inline every time.
|
||||
|
||||
### Test It
|
||||
|
||||
Run the skill and verify the agent follows the instructions correctly:
|
||||
|
||||
```bash
|
||||
hermes --toolsets skills -q "Use the X skill to do Y"
|
||||
```
|
||||
|
||||
## Should the Skill Be Bundled?
|
||||
|
||||
Bundled skills (in `skills/`) ship with every Hermes install. They should be **broadly useful to most users**:
|
||||
|
||||
- Document handling, web research, common dev workflows, system administration
|
||||
- Used regularly by a wide range of people
|
||||
|
||||
If your skill is specialized (a niche engineering tool, a specific SaaS integration, a game), it's better suited for a **Skills Hub** — upload it to a registry and share it via `hermes skills install`.
|
||||
|
||||
## Publishing Skills
|
||||
|
||||
### To the Skills Hub
|
||||
|
||||
```bash
|
||||
hermes skills publish skills/my-skill --to github --repo owner/repo
|
||||
```
|
||||
|
||||
### To a Custom Repository
|
||||
|
||||
Add your repo as a tap:
|
||||
|
||||
```bash
|
||||
hermes skills tap add owner/repo
|
||||
```
|
||||
|
||||
Users can then search and install from your repository.
|
||||
|
||||
## Security Scanning
|
||||
|
||||
All hub-installed skills go through a security scanner that checks for:
|
||||
|
||||
- Data exfiltration patterns
|
||||
- Prompt injection attempts
|
||||
- Destructive commands
|
||||
- Shell injection
|
||||
|
||||
Trust levels:
|
||||
- `builtin` — ships with Hermes (always trusted)
|
||||
- `trusted` — from openai/skills, anthropics/skills
|
||||
- `community` — any findings = blocked unless `--force`
|
||||
8
website/docs/getting-started/_category_.json
Normal file
8
website/docs/getting-started/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Getting Started",
|
||||
"position": 1,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Get up and running with Hermes Agent in minutes."
|
||||
}
|
||||
}
|
||||
293
website/docs/getting-started/installation.md
Normal file
293
website/docs/getting-started/installation.md
Normal file
@@ -0,0 +1,293 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: "Installation"
|
||||
description: "Install Hermes Agent on Linux, macOS, Windows, or WSL"
|
||||
---
|
||||
|
||||
# Installation
|
||||
|
||||
Get Hermes Agent up and running in under two minutes with the one-line installer, or follow the manual steps for full control.
|
||||
|
||||
## Quick Install
|
||||
|
||||
### Linux / macOS / WSL
|
||||
|
||||
```bash
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
```
|
||||
|
||||
### Windows (PowerShell)
|
||||
|
||||
```powershell
|
||||
irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
### Windows (CMD)
|
||||
|
||||
```cmd
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.cmd -o install.cmd && install.cmd && del install.cmd
|
||||
```
|
||||
|
||||
:::warning Windows Note
|
||||
[Git for Windows](https://git-scm.com/download/win) is required. Hermes uses Git Bash internally for shell commands.
|
||||
:::
|
||||
|
||||
### What the Installer Does
|
||||
|
||||
The installer handles everything automatically:
|
||||
|
||||
- Installs [uv](https://docs.astral.sh/uv/) (fast Python package manager) if not present
|
||||
- Installs Python 3.11 via uv if not already available (no sudo needed)
|
||||
- Clones to `~/.hermes/hermes-agent` (with submodules: mini-swe-agent, tinker-atropos)
|
||||
- Creates a virtual environment with Python 3.11
|
||||
- Installs all dependencies and submodule packages
|
||||
- Sets up the `hermes` command globally (no venv activation needed)
|
||||
- Runs the interactive setup wizard
|
||||
|
||||
### After Installation
|
||||
|
||||
Reload your shell and start chatting:
|
||||
|
||||
```bash
|
||||
source ~/.bashrc # or: source ~/.zshrc (Windows: restart your terminal)
|
||||
hermes setup # Configure API keys (if you skipped during install)
|
||||
hermes # Start chatting!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
| Requirement | Minimum Version | Check Command | Notes |
|
||||
|-------------|----------------|---------------|-------|
|
||||
| **Git** | Any recent | `git --version` | Required |
|
||||
| **Node.js** | 18+ | `node --version` | Optional — needed for browser automation and WhatsApp bridge |
|
||||
| **ripgrep** | Any | `rg --version` | Optional — faster file search (falls back to grep) |
|
||||
|
||||
:::info
|
||||
Python and pip are **not** prerequisites. The installer uses [uv](https://docs.astral.sh/uv/) to provision Python 3.11 automatically (no sudo needed). If you already have Python 3.11+ installed, uv will use it.
|
||||
:::
|
||||
|
||||
<details>
|
||||
<summary><strong>Installing prerequisites by platform</strong></summary>
|
||||
|
||||
**Ubuntu / Debian:**
|
||||
```bash
|
||||
sudo apt update && sudo apt install git
|
||||
# Optional:
|
||||
sudo apt install ripgrep nodejs npm
|
||||
```
|
||||
|
||||
**macOS (Homebrew):**
|
||||
```bash
|
||||
brew install git
|
||||
# Optional:
|
||||
brew install ripgrep node
|
||||
```
|
||||
|
||||
**Windows (native):**
|
||||
Hermes runs natively on Windows using [Git for Windows](https://git-scm.com/download/win) (which provides Git Bash for shell commands). Install Git for Windows first, then use the PowerShell or CMD quick-install command above. WSL also works — follow the Ubuntu instructions.
|
||||
|
||||
</details>
|
||||
|
||||
---
|
||||
|
||||
## Manual Installation
|
||||
|
||||
If you prefer full control over the installation process, follow these steps.
|
||||
|
||||
### Step 1: Clone the Repository
|
||||
|
||||
Clone with `--recurse-submodules` to pull the required submodules:
|
||||
|
||||
```bash
|
||||
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
|
||||
cd hermes-agent
|
||||
```
|
||||
|
||||
If you already cloned without `--recurse-submodules`:
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### Step 2: Install uv & Create Virtual Environment
|
||||
|
||||
```bash
|
||||
# Install uv (if not already installed)
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Create venv with Python 3.11 (uv downloads it if not present — no sudo needed)
|
||||
uv venv venv --python 3.11
|
||||
```
|
||||
|
||||
:::tip
|
||||
You do **not** need to activate the venv to use `hermes`. The entry point has a hardcoded shebang pointing to the venv Python, so it works globally once symlinked.
|
||||
:::
|
||||
|
||||
### Step 3: Install Python Dependencies
|
||||
|
||||
```bash
|
||||
# Tell uv which venv to install into
|
||||
export VIRTUAL_ENV="$(pwd)/venv"
|
||||
|
||||
# Install with all extras
|
||||
uv pip install -e ".[all]"
|
||||
```
|
||||
|
||||
If you only want the core agent (no Telegram/Discord/cron support):
|
||||
```bash
|
||||
uv pip install -e "."
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><strong>Optional extras breakdown</strong></summary>
|
||||
|
||||
| Extra | What it adds | Install command |
|
||||
|-------|-------------|-----------------|
|
||||
| `all` | Everything below | `uv pip install -e ".[all]"` |
|
||||
| `messaging` | Telegram & Discord gateway | `uv pip install -e ".[messaging]"` |
|
||||
| `cron` | Cron expression parsing for scheduled tasks | `uv pip install -e ".[cron]"` |
|
||||
| `cli` | Terminal menu UI for setup wizard | `uv pip install -e ".[cli]"` |
|
||||
| `modal` | Modal cloud execution backend | `uv pip install -e ".[modal]"` |
|
||||
| `dev` | pytest & test utilities | `uv pip install -e ".[dev]"` |
|
||||
|
||||
You can combine extras: `uv pip install -e ".[messaging,cron]"`
|
||||
|
||||
</details>
|
||||
|
||||
### Step 4: Install Submodule Packages
|
||||
|
||||
```bash
|
||||
# Terminal tool backend (required for terminal/command-execution)
|
||||
uv pip install -e "./mini-swe-agent"
|
||||
|
||||
# RL training backend
|
||||
uv pip install -e "./tinker-atropos"
|
||||
```
|
||||
|
||||
Both are optional — if you skip them, the corresponding toolsets simply won't be available.
|
||||
|
||||
### Step 5: Install Node.js Dependencies (Optional)
|
||||
|
||||
Only needed for **browser automation** (Browserbase-powered):
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
### Step 6: Create the Configuration Directory
|
||||
|
||||
```bash
|
||||
# Create the directory structure
|
||||
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
|
||||
|
||||
# Copy the example config file
|
||||
cp cli-config.yaml.example ~/.hermes/config.yaml
|
||||
|
||||
# Create an empty .env file for API keys
|
||||
touch ~/.hermes/.env
|
||||
```
|
||||
|
||||
### Step 7: Add Your API Keys
|
||||
|
||||
Open `~/.hermes/.env` and add at minimum an LLM provider key:
|
||||
|
||||
```bash
|
||||
# Required — at least one LLM provider:
|
||||
OPENROUTER_API_KEY=sk-or-v1-your-key-here
|
||||
|
||||
# Optional — enable additional tools:
|
||||
FIRECRAWL_API_KEY=fc-your-key # Web search & scraping
|
||||
FAL_KEY=your-fal-key # Image generation (FLUX)
|
||||
```
|
||||
|
||||
Or set them via the CLI:
|
||||
```bash
|
||||
hermes config set OPENROUTER_API_KEY sk-or-v1-your-key-here
|
||||
```
|
||||
|
||||
### Step 8: Add `hermes` to Your PATH
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.local/bin
|
||||
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
|
||||
```
|
||||
|
||||
If `~/.local/bin` isn't on your PATH, add it to your shell config:
|
||||
|
||||
```bash
|
||||
# Bash
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc
|
||||
|
||||
# Zsh
|
||||
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
|
||||
|
||||
# Fish
|
||||
fish_add_path $HOME/.local/bin
|
||||
```
|
||||
|
||||
### Step 9: Run the Setup Wizard (Optional)
|
||||
|
||||
```bash
|
||||
hermes setup
|
||||
```
|
||||
|
||||
### Step 10: Verify the Installation
|
||||
|
||||
```bash
|
||||
hermes version # Check that the command is available
|
||||
hermes doctor # Run diagnostics to verify everything is working
|
||||
hermes status # Check your configuration
|
||||
hermes chat -q "Hello! What tools do you have available?"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick-Reference: Manual Install (Condensed)
|
||||
|
||||
For those who just want the commands:
|
||||
|
||||
```bash
|
||||
# Install uv
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Clone & enter
|
||||
git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git
|
||||
cd hermes-agent
|
||||
|
||||
# Create venv with Python 3.11
|
||||
uv venv venv --python 3.11
|
||||
export VIRTUAL_ENV="$(pwd)/venv"
|
||||
|
||||
# Install everything
|
||||
uv pip install -e ".[all]"
|
||||
uv pip install -e "./mini-swe-agent"
|
||||
uv pip install -e "./tinker-atropos"
|
||||
npm install # optional, for browser tools
|
||||
|
||||
# Configure
|
||||
mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills}
|
||||
cp cli-config.yaml.example ~/.hermes/config.yaml
|
||||
touch ~/.hermes/.env
|
||||
echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env
|
||||
|
||||
# Make hermes available globally
|
||||
mkdir -p ~/.local/bin
|
||||
ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes
|
||||
|
||||
# Verify
|
||||
hermes doctor
|
||||
hermes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Problem | Solution |
|
||||
|---------|----------|
|
||||
| `hermes: command not found` | Reload your shell (`source ~/.bashrc`) or check PATH |
|
||||
| `API key not set` | Run `hermes setup` or `hermes config set OPENROUTER_API_KEY your_key` |
|
||||
| Missing config after update | Run `hermes config check` then `hermes config migrate` |
|
||||
|
||||
For more diagnostics, run `hermes doctor` — it will tell you exactly what's missing and how to fix it.
|
||||
176
website/docs/getting-started/quickstart.md
Normal file
176
website/docs/getting-started/quickstart.md
Normal file
@@ -0,0 +1,176 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: "Quickstart"
|
||||
description: "Your first conversation with Hermes Agent — from install to chatting in 2 minutes"
|
||||
---
|
||||
|
||||
# Quickstart
|
||||
|
||||
This guide walks you through installing Hermes Agent, setting up a provider, and having your first conversation. By the end, you'll know the key features and how to explore further.
|
||||
|
||||
## 1. Install Hermes Agent
|
||||
|
||||
Run the one-line installer:
|
||||
|
||||
```bash
|
||||
# Linux / macOS / WSL
|
||||
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
|
||||
```
|
||||
|
||||
```powershell
|
||||
# Windows (PowerShell)
|
||||
irm https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.ps1 | iex
|
||||
```
|
||||
|
||||
After it finishes, reload your shell:
|
||||
|
||||
```bash
|
||||
source ~/.bashrc # or source ~/.zshrc
|
||||
```
|
||||
|
||||
## 2. Set Up a Provider
|
||||
|
||||
The installer runs the setup wizard automatically. If you skipped it, run:
|
||||
|
||||
```bash
|
||||
hermes setup
|
||||
```
|
||||
|
||||
This walks you through selecting an inference provider:
|
||||
|
||||
| Provider | What it is | How to set up |
|
||||
|----------|-----------|---------------|
|
||||
| **Nous Portal** | Subscription-based, zero-config | OAuth login via `hermes model` |
|
||||
| **OpenRouter** | 200+ models, pay-per-use | Enter your API key |
|
||||
| **Custom Endpoint** | VLLM, SGLang, any OpenAI-compatible API | Set base URL + API key |
|
||||
|
||||
:::tip
|
||||
You can switch providers at any time with `hermes model` — no code changes, no lock-in.
|
||||
:::
|
||||
|
||||
## 3. Start Chatting
|
||||
|
||||
```bash
|
||||
hermes
|
||||
```
|
||||
|
||||
That's it! You'll see a welcome banner with your model, available tools, and skills. Type a message and press Enter.
|
||||
|
||||
```
|
||||
❯ What can you help me with?
|
||||
```
|
||||
|
||||
The agent has access to tools for web search, file operations, terminal commands, and more — all out of the box.
|
||||
|
||||
## 4. Try Key Features
|
||||
|
||||
### Ask it to use the terminal
|
||||
|
||||
```
|
||||
❯ What's my disk usage? Show the top 5 largest directories.
|
||||
```
|
||||
|
||||
The agent will run terminal commands on your behalf and show you the results.
|
||||
|
||||
### Use slash commands
|
||||
|
||||
Type `/` to see an autocomplete dropdown of all commands:
|
||||
|
||||
| Command | What it does |
|
||||
|---------|-------------|
|
||||
| `/help` | Show all available commands |
|
||||
| `/tools` | List available tools |
|
||||
| `/model` | Switch models interactively |
|
||||
| `/personality pirate` | Try a fun personality |
|
||||
| `/save` | Save the conversation |
|
||||
|
||||
### Multi-line input
|
||||
|
||||
Press `Alt+Enter` or `Ctrl+J` to add a new line. Great for pasting code or writing detailed prompts.
|
||||
|
||||
### Interrupt the agent
|
||||
|
||||
If the agent is taking too long, just type a new message and press Enter — it interrupts the current task and switches to your new instructions. `Ctrl+C` also works.
|
||||
|
||||
### Resume a session
|
||||
|
||||
When you exit, hermes prints a resume command:
|
||||
|
||||
```bash
|
||||
hermes --continue # Resume the most recent session
|
||||
hermes -c # Short form
|
||||
```
|
||||
|
||||
## 5. Explore Further
|
||||
|
||||
Here are some things to try next:
|
||||
|
||||
### Set up a sandboxed terminal
|
||||
|
||||
For safety, run the agent in a Docker container or on a remote server:
|
||||
|
||||
```bash
|
||||
hermes config set terminal.backend docker # Docker isolation
|
||||
hermes config set terminal.backend ssh # Remote server
|
||||
```
|
||||
|
||||
### Connect messaging platforms
|
||||
|
||||
Chat with Hermes from your phone via Telegram, Discord, Slack, or WhatsApp:
|
||||
|
||||
```bash
|
||||
hermes gateway setup # Interactive platform configuration
|
||||
```
|
||||
|
||||
### Schedule automated tasks
|
||||
|
||||
```
|
||||
❯ Every morning at 9am, check Hacker News for AI news and send me a summary on Telegram.
|
||||
```
|
||||
|
||||
The agent will set up a cron job that runs automatically via the gateway.
|
||||
|
||||
### Browse and install skills
|
||||
|
||||
```bash
|
||||
hermes skills search kubernetes
|
||||
hermes skills install openai/skills/k8s
|
||||
```
|
||||
|
||||
Or use the `/skills` slash command inside chat.
|
||||
|
||||
### Try MCP servers
|
||||
|
||||
Connect to external tools via the Model Context Protocol:
|
||||
|
||||
```yaml
|
||||
# Add to ~/.hermes/config.yaml
|
||||
mcp_servers:
|
||||
github:
|
||||
command: npx
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxx"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes` | Start chatting |
|
||||
| `hermes setup` | Configure providers and settings |
|
||||
| `hermes model` | Switch provider or model |
|
||||
| `hermes tools` | See all available tools |
|
||||
| `hermes doctor` | Diagnose issues |
|
||||
| `hermes update` | Update to latest version |
|
||||
| `hermes gateway` | Start the messaging gateway |
|
||||
| `hermes --continue` | Resume last session |
|
||||
|
||||
## Next Steps
|
||||
|
||||
- **[CLI Guide](../user-guide/cli.md)** — Master the terminal interface
|
||||
- **[Configuration](../user-guide/configuration.md)** — Customize your setup
|
||||
- **[Messaging Gateway](../user-guide/messaging/index.md)** — Connect Telegram, Discord, Slack, WhatsApp
|
||||
- **[Tools & Toolsets](../user-guide/features/tools.md)** — Explore available capabilities
|
||||
80
website/docs/getting-started/updating.md
Normal file
80
website/docs/getting-started/updating.md
Normal file
@@ -0,0 +1,80 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: "Updating & Uninstalling"
|
||||
description: "How to update Hermes Agent to the latest version or uninstall it"
|
||||
---
|
||||
|
||||
# Updating & Uninstalling
|
||||
|
||||
## Updating
|
||||
|
||||
Update to the latest version with a single command:
|
||||
|
||||
```bash
|
||||
hermes update
|
||||
```
|
||||
|
||||
This pulls the latest code, updates dependencies, and prompts you to configure any new options that were added since your last update.
|
||||
|
||||
:::tip
|
||||
After updating, run `hermes config check` to see if there are new configuration options available, then `hermes config migrate` to interactively add any missing ones.
|
||||
:::
|
||||
|
||||
### Updating from Messaging Platforms
|
||||
|
||||
You can also update directly from Telegram, Discord, Slack, or WhatsApp by sending:
|
||||
|
||||
```
|
||||
/update
|
||||
```
|
||||
|
||||
This pulls the latest code, updates dependencies, and restarts the gateway.
|
||||
|
||||
### Manual Update
|
||||
|
||||
If you installed manually (not via the quick installer):
|
||||
|
||||
```bash
|
||||
cd /path/to/hermes-agent
|
||||
export VIRTUAL_ENV="$(pwd)/venv"
|
||||
|
||||
# Pull latest code and submodules
|
||||
git pull origin main
|
||||
git submodule update --init --recursive
|
||||
|
||||
# Reinstall (picks up new dependencies)
|
||||
uv pip install -e ".[all]"
|
||||
uv pip install -e "./mini-swe-agent"
|
||||
uv pip install -e "./tinker-atropos"
|
||||
|
||||
# Check for new config options
|
||||
hermes config check
|
||||
hermes config migrate # Interactively add any missing options
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Uninstalling
|
||||
|
||||
```bash
|
||||
hermes uninstall
|
||||
```
|
||||
|
||||
The uninstaller gives you the option to keep your configuration files (`~/.hermes/`) for a future reinstall.
|
||||
|
||||
### Manual Uninstall
|
||||
|
||||
```bash
|
||||
rm -f ~/.local/bin/hermes
|
||||
rm -rf /path/to/hermes-agent
|
||||
rm -rf ~/.hermes # Optional — keep if you plan to reinstall
|
||||
```
|
||||
|
||||
:::info
|
||||
If you installed the gateway as a system service, stop and disable it first:
|
||||
```bash
|
||||
hermes gateway stop
|
||||
# Linux: systemctl --user disable hermes-gateway
|
||||
# macOS: launchctl remove ai.hermes.gateway
|
||||
```
|
||||
:::
|
||||
46
website/docs/index.md
Normal file
46
website/docs/index.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
slug: /
|
||||
sidebar_position: 0
|
||||
title: "Hermes Agent Documentation"
|
||||
description: "An open-source AI agent that grows with you — learns your projects, builds its own skills, and reaches you wherever you are."
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
||||
# Hermes Agent
|
||||
|
||||
An open-source AI agent that grows with you — learns your projects, builds its own skills, and reaches you wherever you are.
|
||||
|
||||
<div style={{display: 'flex', gap: '1rem', marginBottom: '2rem', flexWrap: 'wrap'}}>
|
||||
<a href="/docs/getting-started/installation" style={{display: 'inline-block', padding: '0.6rem 1.2rem', backgroundColor: '#FFD700', color: '#07070d', borderRadius: '8px', fontWeight: 600, textDecoration: 'none'}}>Get Started →</a>
|
||||
<a href="https://github.com/NousResearch/hermes-agent" style={{display: 'inline-block', padding: '0.6rem 1.2rem', border: '1px solid rgba(255,215,0,0.2)', borderRadius: '8px', textDecoration: 'none'}}>View on GitHub</a>
|
||||
</div>
|
||||
|
||||
## What is Hermes Agent?
|
||||
|
||||
It's not a coding copilot tethered to an IDE or a chatbot wrapper around a single API. It's an **autonomous agent** that lives on your server, remembers what it learns, and gets more capable the longer it runs.
|
||||
|
||||
## Quick Links
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| 🚀 **[Installation](/docs/getting-started/installation)** | Install in 60 seconds on Linux, macOS, or Windows |
|
||||
| 📖 **[Quickstart Tutorial](/docs/getting-started/quickstart)** | Your first conversation and key features to try |
|
||||
| ⚙️ **[Configuration](/docs/user-guide/configuration)** | Config file, providers, models, and options |
|
||||
| 💬 **[Messaging Gateway](/docs/user-guide/messaging)** | Set up Telegram, Discord, Slack, or WhatsApp |
|
||||
| 🔧 **[Tools & Toolsets](/docs/user-guide/features/tools)** | 40+ built-in tools and how to configure them |
|
||||
| 🧠 **[Memory System](/docs/user-guide/features/memory)** | Persistent memory that grows across sessions |
|
||||
| 📚 **[Skills System](/docs/user-guide/features/skills)** | Procedural memory the agent creates and reuses |
|
||||
| 🔌 **[MCP Integration](/docs/user-guide/features/mcp)** | Connect to any MCP server for extended capabilities |
|
||||
| 🏗️ **[Architecture](/docs/developer-guide/architecture)** | How it works under the hood |
|
||||
| 🤝 **[Contributing](/docs/developer-guide/contributing)** | Development setup and PR process |
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Lives where you do** — CLI, Telegram, Discord, Slack, WhatsApp, all from one gateway
|
||||
- **Grows the longer it runs** — Persistent memory and self-created skills
|
||||
- **Scheduled automations** — Built-in cron with delivery to any platform
|
||||
- **Delegates & parallelizes** — Spawn isolated subagents for parallel workstreams
|
||||
- **Real sandboxing** — 5 terminal backends: local, Docker, SSH, Singularity, Modal
|
||||
- **Full web control** — Search, extract, browse, vision, image generation, TTS
|
||||
- **MCP support** — Connect to any MCP server for extended tool capabilities
|
||||
- **Research-ready** — Batch processing, trajectory export, RL training integration
|
||||
8
website/docs/reference/_category_.json
Normal file
8
website/docs/reference/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Reference",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Complete reference for CLI commands, environment variables, and configuration."
|
||||
}
|
||||
}
|
||||
175
website/docs/reference/cli-commands.md
Normal file
175
website/docs/reference/cli-commands.md
Normal file
@@ -0,0 +1,175 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: "CLI Commands Reference"
|
||||
description: "Comprehensive reference for all hermes CLI commands and slash commands"
|
||||
---
|
||||
|
||||
# CLI Commands Reference
|
||||
|
||||
## Terminal Commands
|
||||
|
||||
These are commands you run from your shell.
|
||||
|
||||
### Core Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes` | Start interactive chat (default) |
|
||||
| `hermes chat -q "Hello"` | Single query mode (non-interactive) |
|
||||
| `hermes --continue` / `-c` | Resume the most recent session |
|
||||
| `hermes --resume <id>` / `-r <id>` | Resume a specific session |
|
||||
| `hermes --model <name>` | Use a specific model |
|
||||
| `hermes --provider <name>` | Force a provider (`nous`, `openrouter`) |
|
||||
| `hermes --toolsets "web,terminal"` | Use specific toolsets |
|
||||
| `hermes --verbose` | Enable verbose/debug output |
|
||||
|
||||
### Provider & Model Management
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes model` | Switch provider and model interactively |
|
||||
| `hermes logout` | Clear stored OAuth credentials |
|
||||
|
||||
### Configuration
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes setup` | Full setup wizard (provider, terminal, messaging) |
|
||||
| `hermes config` | View current configuration |
|
||||
| `hermes config edit` | Open config.yaml in your editor |
|
||||
| `hermes config set KEY VAL` | Set a specific value |
|
||||
| `hermes config check` | Check for missing config (useful after updates) |
|
||||
| `hermes config migrate` | Interactively add missing options |
|
||||
| `hermes status` | Show configuration status (including auth) |
|
||||
| `hermes doctor` | Diagnose issues |
|
||||
|
||||
### Maintenance
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes update` | Update to latest version |
|
||||
| `hermes uninstall` | Uninstall (can keep configs for later reinstall) |
|
||||
| `hermes version` | Show version info |
|
||||
|
||||
### Gateway (Messaging + Cron)
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes gateway` | Run gateway in foreground |
|
||||
| `hermes gateway setup` | Configure messaging platforms interactively |
|
||||
| `hermes gateway install` | Install as system service (Linux/macOS) |
|
||||
| `hermes gateway start` | Start the service |
|
||||
| `hermes gateway stop` | Stop the service |
|
||||
| `hermes gateway restart` | Restart the service |
|
||||
| `hermes gateway status` | Check service status |
|
||||
| `hermes whatsapp` | Pair WhatsApp via QR code |
|
||||
|
||||
### Skills
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes skills search <query>` | Search skill registries |
|
||||
| `hermes skills install <identifier>` | Install a skill (with security scan) |
|
||||
| `hermes skills inspect <identifier>` | Preview before installing |
|
||||
| `hermes skills list` | List installed skills |
|
||||
| `hermes skills list --source hub` | List hub-installed skills only |
|
||||
| `hermes skills audit` | Re-scan all hub skills |
|
||||
| `hermes skills uninstall <name>` | Remove a hub skill |
|
||||
| `hermes skills publish <path> --to github --repo owner/repo` | Publish a skill |
|
||||
| `hermes skills snapshot export <file>` | Export skill config |
|
||||
| `hermes skills snapshot import <file>` | Import from snapshot |
|
||||
| `hermes skills tap add <repo>` | Add a custom source |
|
||||
| `hermes skills tap remove <repo>` | Remove a source |
|
||||
| `hermes skills tap list` | List custom sources |
|
||||
|
||||
### Cron & Pairing
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes cron list` | View scheduled jobs |
|
||||
| `hermes cron status` | Check if cron scheduler is running |
|
||||
| `hermes pairing list` | View pending + approved users |
|
||||
| `hermes pairing approve <platform> <code>` | Approve a pairing code |
|
||||
| `hermes pairing revoke <platform> <user_id>` | Remove user access |
|
||||
|
||||
### Sessions
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `hermes sessions list` | Browse past sessions |
|
||||
|
||||
---
|
||||
|
||||
## Slash Commands (Inside Chat)
|
||||
|
||||
Type `/` in the interactive CLI to see an autocomplete dropdown.
|
||||
|
||||
### Navigation & Control
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/help` | Show available commands |
|
||||
| `/quit` | Exit the CLI (aliases: `/exit`, `/q`) |
|
||||
| `/clear` | Clear screen and reset conversation |
|
||||
| `/new` | Start a new conversation |
|
||||
| `/reset` | Reset conversation only (keep screen) |
|
||||
|
||||
### Tools & Configuration
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/tools` | List all available tools |
|
||||
| `/toolsets` | List available toolsets |
|
||||
| `/model [name]` | Show or change the current model |
|
||||
| `/config` | Show current configuration |
|
||||
| `/prompt [text]` | View/set custom system prompt |
|
||||
| `/personality [name]` | Set a predefined personality |
|
||||
|
||||
### Conversation
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/history` | Show conversation history |
|
||||
| `/retry` | Retry the last message |
|
||||
| `/undo` | Remove the last user/assistant exchange |
|
||||
| `/save` | Save the current conversation |
|
||||
| `/compress` | Manually compress conversation context |
|
||||
| `/usage` | Show token usage for this session |
|
||||
|
||||
### Skills & Scheduling
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/cron` | Manage scheduled tasks |
|
||||
| `/skills` | Search, install, inspect, or manage skills |
|
||||
| `/platforms` | Show gateway/messaging platform status |
|
||||
| `/verbose` | Cycle tool progress: off → new → all → verbose |
|
||||
| `/<skill-name>` | Invoke any installed skill |
|
||||
|
||||
### Gateway-Only Commands
|
||||
|
||||
These work in messaging platforms (Telegram, Discord, Slack, WhatsApp) but not the interactive CLI:
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/stop` | Stop the running agent (no follow-up message) |
|
||||
| `/sethome` | Set this chat as the home channel |
|
||||
| `/status` | Show session info |
|
||||
| `/reload-mcp` | Reload MCP servers from config |
|
||||
| `/update` | Update Hermes Agent to the latest version |
|
||||
|
||||
---
|
||||
|
||||
## Keybindings
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Enter` | Send message |
|
||||
| `Alt+Enter` / `Ctrl+J` | New line (multi-line input) |
|
||||
| `Ctrl+C` | Interrupt agent (double-press to force exit) |
|
||||
| `Ctrl+D` | Exit |
|
||||
| `Tab` | Autocomplete slash commands |
|
||||
|
||||
:::tip
|
||||
Commands are case-insensitive — `/HELP` works the same as `/help`.
|
||||
:::
|
||||
138
website/docs/reference/environment-variables.md
Normal file
138
website/docs/reference/environment-variables.md
Normal file
@@ -0,0 +1,138 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: "Environment Variables"
|
||||
description: "Complete reference of all environment variables used by Hermes Agent"
|
||||
---
|
||||
|
||||
# Environment Variables Reference
|
||||
|
||||
All variables go in `~/.hermes/.env`. You can also set them with `hermes config set VAR value`.
|
||||
|
||||
## LLM Providers
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `OPENROUTER_API_KEY` | OpenRouter API key (recommended for flexibility) |
|
||||
| `OPENAI_API_KEY` | API key for custom OpenAI-compatible endpoints (used with `OPENAI_BASE_URL`) |
|
||||
| `OPENAI_BASE_URL` | Base URL for custom endpoint (VLLM, SGLang, etc.) |
|
||||
| `LLM_MODEL` | Default model name (fallback when not set in config.yaml) |
|
||||
| `VOICE_TOOLS_OPENAI_KEY` | OpenAI key for TTS and voice transcription (separate from custom endpoint) |
|
||||
| `HERMES_HOME` | Override Hermes config directory (default: `~/.hermes`) |
|
||||
|
||||
## Provider Auth (OAuth)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `HERMES_INFERENCE_PROVIDER` | Override provider selection: `auto`, `openrouter`, `nous` (default: `auto`) |
|
||||
| `HERMES_PORTAL_BASE_URL` | Override Nous Portal URL (for development/testing) |
|
||||
| `NOUS_INFERENCE_BASE_URL` | Override Nous inference API URL |
|
||||
| `HERMES_NOUS_MIN_KEY_TTL_SECONDS` | Min agent key TTL before re-mint (default: 1800 = 30min) |
|
||||
| `HERMES_DUMP_REQUESTS` | Dump API request payloads to log files (`true`/`false`) |
|
||||
|
||||
## Tool APIs
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `FIRECRAWL_API_KEY` | Web scraping ([firecrawl.dev](https://firecrawl.dev/)) |
|
||||
| `BROWSERBASE_API_KEY` | Browser automation ([browserbase.com](https://browserbase.com/)) |
|
||||
| `BROWSERBASE_PROJECT_ID` | Browserbase project ID |
|
||||
| `FAL_KEY` | Image generation ([fal.ai](https://fal.ai/)) |
|
||||
| `ELEVENLABS_API_KEY` | Premium TTS voices ([elevenlabs.io](https://elevenlabs.io/)) |
|
||||
| `HONCHO_API_KEY` | Cross-session user modeling ([honcho.dev](https://honcho.dev/)) |
|
||||
| `TINKER_API_KEY` | RL training ([tinker-console.thinkingmachines.ai](https://tinker-console.thinkingmachines.ai/)) |
|
||||
| `WANDB_API_KEY` | RL training metrics ([wandb.ai](https://wandb.ai/)) |
|
||||
|
||||
## Terminal Backend
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `TERMINAL_ENV` | Backend: `local`, `docker`, `ssh`, `singularity`, `modal` |
|
||||
| `TERMINAL_DOCKER_IMAGE` | Docker image (default: `python:3.11-slim`) |
|
||||
| `TERMINAL_SINGULARITY_IMAGE` | Singularity image or `.sif` path |
|
||||
| `TERMINAL_TIMEOUT` | Command timeout in seconds |
|
||||
| `TERMINAL_CWD` | Working directory for all terminal sessions |
|
||||
| `SUDO_PASSWORD` | Enable sudo without interactive prompt |
|
||||
|
||||
## SSH Backend
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `TERMINAL_SSH_HOST` | Remote server hostname |
|
||||
| `TERMINAL_SSH_USER` | SSH username |
|
||||
| `TERMINAL_SSH_PORT` | SSH port (default: 22) |
|
||||
| `TERMINAL_SSH_KEY` | Path to private key |
|
||||
|
||||
## Container Resources (Docker, Singularity, Modal)
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `TERMINAL_CONTAINER_CPU` | CPU cores (default: 1) |
|
||||
| `TERMINAL_CONTAINER_MEMORY` | Memory in MB (default: 5120) |
|
||||
| `TERMINAL_CONTAINER_DISK` | Disk in MB (default: 51200) |
|
||||
| `TERMINAL_CONTAINER_PERSISTENT` | Persist container filesystem across sessions (default: `true`) |
|
||||
| `TERMINAL_SANDBOX_DIR` | Host directory for workspaces and overlays (default: `~/.hermes/sandboxes/`) |
|
||||
|
||||
## Messaging
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `TELEGRAM_BOT_TOKEN` | Telegram bot token (from @BotFather) |
|
||||
| `TELEGRAM_ALLOWED_USERS` | Comma-separated user IDs allowed to use bot |
|
||||
| `TELEGRAM_HOME_CHANNEL` | Default channel for cron delivery |
|
||||
| `TELEGRAM_HOME_CHANNEL_NAME` | Display name for home channel |
|
||||
| `DISCORD_BOT_TOKEN` | Discord bot token |
|
||||
| `DISCORD_ALLOWED_USERS` | Comma-separated user IDs allowed to use bot |
|
||||
| `DISCORD_HOME_CHANNEL` | Default channel for cron delivery |
|
||||
| `DISCORD_HOME_CHANNEL_NAME` | Display name for home channel |
|
||||
| `SLACK_BOT_TOKEN` | Slack bot token (`xoxb-...`) |
|
||||
| `SLACK_APP_TOKEN` | Slack app-level token (`xapp-...`, required for Socket Mode) |
|
||||
| `SLACK_ALLOWED_USERS` | Comma-separated Slack user IDs |
|
||||
| `SLACK_HOME_CHANNEL` | Default Slack channel for cron delivery |
|
||||
| `WHATSAPP_ENABLED` | Enable WhatsApp bridge (`true`/`false`) |
|
||||
| `WHATSAPP_MODE` | `bot` (separate number) or `self-chat` (message yourself) |
|
||||
| `WHATSAPP_ALLOWED_USERS` | Comma-separated phone numbers (with country code) |
|
||||
| `MESSAGING_CWD` | Working directory for terminal in messaging (default: `~`) |
|
||||
| `GATEWAY_ALLOW_ALL_USERS` | Allow all users without allowlist (`true`/`false`, default: `false`) |
|
||||
|
||||
## Agent Behavior
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `HERMES_MAX_ITERATIONS` | Max tool-calling iterations per conversation (default: 60) |
|
||||
| `HERMES_TOOL_PROGRESS` | Send progress messages when using tools (`true`/`false`) |
|
||||
| `HERMES_TOOL_PROGRESS_MODE` | `all` (every call, default) or `new` (only when tool changes) |
|
||||
| `HERMES_HUMAN_DELAY_MODE` | Response pacing: `off`/`natural`/`custom` |
|
||||
| `HERMES_HUMAN_DELAY_MIN_MS` | Custom delay range minimum (ms) |
|
||||
| `HERMES_HUMAN_DELAY_MAX_MS` | Custom delay range maximum (ms) |
|
||||
|
||||
## Session Settings
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `SESSION_IDLE_MINUTES` | Reset sessions after N minutes of inactivity (default: 120) |
|
||||
| `SESSION_RESET_HOUR` | Daily reset hour in 24h format (default: 4 = 4am) |
|
||||
|
||||
## Context Compression
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `CONTEXT_COMPRESSION_ENABLED` | Enable auto-compression (default: `true`) |
|
||||
| `CONTEXT_COMPRESSION_THRESHOLD` | Trigger at this % of limit (default: 0.85) |
|
||||
| `CONTEXT_COMPRESSION_MODEL` | Model for summaries |
|
||||
|
||||
## Provider Routing (config.yaml only)
|
||||
|
||||
These go in `~/.hermes/config.yaml` under the `provider_routing` section:
|
||||
|
||||
| Key | Description |
|
||||
|-----|-------------|
|
||||
| `sort` | Sort providers: `"price"` (default), `"throughput"`, or `"latency"` |
|
||||
| `only` | List of provider slugs to allow (e.g., `["anthropic", "google"]`) |
|
||||
| `ignore` | List of provider slugs to skip |
|
||||
| `order` | List of provider slugs to try in order |
|
||||
| `require_parameters` | Only use providers supporting all request params (`true`/`false`) |
|
||||
| `data_collection` | `"allow"` (default) or `"deny"` to exclude data-storing providers |
|
||||
|
||||
:::tip
|
||||
Use `hermes config set` to set environment variables — it automatically saves them to the right file (`.env` for secrets, `config.yaml` for everything else).
|
||||
:::
|
||||
8
website/docs/user-guide/_category_.json
Normal file
8
website/docs/user-guide/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "User Guide",
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Learn how to use Hermes Agent effectively."
|
||||
}
|
||||
}
|
||||
268
website/docs/user-guide/cli.md
Normal file
268
website/docs/user-guide/cli.md
Normal file
@@ -0,0 +1,268 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: "CLI Interface"
|
||||
description: "Master the Hermes Agent terminal interface — commands, keybindings, personalities, and more"
|
||||
---
|
||||
|
||||
# CLI Interface
|
||||
|
||||
Hermes Agent's CLI is a full terminal user interface (TUI) — not a web UI. It features multiline editing, slash-command autocomplete, conversation history, interrupt-and-redirect, and streaming tool output. Built for people who live in the terminal.
|
||||
|
||||
## Running the CLI
|
||||
|
||||
```bash
|
||||
# Start an interactive session (default)
|
||||
hermes
|
||||
|
||||
# Single query mode (non-interactive)
|
||||
hermes chat -q "Hello"
|
||||
|
||||
# With a specific model
|
||||
hermes --model "anthropic/claude-sonnet-4"
|
||||
|
||||
# With a specific provider
|
||||
hermes --provider nous # Use Nous Portal
|
||||
hermes --provider openrouter # Force OpenRouter
|
||||
|
||||
# With specific toolsets
|
||||
hermes --toolsets "web,terminal,skills"
|
||||
|
||||
# Resume previous sessions
|
||||
hermes --continue # Resume the most recent CLI session (-c)
|
||||
hermes --resume <session_id> # Resume a specific session by ID (-r)
|
||||
|
||||
# Verbose mode (debug output)
|
||||
hermes --verbose
|
||||
```
|
||||
|
||||
## Interface Layout
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ HERMES-AGENT ASCII Logo │
|
||||
│ ┌─────────────┐ ┌────────────────────────────┐ │
|
||||
│ │ Caduceus │ │ Model: claude-sonnet-4 │ │
|
||||
│ │ ASCII Art │ │ Terminal: local │ │
|
||||
│ │ │ │ Working Dir: /home/user │ │
|
||||
│ │ │ │ Available Tools: 19 │ │
|
||||
│ │ │ │ Available Skills: 12 │ │
|
||||
│ └─────────────┘ └────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ Conversation output scrolls here... │
|
||||
│ │
|
||||
│ (◕‿◕✿) 🧠 pondering... (2.3s) │
|
||||
│ ✧٩(ˊᗜˋ*)و✧ got it! (2.3s) │
|
||||
│ │
|
||||
│ Assistant: Hello! How can I help you today? │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ ❯ [Fixed input area at bottom] │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
The welcome banner shows your model, terminal backend, working directory, available tools, and installed skills at a glance.
|
||||
|
||||
## Keybindings
|
||||
|
||||
| Key | Action |
|
||||
|-----|--------|
|
||||
| `Enter` | Send message |
|
||||
| `Alt+Enter` or `Ctrl+J` | New line (multi-line input) |
|
||||
| `Ctrl+C` | Interrupt agent (double-press within 2s to force exit) |
|
||||
| `Ctrl+D` | Exit |
|
||||
| `Tab` | Autocomplete slash commands |
|
||||
|
||||
## Slash Commands
|
||||
|
||||
Type `/` to see an autocomplete dropdown of all available commands.
|
||||
|
||||
### Navigation & Control
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/help` | Show available commands |
|
||||
| `/quit` | Exit the CLI (also: `/exit`, `/q`) |
|
||||
| `/clear` | Clear screen and reset conversation |
|
||||
| `/new` | Start a new conversation |
|
||||
| `/reset` | Reset conversation only (keep screen) |
|
||||
|
||||
### Tools & Configuration
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/tools` | List all available tools grouped by toolset |
|
||||
| `/toolsets` | List available toolsets with descriptions |
|
||||
| `/model [name]` | Show or change the current model |
|
||||
| `/config` | Show current configuration |
|
||||
| `/prompt [text]` | View/set/clear custom system prompt |
|
||||
| `/personality [name]` | Set a predefined personality |
|
||||
|
||||
### Conversation Management
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/history` | Show conversation history |
|
||||
| `/retry` | Retry the last message |
|
||||
| `/undo` | Remove the last user/assistant exchange |
|
||||
| `/save` | Save the current conversation |
|
||||
| `/compress` | Manually compress conversation context |
|
||||
| `/usage` | Show token usage for this session |
|
||||
|
||||
### Skills & Scheduling
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/cron` | Manage scheduled tasks |
|
||||
| `/skills` | Search, install, inspect, or manage skills |
|
||||
| `/platforms` | Show gateway/messaging platform status |
|
||||
| `/verbose` | Cycle tool progress display: off → new → all → verbose |
|
||||
| `/<skill-name>` | Invoke any installed skill (e.g., `/axolotl`, `/gif-search`) |
|
||||
|
||||
:::tip
|
||||
Commands are case-insensitive — `/HELP` works the same as `/help`. Most commands work mid-conversation.
|
||||
:::
|
||||
|
||||
## Skill Slash Commands
|
||||
|
||||
Every installed skill in `~/.hermes/skills/` is automatically registered as a slash command. The skill name becomes the command:
|
||||
|
||||
```
|
||||
/gif-search funny cats
|
||||
/axolotl help me fine-tune Llama 3 on my dataset
|
||||
/github-pr-workflow create a PR for the auth refactor
|
||||
|
||||
# Just the skill name loads it and lets the agent ask what you need:
|
||||
/excalidraw
|
||||
```
|
||||
|
||||
## Personalities
|
||||
|
||||
Set a predefined personality to change the agent's tone:
|
||||
|
||||
```
|
||||
/personality pirate
|
||||
/personality kawaii
|
||||
/personality concise
|
||||
```
|
||||
|
||||
Built-in personalities include: `helpful`, `concise`, `technical`, `creative`, `teacher`, `kawaii`, `catgirl`, `pirate`, `shakespeare`, `surfer`, `noir`, `uwu`, `philosopher`, `hype`.
|
||||
|
||||
You can also define custom personalities in `~/.hermes/config.yaml`:
|
||||
|
||||
```yaml
|
||||
agent:
|
||||
personalities:
|
||||
helpful: "You are a helpful, friendly AI assistant."
|
||||
kawaii: "You are a kawaii assistant! Use cute expressions..."
|
||||
pirate: "Arrr! Ye be talkin' to Captain Hermes..."
|
||||
# Add your own!
|
||||
```
|
||||
|
||||
## Multi-line Input
|
||||
|
||||
There are two ways to enter multi-line messages:
|
||||
|
||||
1. **`Alt+Enter` or `Ctrl+J`** — inserts a new line
|
||||
2. **Backslash continuation** — end a line with `\` to continue:
|
||||
|
||||
```
|
||||
❯ Write a function that:\
|
||||
1. Takes a list of numbers\
|
||||
2. Returns the sum
|
||||
```
|
||||
|
||||
:::info
|
||||
Pasting 5+ lines of text automatically saves to `~/.hermes/pastes/` and collapses to a reference, keeping your prompt clean.
|
||||
:::
|
||||
|
||||
## Interrupting the Agent
|
||||
|
||||
You can interrupt the agent at any point:
|
||||
|
||||
- **Type a new message + Enter** while the agent is working — it interrupts and processes your new instructions
|
||||
- **`Ctrl+C`** — interrupt the current operation (press twice within 2s to force exit)
|
||||
- In-progress terminal commands are killed immediately (SIGTERM, then SIGKILL after 1s)
|
||||
- Multiple messages typed during interrupt are combined into one prompt
|
||||
|
||||
## Tool Progress Display
|
||||
|
||||
The CLI shows animated feedback as the agent works:
|
||||
|
||||
**Thinking animation** (during API calls):
|
||||
```
|
||||
◜ (。•́︿•̀。) pondering... (1.2s)
|
||||
◠ (⊙_⊙) contemplating... (2.4s)
|
||||
✧٩(ˊᗜˋ*)و✧ got it! (3.1s)
|
||||
```
|
||||
|
||||
**Tool execution feed:**
|
||||
```
|
||||
┊ 💻 terminal `ls -la` (0.3s)
|
||||
┊ 🔍 web_search (1.2s)
|
||||
┊ 📄 web_extract (2.1s)
|
||||
```
|
||||
|
||||
Cycle through display modes with `/verbose`: `off → new → all → verbose`.
|
||||
|
||||
## Session Management
|
||||
|
||||
### Resuming Sessions
|
||||
|
||||
When you exit a CLI session, a resume command is printed:
|
||||
|
||||
```
|
||||
Resume this session with:
|
||||
hermes --resume 20260225_143052_a1b2c3
|
||||
|
||||
Session: 20260225_143052_a1b2c3
|
||||
Duration: 12m 34s
|
||||
Messages: 28 (5 user, 18 tool calls)
|
||||
```
|
||||
|
||||
Resume options:
|
||||
|
||||
```bash
|
||||
hermes --continue # Resume the most recent CLI session
|
||||
hermes -c # Short form
|
||||
hermes --resume 20260225_143052_a1b2c3 # Resume a specific session by ID
|
||||
hermes -r 20260225_143052_a1b2c3 # Short form
|
||||
```
|
||||
|
||||
Resuming restores the full conversation history from SQLite. The agent sees all previous messages, tool calls, and responses — just as if you never left.
|
||||
|
||||
Use `hermes sessions list` to browse past sessions.
|
||||
|
||||
### Session Logging
|
||||
|
||||
Sessions are automatically logged to `~/.hermes/sessions/`:
|
||||
|
||||
```
|
||||
sessions/
|
||||
├── session_20260201_143052_a1b2c3.json
|
||||
├── session_20260201_150217_d4e5f6.json
|
||||
└── ...
|
||||
```
|
||||
|
||||
### Context Compression
|
||||
|
||||
Long conversations are automatically summarized when approaching context limits:
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
compression:
|
||||
enabled: true
|
||||
threshold: 0.85 # Compress at 85% of context limit
|
||||
```
|
||||
|
||||
When compression triggers, middle turns are summarized while the first 3 and last 4 turns are always preserved.
|
||||
|
||||
## Quiet Mode
|
||||
|
||||
By default, the CLI runs in quiet mode which:
|
||||
- Suppresses verbose logging from tools
|
||||
- Enables kawaii-style animated feedback
|
||||
- Keeps output clean and user-friendly
|
||||
|
||||
For debug output:
|
||||
```bash
|
||||
hermes --verbose
|
||||
```
|
||||
204
website/docs/user-guide/configuration.md
Normal file
204
website/docs/user-guide/configuration.md
Normal file
@@ -0,0 +1,204 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: "Configuration"
|
||||
description: "Configure Hermes Agent — config.yaml, providers, models, API keys, and more"
|
||||
---
|
||||
|
||||
# Configuration
|
||||
|
||||
All settings are stored in the `~/.hermes/` directory for easy access.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```text
|
||||
~/.hermes/
|
||||
├── config.yaml # Settings (model, terminal, TTS, compression, etc.)
|
||||
├── .env # API keys and secrets
|
||||
├── auth.json # OAuth provider credentials (Nous Portal, etc.)
|
||||
├── SOUL.md # Optional: global persona (agent embodies this personality)
|
||||
├── memories/ # Persistent memory (MEMORY.md, USER.md)
|
||||
├── skills/ # Agent-created skills (managed via skill_manage tool)
|
||||
├── cron/ # Scheduled jobs
|
||||
├── sessions/ # Gateway sessions
|
||||
└── logs/ # Logs (errors.log, gateway.log — secrets auto-redacted)
|
||||
```
|
||||
|
||||
## Managing Configuration
|
||||
|
||||
```bash
|
||||
hermes config # View current configuration
|
||||
hermes config edit # Open config.yaml in your editor
|
||||
hermes config set KEY VAL # Set a specific value
|
||||
hermes config check # Check for missing options (after updates)
|
||||
hermes config migrate # Interactively add missing options
|
||||
|
||||
# Examples:
|
||||
hermes config set model anthropic/claude-opus-4
|
||||
hermes config set terminal.backend docker
|
||||
hermes config set OPENROUTER_API_KEY sk-or-... # Saves to .env
|
||||
```
|
||||
|
||||
:::tip
|
||||
The `hermes config set` command automatically routes values to the right file — API keys are saved to `.env`, everything else to `config.yaml`.
|
||||
:::
|
||||
|
||||
## Configuration Precedence
|
||||
|
||||
Settings are resolved in this order (highest priority first):
|
||||
|
||||
1. **CLI arguments** — `hermes chat --max-turns 100` (per-invocation override)
|
||||
2. **`~/.hermes/config.yaml`** — the primary config file for all non-secret settings
|
||||
3. **`~/.hermes/.env`** — fallback for env vars; **required** for secrets (API keys, tokens, passwords)
|
||||
4. **Built-in defaults** — hardcoded safe defaults when nothing else is set
|
||||
|
||||
:::info Rule of Thumb
|
||||
Secrets (API keys, bot tokens, passwords) go in `.env`. Everything else (model, terminal backend, compression settings, memory limits, toolsets) goes in `config.yaml`. When both are set, `config.yaml` wins for non-secret settings.
|
||||
:::
|
||||
|
||||
## Inference Providers
|
||||
|
||||
You need at least one way to connect to an LLM. Use `hermes model` to switch providers and models interactively, or configure directly:
|
||||
|
||||
| Provider | Setup |
|
||||
|----------|-------|
|
||||
| **Nous Portal** | `hermes model` (OAuth, subscription-based) |
|
||||
| **OpenAI Codex** | `hermes model` (ChatGPT OAuth, uses Codex models) |
|
||||
| **OpenRouter** | `OPENROUTER_API_KEY` in `~/.hermes/.env` |
|
||||
| **Custom Endpoint** | `OPENAI_BASE_URL` + `OPENAI_API_KEY` in `~/.hermes/.env` |
|
||||
|
||||
:::info Codex Note
|
||||
The OpenAI Codex provider authenticates via device code (open a URL, enter a code). Credentials are stored at `~/.codex/auth.json` and auto-refresh. No Codex CLI installation required.
|
||||
:::
|
||||
|
||||
:::warning
|
||||
Even when using Nous Portal, Codex, or a custom endpoint, some tools (vision, web summarization, MoA) use OpenRouter independently. An `OPENROUTER_API_KEY` enables these tools.
|
||||
:::
|
||||
|
||||
## Optional API Keys
|
||||
|
||||
| Feature | Provider | Env Variable |
|
||||
|---------|----------|--------------|
|
||||
| Web scraping | [Firecrawl](https://firecrawl.dev/) | `FIRECRAWL_API_KEY` |
|
||||
| Browser automation | [Browserbase](https://browserbase.com/) | `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID` |
|
||||
| Image generation | [FAL](https://fal.ai/) | `FAL_KEY` |
|
||||
| Premium TTS voices | [ElevenLabs](https://elevenlabs.io/) | `ELEVENLABS_API_KEY` |
|
||||
| OpenAI TTS + voice transcription | [OpenAI](https://platform.openai.com/api-keys) | `VOICE_TOOLS_OPENAI_KEY` |
|
||||
| RL Training | [Tinker](https://tinker-console.thinkingmachines.ai/) + [WandB](https://wandb.ai/) | `TINKER_API_KEY`, `WANDB_API_KEY` |
|
||||
| Cross-session user modeling | [Honcho](https://honcho.dev/) | `HONCHO_API_KEY` |
|
||||
|
||||
## OpenRouter Provider Routing
|
||||
|
||||
When using OpenRouter, you can control how requests are routed across providers. Add a `provider_routing` section to `~/.hermes/config.yaml`:
|
||||
|
||||
```yaml
|
||||
provider_routing:
|
||||
sort: "throughput" # "price" (default), "throughput", or "latency"
|
||||
# only: ["anthropic"] # Only use these providers
|
||||
# ignore: ["deepinfra"] # Skip these providers
|
||||
# order: ["anthropic", "google"] # Try providers in this order
|
||||
# require_parameters: true # Only use providers that support all request params
|
||||
# data_collection: "deny" # Exclude providers that may store/train on data
|
||||
```
|
||||
|
||||
**Shortcuts:** Append `:nitro` to any model name for throughput sorting (e.g., `anthropic/claude-sonnet-4:nitro`), or `:floor` for price sorting.
|
||||
|
||||
## Terminal Backend Configuration
|
||||
|
||||
Configure which environment the agent uses for terminal commands:
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
backend: local # or: docker, ssh, singularity, modal
|
||||
cwd: "." # Working directory ("." = current dir)
|
||||
timeout: 180 # Command timeout in seconds
|
||||
```
|
||||
|
||||
See [Code Execution](features/code-execution.md) and the [Terminal section of the README](features/tools.md) for details on each backend.
|
||||
|
||||
## Memory Configuration
|
||||
|
||||
```yaml
|
||||
memory:
|
||||
memory_enabled: true
|
||||
user_profile_enabled: true
|
||||
memory_char_limit: 2200 # ~800 tokens
|
||||
user_char_limit: 1375 # ~500 tokens
|
||||
```
|
||||
|
||||
## Context Compression
|
||||
|
||||
```yaml
|
||||
compression:
|
||||
enabled: true
|
||||
threshold: 0.85 # Compress at 85% of context limit
|
||||
```
|
||||
|
||||
## Reasoning Effort
|
||||
|
||||
Control how much "thinking" the model does before responding:
|
||||
|
||||
```yaml
|
||||
agent:
|
||||
reasoning_effort: "xhigh" # xhigh (max), high, medium, low, minimal, none
|
||||
```
|
||||
|
||||
Higher reasoning effort gives better results on complex tasks at the cost of more tokens and latency.
|
||||
|
||||
## TTS Configuration
|
||||
|
||||
```yaml
|
||||
tts:
|
||||
provider: "edge" # "edge" | "elevenlabs" | "openai"
|
||||
edge:
|
||||
voice: "en-US-AriaNeural" # 322 voices, 74 languages
|
||||
elevenlabs:
|
||||
voice_id: "pNInz6obpgDQGcFmaJgB"
|
||||
model_id: "eleven_multilingual_v2"
|
||||
openai:
|
||||
model: "gpt-4o-mini-tts"
|
||||
voice: "alloy" # alloy, echo, fable, onyx, nova, shimmer
|
||||
```
|
||||
|
||||
## Display Settings
|
||||
|
||||
```yaml
|
||||
display:
|
||||
tool_progress: all # off | new | all | verbose
|
||||
```
|
||||
|
||||
| Mode | What you see |
|
||||
|------|-------------|
|
||||
| `off` | Silent — just the final response |
|
||||
| `new` | Tool indicator only when the tool changes |
|
||||
| `all` | Every tool call with a short preview (default) |
|
||||
| `verbose` | Full args, results, and debug logs |
|
||||
|
||||
## Context Files (SOUL.md, AGENTS.md)
|
||||
|
||||
Drop these files in your project directory and the agent automatically picks them up:
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `AGENTS.md` | Project-specific instructions, coding conventions |
|
||||
| `SOUL.md` | Persona definition — the agent embodies this personality |
|
||||
| `.cursorrules` | Cursor IDE rules (also detected) |
|
||||
| `.cursor/rules/*.mdc` | Cursor rule files (also detected) |
|
||||
|
||||
- **AGENTS.md** is hierarchical: if subdirectories also have AGENTS.md, all are combined.
|
||||
- **SOUL.md** checks cwd first, then `~/.hermes/SOUL.md` as a global fallback.
|
||||
- All context files are capped at 20,000 characters with smart truncation.
|
||||
|
||||
## Working Directory
|
||||
|
||||
| Context | Default |
|
||||
|---------|---------|
|
||||
| **CLI (`hermes`)** | Current directory where you run the command |
|
||||
| **Messaging gateway** | Home directory `~` (override with `MESSAGING_CWD`) |
|
||||
| **Docker / Singularity / Modal / SSH** | User's home directory inside the container or remote machine |
|
||||
|
||||
Override the working directory:
|
||||
```bash
|
||||
# In ~/.hermes/.env or ~/.hermes/config.yaml:
|
||||
MESSAGING_CWD=/home/myuser/projects # Gateway sessions
|
||||
TERMINAL_CWD=/workspace # All terminal sessions
|
||||
```
|
||||
8
website/docs/user-guide/features/_category_.json
Normal file
8
website/docs/user-guide/features/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Features",
|
||||
"position": 4,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"description": "Explore the powerful features of Hermes Agent."
|
||||
}
|
||||
}
|
||||
51
website/docs/user-guide/features/code-execution.md
Normal file
51
website/docs/user-guide/features/code-execution.md
Normal file
@@ -0,0 +1,51 @@
|
||||
---
|
||||
sidebar_position: 8
|
||||
title: "Code Execution"
|
||||
description: "Sandboxed Python execution with RPC tool access — collapse multi-step workflows into a single turn"
|
||||
---
|
||||
|
||||
# Code Execution (Programmatic Tool Calling)
|
||||
|
||||
The `execute_code` tool lets the agent write Python scripts that call Hermes tools programmatically, collapsing multi-step workflows into a single LLM turn. The script runs in a sandboxed child process on the agent host, communicating via Unix domain socket RPC.
|
||||
|
||||
## How It Works
|
||||
|
||||
```python
|
||||
# The agent can write scripts like:
|
||||
from hermes_tools import web_search, web_extract
|
||||
|
||||
results = web_search("Python 3.13 features", limit=5)
|
||||
for r in results["data"]["web"]:
|
||||
content = web_extract([r["url"]])
|
||||
# ... filter and process ...
|
||||
print(summary)
|
||||
```
|
||||
|
||||
**Available tools in sandbox:** `web_search`, `web_extract`, `read_file`, `write_file`, `search`, `patch`, `terminal` (foreground only).
|
||||
|
||||
## When the Agent Uses This
|
||||
|
||||
The agent uses `execute_code` when there are:
|
||||
|
||||
- **3+ tool calls** with processing logic between them
|
||||
- Bulk data filtering or conditional branching
|
||||
- Loops over results
|
||||
|
||||
The key benefit: intermediate tool results never enter the context window — only the final `print()` output comes back, dramatically reducing token usage.
|
||||
|
||||
## Security
|
||||
|
||||
:::danger Security Model
|
||||
The child process runs with a **minimal environment**. API keys, tokens, and credentials are stripped entirely. The script accesses tools exclusively via the RPC channel — it cannot read secrets from environment variables.
|
||||
:::
|
||||
|
||||
Only safe system variables (`PATH`, `HOME`, `LANG`, etc.) are passed through.
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
code_execution:
|
||||
timeout: 300 # Max seconds per script (default: 300)
|
||||
max_tool_calls: 50 # Max tool calls per execution (default: 50)
|
||||
```
|
||||
87
website/docs/user-guide/features/cron.md
Normal file
87
website/docs/user-guide/features/cron.md
Normal file
@@ -0,0 +1,87 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
title: "Scheduled Tasks (Cron)"
|
||||
description: "Schedule automated tasks with natural language — cron jobs, delivery options, and the gateway scheduler"
|
||||
---
|
||||
|
||||
# Scheduled Tasks (Cron)
|
||||
|
||||
Schedule tasks to run automatically with natural language or cron expressions. The agent can self-schedule using the `schedule_cronjob` tool from any platform.
|
||||
|
||||
## Creating Scheduled Tasks
|
||||
|
||||
### In the CLI
|
||||
|
||||
Use the `/cron` slash command:
|
||||
|
||||
```
|
||||
/cron add 30m "Remind me to check the build"
|
||||
/cron add "every 2h" "Check server status"
|
||||
/cron add "0 9 * * *" "Morning briefing"
|
||||
/cron list
|
||||
/cron remove <job_id>
|
||||
```
|
||||
|
||||
### Through Natural Conversation
|
||||
|
||||
Simply ask the agent on any platform:
|
||||
|
||||
```
|
||||
Every morning at 9am, check Hacker News for AI news and send me a summary on Telegram.
|
||||
```
|
||||
|
||||
The agent will use the `schedule_cronjob` tool to set it up.
|
||||
|
||||
## How It Works
|
||||
|
||||
**Cron execution is handled by the gateway daemon.** The gateway ticks the scheduler every 60 seconds, running any due jobs in isolated agent sessions:
|
||||
|
||||
```bash
|
||||
hermes gateway install # Install as system service (recommended)
|
||||
hermes gateway # Or run in foreground
|
||||
|
||||
hermes cron list # View scheduled jobs
|
||||
hermes cron status # Check if gateway is running
|
||||
```
|
||||
|
||||
:::info
|
||||
Even if no messaging platforms are configured, the gateway stays running for cron. A file lock prevents duplicate execution if multiple processes overlap.
|
||||
:::
|
||||
|
||||
## Delivery Options
|
||||
|
||||
When scheduling jobs, you specify where the output goes:
|
||||
|
||||
| Option | Description |
|
||||
|--------|-------------|
|
||||
| `"origin"` | Back to where the job was created |
|
||||
| `"local"` | Save to local files only |
|
||||
| `"telegram"` | Telegram home channel |
|
||||
| `"discord"` | Discord home channel |
|
||||
| `"telegram:123456"` | Specific Telegram chat |
|
||||
|
||||
The agent knows your connected platforms and home channels — it'll choose sensible defaults.
|
||||
|
||||
## Schedule Formats
|
||||
|
||||
- **Relative:** `30m`, `2h`, `1d`
|
||||
- **Human-readable:** `"every 2 hours"`, `"daily at 9am"`
|
||||
- **Cron expressions:** `"0 9 * * *"` (standard 5-field cron syntax)
|
||||
|
||||
## Managing Jobs
|
||||
|
||||
```bash
|
||||
# CLI commands
|
||||
hermes cron list # View all scheduled jobs
|
||||
hermes cron status # Check if the scheduler is running
|
||||
|
||||
# Slash commands (inside chat)
|
||||
/cron list
|
||||
/cron remove <job_id>
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
Scheduled task prompts are scanned for instruction-override patterns (prompt injection). Jobs with suspicious content are blocked.
|
||||
:::
|
||||
60
website/docs/user-guide/features/delegation.md
Normal file
60
website/docs/user-guide/features/delegation.md
Normal file
@@ -0,0 +1,60 @@
|
||||
---
|
||||
sidebar_position: 7
|
||||
title: "Subagent Delegation"
|
||||
description: "Spawn isolated child agents for parallel workstreams with delegate_task"
|
||||
---
|
||||
|
||||
# Subagent Delegation
|
||||
|
||||
The `delegate_task` tool spawns child AIAgent instances with isolated context, restricted toolsets, and their own terminal sessions. Each child gets a fresh conversation and works independently — only its final summary enters the parent's context.
|
||||
|
||||
## Single Task
|
||||
|
||||
```python
|
||||
delegate_task(
|
||||
goal="Debug why tests fail",
|
||||
context="Error: assertion in test_foo.py line 42",
|
||||
toolsets=["terminal", "file"]
|
||||
)
|
||||
```
|
||||
|
||||
## Parallel Batch
|
||||
|
||||
Up to 3 concurrent subagents:
|
||||
|
||||
```python
|
||||
delegate_task(tasks=[
|
||||
{"goal": "Research topic A", "toolsets": ["web"]},
|
||||
{"goal": "Research topic B", "toolsets": ["web"]},
|
||||
{"goal": "Fix the build", "toolsets": ["terminal", "file"]}
|
||||
])
|
||||
```
|
||||
|
||||
## Key Properties
|
||||
|
||||
- Each subagent gets its **own terminal session** (separate from the parent)
|
||||
- **Depth limit of 2** — no grandchildren
|
||||
- Subagents **cannot** call: `delegate_task`, `clarify`, `memory`, `send_message`, `execute_code`
|
||||
- **Interrupt propagation** — interrupting the parent interrupts all active children
|
||||
- Only the final summary enters the parent's context, keeping token usage efficient
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
delegation:
|
||||
max_iterations: 50 # Max turns per child (default: 50)
|
||||
default_toolsets: ["terminal", "file", "web"] # Default toolsets
|
||||
```
|
||||
|
||||
## When to Use Delegation
|
||||
|
||||
Delegation is most useful when:
|
||||
|
||||
- You have **independent workstreams** that can run in parallel
|
||||
- A subtask needs a **clean context** (e.g., debugging a long error trace without polluting the main conversation)
|
||||
- You want to **fan out** research across multiple topics and collect summaries
|
||||
|
||||
:::tip
|
||||
The agent handles delegation automatically based on the task complexity. You don't need to explicitly ask it to delegate — it will do so when it makes sense.
|
||||
:::
|
||||
182
website/docs/user-guide/features/hooks.md
Normal file
182
website/docs/user-guide/features/hooks.md
Normal file
@@ -0,0 +1,182 @@
|
||||
---
|
||||
sidebar_position: 6
|
||||
title: "Event Hooks"
|
||||
description: "Run custom code at key lifecycle points — log activity, send alerts, post to webhooks"
|
||||
---
|
||||
|
||||
# Event Hooks
|
||||
|
||||
The hooks system lets you run custom code at key points in the agent lifecycle — session creation, slash commands, each tool-calling step, and more. Hooks fire automatically during gateway operation without blocking the main agent pipeline.
|
||||
|
||||
## Creating a Hook
|
||||
|
||||
Each hook is a directory under `~/.hermes/hooks/` containing two files:
|
||||
|
||||
```
|
||||
~/.hermes/hooks/
|
||||
└── my-hook/
|
||||
├── HOOK.yaml # Declares which events to listen for
|
||||
└── handler.py # Python handler function
|
||||
```
|
||||
|
||||
### HOOK.yaml
|
||||
|
||||
```yaml
|
||||
name: my-hook
|
||||
description: Log all agent activity to a file
|
||||
events:
|
||||
- agent:start
|
||||
- agent:end
|
||||
- agent:step
|
||||
```
|
||||
|
||||
The `events` list determines which events trigger your handler. You can subscribe to any combination of events, including wildcards like `command:*`.
|
||||
|
||||
### handler.py
|
||||
|
||||
```python
|
||||
import json
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
LOG_FILE = Path.home() / ".hermes" / "hooks" / "my-hook" / "activity.log"
|
||||
|
||||
async def handle(event_type: str, context: dict):
|
||||
"""Called for each subscribed event. Must be named 'handle'."""
|
||||
entry = {
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"event": event_type,
|
||||
**context,
|
||||
}
|
||||
with open(LOG_FILE, "a") as f:
|
||||
f.write(json.dumps(entry) + "\n")
|
||||
```
|
||||
|
||||
**Handler rules:**
|
||||
- Must be named `handle`
|
||||
- Receives `event_type` (string) and `context` (dict)
|
||||
- Can be `async def` or regular `def` — both work
|
||||
- Errors are caught and logged, never crashing the agent
|
||||
|
||||
## Available Events
|
||||
|
||||
| Event | When it fires | Context keys |
|
||||
|-------|---------------|--------------|
|
||||
| `gateway:startup` | Gateway process starts | `platforms` (list of active platform names) |
|
||||
| `session:start` | New messaging session created | `platform`, `user_id`, `session_id`, `session_key` |
|
||||
| `session:reset` | User ran `/new` or `/reset` | `platform`, `user_id`, `session_key` |
|
||||
| `agent:start` | Agent begins processing a message | `platform`, `user_id`, `session_id`, `message` |
|
||||
| `agent:step` | Each iteration of the tool-calling loop | `platform`, `user_id`, `session_id`, `iteration`, `tool_names` |
|
||||
| `agent:end` | Agent finishes processing | `platform`, `user_id`, `session_id`, `message`, `response` |
|
||||
| `command:*` | Any slash command executed | `platform`, `user_id`, `command`, `args` |
|
||||
|
||||
### Wildcard Matching
|
||||
|
||||
Handlers registered for `command:*` fire for any `command:` event (`command:model`, `command:reset`, etc.). Monitor all slash commands with a single subscription.
|
||||
|
||||
## Examples
|
||||
|
||||
### Telegram Alert on Long Tasks
|
||||
|
||||
Send yourself a message when the agent takes more than 10 steps:
|
||||
|
||||
```yaml
|
||||
# ~/.hermes/hooks/long-task-alert/HOOK.yaml
|
||||
name: long-task-alert
|
||||
description: Alert when agent is taking many steps
|
||||
events:
|
||||
- agent:step
|
||||
```
|
||||
|
||||
```python
|
||||
# ~/.hermes/hooks/long-task-alert/handler.py
|
||||
import os
|
||||
import httpx
|
||||
|
||||
THRESHOLD = 10
|
||||
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||
CHAT_ID = os.getenv("TELEGRAM_HOME_CHANNEL")
|
||||
|
||||
async def handle(event_type: str, context: dict):
|
||||
iteration = context.get("iteration", 0)
|
||||
if iteration == THRESHOLD and BOT_TOKEN and CHAT_ID:
|
||||
tools = ", ".join(context.get("tool_names", []))
|
||||
text = f"⚠️ Agent has been running for {iteration} steps. Last tools: {tools}"
|
||||
async with httpx.AsyncClient() as client:
|
||||
await client.post(
|
||||
f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage",
|
||||
json={"chat_id": CHAT_ID, "text": text},
|
||||
)
|
||||
```
|
||||
|
||||
### Command Usage Logger
|
||||
|
||||
Track which slash commands are used:
|
||||
|
||||
```yaml
|
||||
# ~/.hermes/hooks/command-logger/HOOK.yaml
|
||||
name: command-logger
|
||||
description: Log slash command usage
|
||||
events:
|
||||
- command:*
|
||||
```
|
||||
|
||||
```python
|
||||
# ~/.hermes/hooks/command-logger/handler.py
|
||||
import json
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
LOG = Path.home() / ".hermes" / "logs" / "command_usage.jsonl"
|
||||
|
||||
def handle(event_type: str, context: dict):
|
||||
LOG.parent.mkdir(parents=True, exist_ok=True)
|
||||
entry = {
|
||||
"ts": datetime.now().isoformat(),
|
||||
"command": context.get("command"),
|
||||
"args": context.get("args"),
|
||||
"platform": context.get("platform"),
|
||||
"user": context.get("user_id"),
|
||||
}
|
||||
with open(LOG, "a") as f:
|
||||
f.write(json.dumps(entry) + "\n")
|
||||
```
|
||||
|
||||
### Session Start Webhook
|
||||
|
||||
POST to an external service on new sessions:
|
||||
|
||||
```yaml
|
||||
# ~/.hermes/hooks/session-webhook/HOOK.yaml
|
||||
name: session-webhook
|
||||
description: Notify external service on new sessions
|
||||
events:
|
||||
- session:start
|
||||
- session:reset
|
||||
```
|
||||
|
||||
```python
|
||||
# ~/.hermes/hooks/session-webhook/handler.py
|
||||
import httpx
|
||||
|
||||
WEBHOOK_URL = "https://your-service.example.com/hermes-events"
|
||||
|
||||
async def handle(event_type: str, context: dict):
|
||||
async with httpx.AsyncClient() as client:
|
||||
await client.post(WEBHOOK_URL, json={
|
||||
"event": event_type,
|
||||
**context,
|
||||
}, timeout=5)
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. On gateway startup, `HookRegistry.discover_and_load()` scans `~/.hermes/hooks/`
|
||||
2. Each subdirectory with `HOOK.yaml` + `handler.py` is loaded dynamically
|
||||
3. Handlers are registered for their declared events
|
||||
4. At each lifecycle point, `hooks.emit()` fires all matching handlers
|
||||
5. Errors in any handler are caught and logged — a broken hook never crashes the agent
|
||||
|
||||
:::info
|
||||
Hooks only fire in the **gateway** (Telegram, Discord, Slack, WhatsApp). The CLI does not currently load hooks.
|
||||
:::
|
||||
269
website/docs/user-guide/features/mcp.md
Normal file
269
website/docs/user-guide/features/mcp.md
Normal file
@@ -0,0 +1,269 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: "MCP (Model Context Protocol)"
|
||||
description: "Connect Hermes Agent to external tool servers via MCP — databases, APIs, filesystems, and more"
|
||||
---
|
||||
|
||||
# MCP (Model Context Protocol)
|
||||
|
||||
MCP lets Hermes Agent connect to external tool servers — giving the agent access to databases, APIs, filesystems, and more without any code changes.
|
||||
|
||||
## Overview
|
||||
|
||||
The [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) is an open standard for connecting AI agents to external tools and data sources. MCP servers expose tools over a lightweight RPC protocol, and Hermes Agent can connect to any compliant server automatically.
|
||||
|
||||
What this means for you:
|
||||
|
||||
- **Thousands of ready-made tools** — browse the [MCP server directory](https://github.com/modelcontextprotocol/servers) for servers covering GitHub, Slack, databases, file systems, web scraping, and more
|
||||
- **No code changes needed** — add a few lines to `~/.hermes/config.yaml` and the tools appear alongside built-in ones
|
||||
- **Mix and match** — run multiple MCP servers simultaneously, combining stdio-based and HTTP-based servers
|
||||
- **Secure by default** — environment variables are filtered and credentials are stripped from error messages
|
||||
|
||||
## Prerequisites
|
||||
|
||||
```bash
|
||||
pip install hermes-agent[mcp]
|
||||
```
|
||||
|
||||
| Server Type | Runtime Needed | Example |
|
||||
|-------------|---------------|---------|
|
||||
| HTTP/remote | Nothing extra | `url: "https://mcp.example.com"` |
|
||||
| npm-based (npx) | Node.js 18+ | `command: "npx"` |
|
||||
| Python-based | uv (recommended) | `command: "uvx"` |
|
||||
|
||||
## Configuration
|
||||
|
||||
MCP servers are configured in `~/.hermes/config.yaml` under the `mcp_servers` key.
|
||||
|
||||
### Stdio Servers
|
||||
|
||||
Stdio servers run as local subprocesses, communicating over stdin/stdout:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
|
||||
env: {}
|
||||
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxx"
|
||||
```
|
||||
|
||||
| Key | Required | Description |
|
||||
|-----|----------|-------------|
|
||||
| `command` | Yes | Executable to run (`npx`, `uvx`, `python`) |
|
||||
| `args` | No | Command-line arguments |
|
||||
| `env` | No | Environment variables for the subprocess |
|
||||
|
||||
:::info Security
|
||||
Only explicitly listed `env` variables plus a safe baseline (`PATH`, `HOME`, `USER`, `LANG`, `SHELL`, `TMPDIR`, `XDG_*`) are passed to the subprocess. Your API keys and secrets are **not** leaked.
|
||||
:::
|
||||
|
||||
### HTTP Servers
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
remote_api:
|
||||
url: "https://my-mcp-server.example.com/mcp"
|
||||
headers:
|
||||
Authorization: "Bearer sk-xxxxxxxxxxxx"
|
||||
```
|
||||
|
||||
### Per-Server Timeouts
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
slow_database:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-postgres"]
|
||||
env:
|
||||
DATABASE_URL: "postgres://user:pass@localhost/mydb"
|
||||
timeout: 300 # Tool call timeout (default: 120s)
|
||||
connect_timeout: 90 # Initial connection timeout (default: 60s)
|
||||
```
|
||||
|
||||
### Mixed Configuration Example
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
# Local filesystem via stdio
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
||||
|
||||
# GitHub API via stdio with auth
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxx"
|
||||
|
||||
# Remote database via HTTP
|
||||
company_db:
|
||||
url: "https://mcp.internal.company.com/db"
|
||||
headers:
|
||||
Authorization: "Bearer sk-xxxxxxxxxxxx"
|
||||
timeout: 180
|
||||
|
||||
# Python-based server via uvx
|
||||
memory:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-memory"]
|
||||
```
|
||||
|
||||
## Translating from Claude Desktop Config
|
||||
|
||||
Many MCP server docs show Claude Desktop JSON format. Here's the translation:
|
||||
|
||||
**Claude Desktop JSON:**
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"filesystem": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Hermes YAML:**
|
||||
```yaml
|
||||
mcp_servers: # mcpServers → mcp_servers (snake_case)
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
|
||||
```
|
||||
|
||||
Rules: `mcpServers` → `mcp_servers` (snake_case), JSON → YAML. Keys like `command`, `args`, `env` are identical.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Tool Registration
|
||||
|
||||
Each MCP tool is registered with a prefixed name:
|
||||
|
||||
```
|
||||
mcp_{server_name}_{tool_name}
|
||||
```
|
||||
|
||||
| Server Name | MCP Tool Name | Registered As |
|
||||
|-------------|--------------|---------------|
|
||||
| `filesystem` | `read_file` | `mcp_filesystem_read_file` |
|
||||
| `github` | `create-issue` | `mcp_github_create_issue` |
|
||||
| `my-api` | `query.data` | `mcp_my_api_query_data` |
|
||||
|
||||
Tools appear alongside built-in tools — the agent calls them like any other tool.
|
||||
|
||||
### Reconnection
|
||||
|
||||
If an MCP server disconnects, Hermes automatically reconnects with exponential backoff (1s, 2s, 4s, 8s, 16s — max 5 attempts). Initial connection failures are reported immediately.
|
||||
|
||||
### Shutdown
|
||||
|
||||
On agent exit, all MCP server connections are cleanly shut down.
|
||||
|
||||
## Popular MCP Servers
|
||||
|
||||
| Server | Package | Description |
|
||||
|--------|---------|-------------|
|
||||
| Filesystem | `@modelcontextprotocol/server-filesystem` | Read/write/search local files |
|
||||
| GitHub | `@modelcontextprotocol/server-github` | Issues, PRs, repos, code search |
|
||||
| Git | `@modelcontextprotocol/server-git` | Git operations on local repos |
|
||||
| Fetch | `@modelcontextprotocol/server-fetch` | HTTP fetching and web content |
|
||||
| Memory | `@modelcontextprotocol/server-memory` | Persistent key-value memory |
|
||||
| SQLite | `@modelcontextprotocol/server-sqlite` | Query SQLite databases |
|
||||
| PostgreSQL | `@modelcontextprotocol/server-postgres` | Query PostgreSQL databases |
|
||||
| Brave Search | `@modelcontextprotocol/server-brave-search` | Web search via Brave API |
|
||||
| Puppeteer | `@modelcontextprotocol/server-puppeteer` | Browser automation |
|
||||
|
||||
### Example Configs
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
# No API key needed
|
||||
filesystem:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/projects"]
|
||||
|
||||
git:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-git", "--repository", "/home/user/my-repo"]
|
||||
|
||||
fetch:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-fetch"]
|
||||
|
||||
sqlite:
|
||||
command: "uvx"
|
||||
args: ["mcp-server-sqlite", "--db-path", "/home/user/data.db"]
|
||||
|
||||
# Requires API key
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxxxxxxxxxxx"
|
||||
|
||||
brave_search:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-brave-search"]
|
||||
env:
|
||||
BRAVE_API_KEY: "BSA_xxxxxxxxxxxx"
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "MCP SDK not available"
|
||||
|
||||
```bash
|
||||
pip install hermes-agent[mcp]
|
||||
```
|
||||
|
||||
### Server fails to start
|
||||
|
||||
The MCP server command (`npx`, `uvx`) is not on PATH. Install the required runtime:
|
||||
|
||||
```bash
|
||||
# For npm-based servers
|
||||
npm install -g npx # or ensure Node.js 18+ is installed
|
||||
|
||||
# For Python-based servers
|
||||
pip install uv # then use "uvx" as the command
|
||||
```
|
||||
|
||||
### Server connects but tools fail with auth errors
|
||||
|
||||
Ensure the key is in the server's `env` block:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
github:
|
||||
command: "npx"
|
||||
args: ["-y", "@modelcontextprotocol/server-github"]
|
||||
env:
|
||||
GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_your_actual_token" # Check this
|
||||
```
|
||||
|
||||
### Connection timeout
|
||||
|
||||
Increase `connect_timeout` for slow-starting servers:
|
||||
|
||||
```yaml
|
||||
mcp_servers:
|
||||
slow_server:
|
||||
command: "npx"
|
||||
args: ["-y", "heavy-server-package"]
|
||||
connect_timeout: 120 # default is 60
|
||||
```
|
||||
|
||||
### Reload MCP Servers
|
||||
|
||||
You can reload MCP servers without restarting Hermes:
|
||||
|
||||
- In the CLI: the agent reconnects automatically
|
||||
- In messaging: send `/reload-mcp`
|
||||
97
website/docs/user-guide/features/memory.md
Normal file
97
website/docs/user-guide/features/memory.md
Normal file
@@ -0,0 +1,97 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: "Persistent Memory"
|
||||
description: "How Hermes Agent remembers across sessions — MEMORY.md, USER.md, and session search"
|
||||
---
|
||||
|
||||
# Persistent Memory
|
||||
|
||||
Hermes Agent has bounded, curated memory that persists across sessions. This lets it remember your preferences, your projects, your environment, and things it has learned.
|
||||
|
||||
## How It Works
|
||||
|
||||
Two files make up the agent's memory:
|
||||
|
||||
| File | Purpose | Token Budget |
|
||||
|------|---------|-------------|
|
||||
| **MEMORY.md** | Agent's personal notes — environment facts, conventions, things learned | ~800 tokens (~2200 chars) |
|
||||
| **USER.md** | User profile — your preferences, communication style, expectations | ~500 tokens (~1375 chars) |
|
||||
|
||||
Both are stored in `~/.hermes/memories/` and are injected into the system prompt as a frozen snapshot at session start. The agent manages its own memory via the `memory` tool — it can add, replace, or remove entries.
|
||||
|
||||
:::info
|
||||
Character limits keep memory focused. When memory is full, the agent consolidates or replaces entries to make room for new information.
|
||||
:::
|
||||
|
||||
## Configuration
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
memory:
|
||||
memory_enabled: true
|
||||
user_profile_enabled: true
|
||||
memory_char_limit: 2200 # ~800 tokens
|
||||
user_char_limit: 1375 # ~500 tokens
|
||||
```
|
||||
|
||||
## Memory Tool Actions
|
||||
|
||||
The agent uses the `memory` tool with these actions:
|
||||
|
||||
- **add** — Add a new memory entry
|
||||
- **replace** — Replace an existing entry with updated content
|
||||
- **remove** — Remove an entry that's no longer relevant
|
||||
- **read** — Read current memory contents
|
||||
|
||||
## Session Search
|
||||
|
||||
Beyond MEMORY.md and USER.md, the agent can search its past conversations using the `session_search` tool:
|
||||
|
||||
- All CLI and messaging sessions are stored in SQLite (`~/.hermes/state.db`) with FTS5 full-text search
|
||||
- Search queries return relevant past conversations with Gemini Flash summarization
|
||||
- The agent can find things it discussed weeks ago, even if they're not in its active memory
|
||||
|
||||
```bash
|
||||
hermes sessions list # Browse past sessions
|
||||
```
|
||||
|
||||
## Honcho Integration (Cross-Session User Modeling)
|
||||
|
||||
For deeper, AI-generated user understanding that works across tools, you can optionally enable [Honcho](https://honcho.dev/) by Plastic Labs. Honcho runs alongside existing memory — USER.md stays as-is, and Honcho adds an additional layer of context.
|
||||
|
||||
When enabled:
|
||||
- **Prefetch**: Each turn, Honcho's user representation is injected into the system prompt
|
||||
- **Sync**: After each conversation, messages are synced to Honcho
|
||||
- **Query tool**: The agent can actively query its understanding of you via `query_user_context`
|
||||
|
||||
**Setup:**
|
||||
|
||||
```bash
|
||||
# 1. Install the optional dependency
|
||||
uv pip install honcho-ai
|
||||
|
||||
# 2. Get an API key from https://app.honcho.dev
|
||||
|
||||
# 3. Create ~/.honcho/config.json
|
||||
cat > ~/.honcho/config.json << 'EOF'
|
||||
{
|
||||
"enabled": true,
|
||||
"apiKey": "your-honcho-api-key",
|
||||
"peerName": "your-name",
|
||||
"hosts": {
|
||||
"hermes": {
|
||||
"workspace": "hermes"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
```
|
||||
|
||||
Or via environment variable:
|
||||
```bash
|
||||
hermes config set HONCHO_API_KEY your-key
|
||||
```
|
||||
|
||||
:::tip
|
||||
Honcho is fully opt-in — zero behavior change when disabled or unconfigured. All Honcho calls are non-fatal; if the service is unreachable, the agent continues normally.
|
||||
:::
|
||||
159
website/docs/user-guide/features/skills.md
Normal file
159
website/docs/user-guide/features/skills.md
Normal file
@@ -0,0 +1,159 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: "Skills System"
|
||||
description: "On-demand knowledge documents — progressive disclosure, agent-managed skills, and the Skills Hub"
|
||||
---
|
||||
|
||||
# Skills System
|
||||
|
||||
Skills are on-demand knowledge documents the agent can load when needed. They follow a **progressive disclosure** pattern to minimize token usage and are compatible with the [agentskills.io](https://agentskills.io/specification) open standard.
|
||||
|
||||
All skills live in **`~/.hermes/skills/`** — a single directory that serves as the source of truth. On fresh install, bundled skills are copied from the repo. Hub-installed and agent-created skills also go here. The agent can modify or delete any skill.
|
||||
|
||||
## Using Skills
|
||||
|
||||
Every installed skill is automatically available as a slash command:
|
||||
|
||||
```bash
|
||||
# In the CLI or any messaging platform:
|
||||
/gif-search funny cats
|
||||
/axolotl help me fine-tune Llama 3 on my dataset
|
||||
/github-pr-workflow create a PR for the auth refactor
|
||||
|
||||
# Just the skill name loads it and lets the agent ask what you need:
|
||||
/excalidraw
|
||||
```
|
||||
|
||||
You can also interact with skills through natural conversation:
|
||||
|
||||
```bash
|
||||
hermes --toolsets skills -q "What skills do you have?"
|
||||
hermes --toolsets skills -q "Show me the axolotl skill"
|
||||
```
|
||||
|
||||
## Progressive Disclosure
|
||||
|
||||
Skills use a token-efficient loading pattern:
|
||||
|
||||
```
|
||||
Level 0: skills_categories() → ["mlops", "devops"] (~50 tokens)
|
||||
Level 1: skills_list(category) → [{name, description}, ...] (~3k tokens)
|
||||
Level 2: skill_view(name) → Full content + metadata (varies)
|
||||
Level 3: skill_view(name, path) → Specific reference file (varies)
|
||||
```
|
||||
|
||||
The agent only loads the full skill content when it actually needs it.
|
||||
|
||||
## SKILL.md Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: my-skill
|
||||
description: Brief description of what this skill does
|
||||
version: 1.0.0
|
||||
metadata:
|
||||
hermes:
|
||||
tags: [python, automation]
|
||||
category: devops
|
||||
---
|
||||
|
||||
# Skill Title
|
||||
|
||||
## When to Use
|
||||
Trigger conditions for this skill.
|
||||
|
||||
## Procedure
|
||||
1. Step one
|
||||
2. Step two
|
||||
|
||||
## Pitfalls
|
||||
- Known failure modes and fixes
|
||||
|
||||
## Verification
|
||||
How to confirm it worked.
|
||||
```
|
||||
|
||||
## Skill Directory Structure
|
||||
|
||||
```
|
||||
~/.hermes/skills/ # Single source of truth
|
||||
├── mlops/ # Category directory
|
||||
│ ├── axolotl/
|
||||
│ │ ├── SKILL.md # Main instructions (required)
|
||||
│ │ ├── references/ # Additional docs
|
||||
│ │ ├── templates/ # Output formats
|
||||
│ │ └── assets/ # Supplementary files
|
||||
│ └── vllm/
|
||||
│ └── SKILL.md
|
||||
├── devops/
|
||||
│ └── deploy-k8s/ # Agent-created skill
|
||||
│ ├── SKILL.md
|
||||
│ └── references/
|
||||
├── .hub/ # Skills Hub state
|
||||
│ ├── lock.json
|
||||
│ ├── quarantine/
|
||||
│ └── audit.log
|
||||
└── .bundled_manifest # Tracks seeded bundled skills
|
||||
```
|
||||
|
||||
## Agent-Managed Skills (skill_manage tool)
|
||||
|
||||
The agent can create, update, and delete its own skills via the `skill_manage` tool. This is the agent's **procedural memory** — when it figures out a non-trivial workflow, it saves the approach as a skill for future reuse.
|
||||
|
||||
### When the Agent Creates Skills
|
||||
|
||||
- After completing a complex task (5+ tool calls) successfully
|
||||
- When it hit errors or dead ends and found the working path
|
||||
- When the user corrected its approach
|
||||
- When it discovered a non-trivial workflow
|
||||
|
||||
### Actions
|
||||
|
||||
| Action | Use for | Key params |
|
||||
|--------|---------|------------|
|
||||
| `create` | New skill from scratch | `name`, `content` (full SKILL.md), optional `category` |
|
||||
| `patch` | Targeted fixes (preferred) | `name`, `old_string`, `new_string` |
|
||||
| `edit` | Major structural rewrites | `name`, `content` (full SKILL.md replacement) |
|
||||
| `delete` | Remove a skill entirely | `name` |
|
||||
| `write_file` | Add/update supporting files | `name`, `file_path`, `file_content` |
|
||||
| `remove_file` | Remove a supporting file | `name`, `file_path` |
|
||||
|
||||
:::tip
|
||||
The `patch` action is preferred for updates — it's more token-efficient than `edit` because only the changed text appears in the tool call.
|
||||
:::
|
||||
|
||||
## Skills Hub
|
||||
|
||||
Search, install, and manage skills from online registries:
|
||||
|
||||
```bash
|
||||
hermes skills search kubernetes # Search all sources
|
||||
hermes skills install openai/skills/k8s # Install with security scan
|
||||
hermes skills inspect openai/skills/k8s # Preview before installing
|
||||
hermes skills list --source hub # List hub-installed skills
|
||||
hermes skills audit # Re-scan all hub skills
|
||||
hermes skills uninstall k8s # Remove a hub skill
|
||||
hermes skills publish skills/my-skill --to github --repo owner/repo
|
||||
hermes skills snapshot export setup.json # Export skill config
|
||||
hermes skills tap add myorg/skills-repo # Add a custom source
|
||||
```
|
||||
|
||||
All hub-installed skills go through a **security scanner** that checks for data exfiltration, prompt injection, destructive commands, and other threats.
|
||||
|
||||
### Trust Levels
|
||||
|
||||
| Level | Source | Policy |
|
||||
|-------|--------|--------|
|
||||
| `builtin` | Ships with Hermes | Always trusted |
|
||||
| `trusted` | openai/skills, anthropics/skills | Trusted sources |
|
||||
| `community` | Everything else | Any findings = blocked unless `--force` |
|
||||
|
||||
### Slash Commands (Inside Chat)
|
||||
|
||||
All the same commands work with `/skills` prefix:
|
||||
|
||||
```
|
||||
/skills search kubernetes
|
||||
/skills install openai/skills/skill-creator
|
||||
/skills list
|
||||
```
|
||||
163
website/docs/user-guide/features/tools.md
Normal file
163
website/docs/user-guide/features/tools.md
Normal file
@@ -0,0 +1,163 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: "Tools & Toolsets"
|
||||
description: "Overview of Hermes Agent's tools — what's available, how toolsets work, and terminal backends"
|
||||
---
|
||||
|
||||
# Tools & Toolsets
|
||||
|
||||
Tools are functions that extend the agent's capabilities. They're organized into logical **toolsets** that can be enabled or disabled per platform.
|
||||
|
||||
## Available Tools
|
||||
|
||||
| Category | Tools | Description |
|
||||
|----------|-------|-------------|
|
||||
| **Web** | `web_search`, `web_extract`, `web_crawl` | Search the web, extract page content, crawl sites |
|
||||
| **Terminal** | `terminal` | Execute commands (local/docker/singularity/modal/ssh backends) |
|
||||
| **File** | `read_file`, `write_file`, `patch`, `search` | Read, write, edit, and search files |
|
||||
| **Browser** | `browser_navigate`, `browser_click`, `browser_type`, etc. | Full browser automation via Browserbase |
|
||||
| **Vision** | `vision_analyze` | Image analysis via multimodal models |
|
||||
| **Image Gen** | `image_generate` | Generate images (FLUX via FAL) |
|
||||
| **TTS** | `text_to_speech` | Text-to-speech (Edge TTS / ElevenLabs / OpenAI) |
|
||||
| **Reasoning** | `mixture_of_agents` | Multi-model reasoning |
|
||||
| **Skills** | `skills_list`, `skill_view`, `skill_manage` | Find, view, create, and manage skills |
|
||||
| **Todo** | `todo` | Read/write task list for multi-step planning |
|
||||
| **Memory** | `memory` | Persistent notes + user profile across sessions |
|
||||
| **Session Search** | `session_search` | Search + summarize past conversations (FTS5) |
|
||||
| **Cronjob** | `schedule_cronjob`, `list_cronjobs`, `remove_cronjob` | Scheduled task management |
|
||||
| **Code Execution** | `execute_code` | Run Python scripts that call tools via RPC sandbox |
|
||||
| **Delegation** | `delegate_task` | Spawn subagents with isolated context |
|
||||
| **Clarify** | `clarify` | Ask the user multiple-choice or open-ended questions (CLI-only) |
|
||||
| **MCP** | Auto-discovered | External tools from MCP servers |
|
||||
|
||||
## Using Toolsets
|
||||
|
||||
```bash
|
||||
# Use specific toolsets
|
||||
hermes --toolsets "web,terminal"
|
||||
|
||||
# See all available tools
|
||||
hermes tools
|
||||
|
||||
# Configure tools per platform (interactive)
|
||||
hermes tools
|
||||
```
|
||||
|
||||
**Available toolsets:** `web`, `terminal`, `file`, `browser`, `vision`, `image_gen`, `moa`, `skills`, `tts`, `todo`, `memory`, `session_search`, `cronjob`, `code_execution`, `delegation`, `clarify`, and more.
|
||||
|
||||
## Terminal Backends
|
||||
|
||||
The terminal tool can execute commands in different environments:
|
||||
|
||||
| Backend | Description | Use Case |
|
||||
|---------|-------------|----------|
|
||||
| `local` | Run on your machine (default) | Development, trusted tasks |
|
||||
| `docker` | Isolated containers | Security, reproducibility |
|
||||
| `ssh` | Remote server | Sandboxing, keep agent away from its own code |
|
||||
| `singularity` | HPC containers | Cluster computing, rootless |
|
||||
| `modal` | Cloud execution | Serverless, scale |
|
||||
|
||||
### Configuration
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
terminal:
|
||||
backend: local # or: docker, ssh, singularity, modal
|
||||
cwd: "." # Working directory
|
||||
timeout: 180 # Command timeout in seconds
|
||||
```
|
||||
|
||||
### Docker Backend
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
backend: docker
|
||||
docker_image: python:3.11-slim
|
||||
```
|
||||
|
||||
### SSH Backend
|
||||
|
||||
Recommended for security — agent can't modify its own code:
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
backend: ssh
|
||||
```
|
||||
```bash
|
||||
# Set credentials in ~/.hermes/.env
|
||||
TERMINAL_SSH_HOST=my-server.example.com
|
||||
TERMINAL_SSH_USER=myuser
|
||||
TERMINAL_SSH_KEY=~/.ssh/id_rsa
|
||||
```
|
||||
|
||||
### Singularity/Apptainer
|
||||
|
||||
```bash
|
||||
# Pre-build SIF for parallel workers
|
||||
apptainer build ~/python.sif docker://python:3.11-slim
|
||||
|
||||
# Configure
|
||||
hermes config set terminal.backend singularity
|
||||
hermes config set terminal.singularity_image ~/python.sif
|
||||
```
|
||||
|
||||
### Modal (Serverless Cloud)
|
||||
|
||||
```bash
|
||||
uv pip install "swe-rex[modal]"
|
||||
modal setup
|
||||
hermes config set terminal.backend modal
|
||||
```
|
||||
|
||||
### Container Resources
|
||||
|
||||
Configure CPU, memory, disk, and persistence for all container backends:
|
||||
|
||||
```yaml
|
||||
terminal:
|
||||
backend: docker # or singularity, modal
|
||||
container_cpu: 1 # CPU cores (default: 1)
|
||||
container_memory: 5120 # Memory in MB (default: 5GB)
|
||||
container_disk: 51200 # Disk in MB (default: 50GB)
|
||||
container_persistent: true # Persist filesystem across sessions (default: true)
|
||||
```
|
||||
|
||||
When `container_persistent: true`, installed packages, files, and config survive across sessions.
|
||||
|
||||
### Container Security
|
||||
|
||||
All container backends run with security hardening:
|
||||
|
||||
- Read-only root filesystem (Docker)
|
||||
- All Linux capabilities dropped
|
||||
- No privilege escalation
|
||||
- PID limits (256 processes)
|
||||
- Full namespace isolation
|
||||
- Persistent workspace via volumes, not writable root layer
|
||||
|
||||
## Background Process Management
|
||||
|
||||
Start background processes and manage them:
|
||||
|
||||
```python
|
||||
terminal(command="pytest -v tests/", background=true)
|
||||
# Returns: {"session_id": "proc_abc123", "pid": 12345}
|
||||
|
||||
# Then manage with the process tool:
|
||||
process(action="list") # Show all running processes
|
||||
process(action="poll", session_id="proc_abc123") # Check status
|
||||
process(action="wait", session_id="proc_abc123") # Block until done
|
||||
process(action="log", session_id="proc_abc123") # Full output
|
||||
process(action="kill", session_id="proc_abc123") # Terminate
|
||||
process(action="write", session_id="proc_abc123", data="y") # Send input
|
||||
```
|
||||
|
||||
PTY mode (`pty=true`) enables interactive CLI tools like Codex and Claude Code.
|
||||
|
||||
## Sudo Support
|
||||
|
||||
If a command needs sudo, you'll be prompted for your password (cached for the session). Or set `SUDO_PASSWORD` in `~/.hermes/.env`.
|
||||
|
||||
:::warning
|
||||
On messaging platforms, if sudo fails, the output includes a tip to add `SUDO_PASSWORD` to `~/.hermes/.env`.
|
||||
:::
|
||||
89
website/docs/user-guide/features/tts.md
Normal file
89
website/docs/user-guide/features/tts.md
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
sidebar_position: 9
|
||||
title: "Voice & TTS"
|
||||
description: "Text-to-speech and voice message transcription across all platforms"
|
||||
---
|
||||
|
||||
# Voice & TTS
|
||||
|
||||
Hermes Agent supports both text-to-speech output and voice message transcription across all messaging platforms.
|
||||
|
||||
## Text-to-Speech
|
||||
|
||||
Convert text to speech with three providers:
|
||||
|
||||
| Provider | Quality | Cost | API Key |
|
||||
|----------|---------|------|---------|
|
||||
| **Edge TTS** (default) | Good | Free | None needed |
|
||||
| **ElevenLabs** | Excellent | Paid | `ELEVENLABS_API_KEY` |
|
||||
| **OpenAI TTS** | Good | Paid | `VOICE_TOOLS_OPENAI_KEY` |
|
||||
|
||||
### Platform Delivery
|
||||
|
||||
| Platform | Delivery | Format |
|
||||
|----------|----------|--------|
|
||||
| Telegram | Voice bubble (plays inline) | Opus `.ogg` |
|
||||
| Discord | Audio file attachment | MP3 |
|
||||
| WhatsApp | Audio file attachment | MP3 |
|
||||
| CLI | Saved to `~/voice-memos/` | MP3 |
|
||||
|
||||
### Configuration
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
tts:
|
||||
provider: "edge" # "edge" | "elevenlabs" | "openai"
|
||||
edge:
|
||||
voice: "en-US-AriaNeural" # 322 voices, 74 languages
|
||||
elevenlabs:
|
||||
voice_id: "pNInz6obpgDQGcFmaJgB" # Adam
|
||||
model_id: "eleven_multilingual_v2"
|
||||
openai:
|
||||
model: "gpt-4o-mini-tts"
|
||||
voice: "alloy" # alloy, echo, fable, onyx, nova, shimmer
|
||||
```
|
||||
|
||||
### Telegram Voice Bubbles & ffmpeg
|
||||
|
||||
Telegram voice bubbles require Opus/OGG audio format:
|
||||
|
||||
- **OpenAI and ElevenLabs** produce Opus natively — no extra setup
|
||||
- **Edge TTS** (default) outputs MP3 and needs **ffmpeg** to convert:
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install ffmpeg
|
||||
|
||||
# macOS
|
||||
brew install ffmpeg
|
||||
|
||||
# Fedora
|
||||
sudo dnf install ffmpeg
|
||||
```
|
||||
|
||||
Without ffmpeg, Edge TTS audio is sent as a regular audio file (playable, but shows as a rectangular player instead of a voice bubble).
|
||||
|
||||
:::tip
|
||||
If you want voice bubbles without installing ffmpeg, switch to the OpenAI or ElevenLabs provider.
|
||||
:::
|
||||
|
||||
## Voice Message Transcription
|
||||
|
||||
Voice messages sent on Telegram, Discord, WhatsApp, or Slack are automatically transcribed and injected as text into the conversation. The agent sees the transcript as normal text.
|
||||
|
||||
| Provider | Model | Quality | Cost |
|
||||
|----------|-------|---------|------|
|
||||
| **OpenAI Whisper** | `whisper-1` (default) | Good | Low |
|
||||
| **OpenAI GPT-4o** | `gpt-4o-mini-transcribe` | Better | Medium |
|
||||
| **OpenAI GPT-4o** | `gpt-4o-transcribe` | Best | Higher |
|
||||
|
||||
Requires `VOICE_TOOLS_OPENAI_KEY` in `~/.hermes/.env`.
|
||||
|
||||
### Configuration
|
||||
|
||||
```yaml
|
||||
# In ~/.hermes/config.yaml
|
||||
stt:
|
||||
enabled: true
|
||||
model: "whisper-1"
|
||||
```
|
||||
8
website/docs/user-guide/messaging/_category_.json
Normal file
8
website/docs/user-guide/messaging/_category_.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"label": "Messaging Gateway",
|
||||
"position": 3,
|
||||
"link": {
|
||||
"type": "doc",
|
||||
"id": "user-guide/messaging/index"
|
||||
}
|
||||
}
|
||||
57
website/docs/user-guide/messaging/discord.md
Normal file
57
website/docs/user-guide/messaging/discord.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
title: "Discord"
|
||||
description: "Set up Hermes Agent as a Discord bot"
|
||||
---
|
||||
|
||||
# Discord Setup
|
||||
|
||||
Connect Hermes Agent to Discord to chat with it in DMs or server channels.
|
||||
|
||||
## Setup Steps
|
||||
|
||||
1. **Create a bot:** Go to the [Discord Developer Portal](https://discord.com/developers/applications)
|
||||
2. **Enable intents:** Bot → Privileged Gateway Intents → enable **Message Content Intent**
|
||||
3. **Get your user ID:** Enable Developer Mode in Discord settings, right-click your name → Copy ID
|
||||
4. **Invite to your server:** OAuth2 → URL Generator → scopes: `bot`, `applications.commands` → permissions: Send Messages, Read Message History, Attach Files
|
||||
5. **Configure:** Run `hermes gateway setup` and select Discord, or add to `~/.hermes/.env` manually:
|
||||
|
||||
```bash
|
||||
DISCORD_BOT_TOKEN=MTIz...
|
||||
DISCORD_ALLOWED_USERS=YOUR_USER_ID
|
||||
```
|
||||
|
||||
6. **Start the gateway:**
|
||||
|
||||
```bash
|
||||
hermes gateway
|
||||
```
|
||||
|
||||
## Optional: Home Channel
|
||||
|
||||
Set a default channel for cron job delivery:
|
||||
|
||||
```bash
|
||||
DISCORD_HOME_CHANNEL=123456789012345678
|
||||
DISCORD_HOME_CHANNEL_NAME="#bot-updates"
|
||||
```
|
||||
|
||||
Or use `/sethome` in any Discord channel.
|
||||
|
||||
## Required Bot Permissions
|
||||
|
||||
When generating the invite URL, make sure to include:
|
||||
|
||||
- **Send Messages** — bot needs to reply
|
||||
- **Read Message History** — for context
|
||||
- **Attach Files** — for audio, images, and file outputs
|
||||
|
||||
## Voice Messages
|
||||
|
||||
Voice messages on Discord are automatically transcribed (requires `VOICE_TOOLS_OPENAI_KEY`). TTS audio is sent as MP3 file attachments.
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
Always set `DISCORD_ALLOWED_USERS` to restrict who can use the bot. Without it, the gateway denies all users by default.
|
||||
:::
|
||||
204
website/docs/user-guide/messaging/index.md
Normal file
204
website/docs/user-guide/messaging/index.md
Normal file
@@ -0,0 +1,204 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
title: "Messaging Gateway"
|
||||
description: "Chat with Hermes from Telegram, Discord, Slack, or WhatsApp — architecture and setup overview"
|
||||
---
|
||||
|
||||
# Messaging Gateway
|
||||
|
||||
Chat with Hermes from Telegram, Discord, Slack, or WhatsApp. The gateway is a single background process that connects to all your configured platforms, handles sessions, runs cron jobs, and delivers voice messages.
|
||||
|
||||
## Architecture
|
||||
|
||||
```text
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Hermes Gateway │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
|
||||
│ │ Telegram │ │ Discord │ │ WhatsApp │ │ Slack │ │
|
||||
│ │ Adapter │ │ Adapter │ │ Adapter │ │ Adapter │ │
|
||||
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └─────────────┼────────────┼─────────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────▼────────┐ │
|
||||
│ │ Session Store │ │
|
||||
│ │ (per-chat) │ │
|
||||
│ └────────┬────────┘ │
|
||||
│ │ │
|
||||
│ ┌────────▼────────┐ │
|
||||
│ │ AIAgent │ │
|
||||
│ │ (run_agent) │ │
|
||||
│ └─────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Each platform adapter receives messages, routes them through a per-chat session store, and dispatches them to the AIAgent for processing. The gateway also runs the cron scheduler, ticking every 60 seconds to execute any due jobs.
|
||||
|
||||
## Quick Setup
|
||||
|
||||
The easiest way to configure messaging platforms is the interactive wizard:
|
||||
|
||||
```bash
|
||||
hermes gateway setup # Interactive setup for all messaging platforms
|
||||
```
|
||||
|
||||
This walks you through configuring each platform with arrow-key selection, shows which platforms are already configured, and offers to start/restart the gateway when done.
|
||||
|
||||
## Gateway Commands
|
||||
|
||||
```bash
|
||||
hermes gateway # Run in foreground
|
||||
hermes gateway setup # Configure messaging platforms interactively
|
||||
hermes gateway install # Install as systemd service (Linux) / launchd (macOS)
|
||||
hermes gateway start # Start the service
|
||||
hermes gateway stop # Stop the service
|
||||
hermes gateway status # Check service status
|
||||
```
|
||||
|
||||
## Chat Commands (Inside Messaging)
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `/new` or `/reset` | Start fresh conversation |
|
||||
| `/model [name]` | Show or change the model |
|
||||
| `/personality [name]` | Set a personality |
|
||||
| `/retry` | Retry the last message |
|
||||
| `/undo` | Remove the last exchange |
|
||||
| `/status` | Show session info |
|
||||
| `/stop` | Stop the running agent |
|
||||
| `/sethome` | Set this chat as the home channel |
|
||||
| `/compress` | Manually compress conversation context |
|
||||
| `/usage` | Show token usage for this session |
|
||||
| `/reload-mcp` | Reload MCP servers from config |
|
||||
| `/update` | Update Hermes Agent to the latest version |
|
||||
| `/help` | Show available commands |
|
||||
| `/<skill-name>` | Invoke any installed skill |
|
||||
|
||||
## Session Management
|
||||
|
||||
### Session Persistence
|
||||
|
||||
Sessions persist across messages until they reset. The agent remembers your conversation context.
|
||||
|
||||
### Reset Policies
|
||||
|
||||
Sessions reset based on configurable policies:
|
||||
|
||||
| Policy | Default | Description |
|
||||
|--------|---------|-------------|
|
||||
| Daily | 4:00 AM | Reset at a specific hour each day |
|
||||
| Idle | 120 min | Reset after N minutes of inactivity |
|
||||
| Both | (combined) | Whichever triggers first |
|
||||
|
||||
Configure per-platform overrides in `~/.hermes/gateway.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"reset_by_platform": {
|
||||
"telegram": { "mode": "idle", "idle_minutes": 240 },
|
||||
"discord": { "mode": "idle", "idle_minutes": 60 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
**By default, the gateway denies all users who are not in an allowlist or paired via DM.** This is the safe default for a bot with terminal access.
|
||||
|
||||
```bash
|
||||
# Restrict to specific users (recommended):
|
||||
TELEGRAM_ALLOWED_USERS=123456789,987654321
|
||||
DISCORD_ALLOWED_USERS=123456789012345678
|
||||
|
||||
# Or explicitly allow all users (NOT recommended for bots with terminal access):
|
||||
GATEWAY_ALLOW_ALL_USERS=true
|
||||
```
|
||||
|
||||
### DM Pairing (Alternative to Allowlists)
|
||||
|
||||
Instead of manually configuring user IDs, unknown users receive a one-time pairing code when they DM the bot:
|
||||
|
||||
```bash
|
||||
# The user sees: "Pairing code: XKGH5N7P"
|
||||
# You approve them with:
|
||||
hermes pairing approve telegram XKGH5N7P
|
||||
|
||||
# Other pairing commands:
|
||||
hermes pairing list # View pending + approved users
|
||||
hermes pairing revoke telegram 123456789 # Remove access
|
||||
```
|
||||
|
||||
Pairing codes expire after 1 hour, are rate-limited, and use cryptographic randomness.
|
||||
|
||||
## Interrupting the Agent
|
||||
|
||||
Send any message while the agent is working to interrupt it. Key behaviors:
|
||||
|
||||
- **In-progress terminal commands are killed immediately** (SIGTERM, then SIGKILL after 1s)
|
||||
- **Tool calls are cancelled** — only the currently-executing one runs, the rest are skipped
|
||||
- **Multiple messages are combined** — messages sent during interruption are joined into one prompt
|
||||
- **`/stop` command** — interrupts without queuing a follow-up message
|
||||
|
||||
## Tool Progress Notifications
|
||||
|
||||
Control how much tool activity is displayed in `~/.hermes/config.yaml`:
|
||||
|
||||
```yaml
|
||||
display:
|
||||
tool_progress: all # off | new | all | verbose
|
||||
```
|
||||
|
||||
When enabled, the bot sends status messages as it works:
|
||||
|
||||
```text
|
||||
💻 `ls -la`...
|
||||
🔍 web_search...
|
||||
📄 web_extract...
|
||||
🐍 execute_code...
|
||||
```
|
||||
|
||||
## Service Management
|
||||
|
||||
### Linux (systemd)
|
||||
|
||||
```bash
|
||||
hermes gateway install # Install as user service
|
||||
systemctl --user start hermes-gateway
|
||||
systemctl --user stop hermes-gateway
|
||||
systemctl --user status hermes-gateway
|
||||
journalctl --user -u hermes-gateway -f
|
||||
|
||||
# Enable lingering (keeps running after logout)
|
||||
sudo loginctl enable-linger $USER
|
||||
```
|
||||
|
||||
### macOS (launchd)
|
||||
|
||||
```bash
|
||||
hermes gateway install
|
||||
launchctl start ai.hermes.gateway
|
||||
launchctl stop ai.hermes.gateway
|
||||
tail -f ~/.hermes/logs/gateway.log
|
||||
```
|
||||
|
||||
## Platform-Specific Toolsets
|
||||
|
||||
Each platform has its own toolset:
|
||||
|
||||
| Platform | Toolset | Capabilities |
|
||||
|----------|---------|--------------|
|
||||
| CLI | `hermes-cli` | Full access |
|
||||
| Telegram | `hermes-telegram` | Full tools including terminal |
|
||||
| Discord | `hermes-discord` | Full tools including terminal |
|
||||
| WhatsApp | `hermes-whatsapp` | Full tools including terminal |
|
||||
| Slack | `hermes-slack` | Full tools including terminal |
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [Telegram Setup](telegram.md)
|
||||
- [Discord Setup](discord.md)
|
||||
- [Slack Setup](slack.md)
|
||||
- [WhatsApp Setup](whatsapp.md)
|
||||
57
website/docs/user-guide/messaging/slack.md
Normal file
57
website/docs/user-guide/messaging/slack.md
Normal file
@@ -0,0 +1,57 @@
|
||||
---
|
||||
sidebar_position: 4
|
||||
title: "Slack"
|
||||
description: "Set up Hermes Agent as a Slack bot"
|
||||
---
|
||||
|
||||
# Slack Setup
|
||||
|
||||
Connect Hermes Agent to Slack using Socket Mode for real-time communication.
|
||||
|
||||
## Setup Steps
|
||||
|
||||
1. **Create an app:** Go to [Slack API](https://api.slack.com/apps), create a new app
|
||||
2. **Enable Socket Mode:** In app settings → Socket Mode → Enable
|
||||
3. **Get tokens:**
|
||||
- Bot Token (`xoxb-...`): OAuth & Permissions → Install to Workspace
|
||||
- App Token (`xapp-...`): Basic Information → App-Level Tokens → Generate (with `connections:write` scope)
|
||||
4. **Configure:** Run `hermes gateway setup` and select Slack, or add to `~/.hermes/.env` manually:
|
||||
|
||||
```bash
|
||||
SLACK_BOT_TOKEN=xoxb-...
|
||||
SLACK_APP_TOKEN=xapp-...
|
||||
SLACK_ALLOWED_USERS=U01234ABCDE # Comma-separated Slack user IDs
|
||||
```
|
||||
|
||||
5. **Start the gateway:**
|
||||
|
||||
```bash
|
||||
hermes gateway
|
||||
```
|
||||
|
||||
## Optional: Home Channel
|
||||
|
||||
Set a default channel for cron job delivery:
|
||||
|
||||
```bash
|
||||
SLACK_HOME_CHANNEL=C01234567890
|
||||
```
|
||||
|
||||
## Required Bot Scopes
|
||||
|
||||
Make sure your Slack app has these OAuth scopes:
|
||||
|
||||
- `chat:write` — Send messages
|
||||
- `channels:history` — Read channel messages
|
||||
- `im:history` — Read DM messages
|
||||
- `files:write` — Upload files (audio, images)
|
||||
|
||||
## Voice Messages
|
||||
|
||||
Voice messages on Slack are automatically transcribed (requires `VOICE_TOOLS_OPENAI_KEY`). TTS audio is sent as file attachments.
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
Always set `SLACK_ALLOWED_USERS` to restrict who can use the bot. Without it, the gateway denies all users by default.
|
||||
:::
|
||||
74
website/docs/user-guide/messaging/telegram.md
Normal file
74
website/docs/user-guide/messaging/telegram.md
Normal file
@@ -0,0 +1,74 @@
|
||||
---
|
||||
sidebar_position: 2
|
||||
title: "Telegram"
|
||||
description: "Set up Hermes Agent as a Telegram bot"
|
||||
---
|
||||
|
||||
# Telegram Setup
|
||||
|
||||
Connect Hermes Agent to Telegram so you can chat from your phone, send voice memos, and receive scheduled task results.
|
||||
|
||||
## Setup Steps
|
||||
|
||||
1. **Create a bot:** Message [@BotFather](https://t.me/BotFather) on Telegram, use `/newbot`
|
||||
2. **Get your user ID:** Message [@userinfobot](https://t.me/userinfobot) — it replies with your numeric ID
|
||||
3. **Configure:** Run `hermes gateway setup` and select Telegram, or add to `~/.hermes/.env` manually:
|
||||
|
||||
```bash
|
||||
TELEGRAM_BOT_TOKEN=123456:ABC-DEF...
|
||||
TELEGRAM_ALLOWED_USERS=YOUR_USER_ID # Comma-separated for multiple users
|
||||
```
|
||||
|
||||
4. **Start the gateway:**
|
||||
|
||||
```bash
|
||||
hermes gateway
|
||||
```
|
||||
|
||||
## Optional: Home Channel
|
||||
|
||||
Set a home channel for cron job delivery:
|
||||
|
||||
```bash
|
||||
TELEGRAM_HOME_CHANNEL=-1001234567890
|
||||
TELEGRAM_HOME_CHANNEL_NAME="My Notes"
|
||||
```
|
||||
|
||||
Or use the `/sethome` command in any Telegram chat to set it dynamically.
|
||||
|
||||
## Voice Messages
|
||||
|
||||
Voice messages sent on Telegram are automatically transcribed using OpenAI's Whisper API and injected as text into the conversation. Requires `VOICE_TOOLS_OPENAI_KEY` in `~/.hermes/.env`.
|
||||
|
||||
### Voice Bubbles (TTS)
|
||||
|
||||
When the agent generates audio via text-to-speech, it's delivered as native Telegram voice bubbles (the round, inline-playable kind).
|
||||
|
||||
- **OpenAI and ElevenLabs** produce Opus natively — no extra setup needed
|
||||
- **Edge TTS** (the default free provider) outputs MP3 and needs **ffmpeg** to convert to Opus:
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install ffmpeg
|
||||
|
||||
# macOS
|
||||
brew install ffmpeg
|
||||
```
|
||||
|
||||
Without ffmpeg, Edge TTS audio is sent as a regular audio file (still playable, but rectangular player instead of voice bubble).
|
||||
|
||||
## Exec Approval
|
||||
|
||||
When the agent tries to run a potentially dangerous command, it asks you for approval in the chat:
|
||||
|
||||
> ⚠️ This command is potentially dangerous (recursive delete). Reply "yes" to approve.
|
||||
|
||||
Reply "yes"/"y" to approve or "no"/"n" to deny.
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
Always set `TELEGRAM_ALLOWED_USERS` to restrict who can use the bot. Without it, the gateway denies all users by default.
|
||||
:::
|
||||
|
||||
You can also use [DM pairing](/user-guide/messaging#dm-pairing-alternative-to-allowlists) for a more dynamic approach.
|
||||
77
website/docs/user-guide/messaging/whatsapp.md
Normal file
77
website/docs/user-guide/messaging/whatsapp.md
Normal file
@@ -0,0 +1,77 @@
|
||||
---
|
||||
sidebar_position: 5
|
||||
title: "WhatsApp"
|
||||
description: "Set up Hermes Agent as a WhatsApp bot via the built-in Baileys bridge"
|
||||
---
|
||||
|
||||
# WhatsApp Setup
|
||||
|
||||
WhatsApp doesn't have a simple bot API like Telegram or Discord. Hermes includes a built-in bridge using [Baileys](https://github.com/WhiskeySockets/Baileys) that connects via WhatsApp Web.
|
||||
|
||||
## Two Modes
|
||||
|
||||
| Mode | How it works | Best for |
|
||||
|------|-------------|----------|
|
||||
| **Separate bot number** (recommended) | Dedicate a phone number to the bot. People message that number directly. | Clean UX, multiple users |
|
||||
| **Personal self-chat** | Use your own WhatsApp. You message yourself to talk to the agent. | Quick setup, single user |
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
hermes whatsapp
|
||||
```
|
||||
|
||||
The wizard will:
|
||||
|
||||
1. Ask which mode you want
|
||||
2. For **bot mode**: guide you through getting a second number
|
||||
3. Configure the allowlist
|
||||
4. Install bridge dependencies (Node.js required)
|
||||
5. Display a QR code — scan from WhatsApp → Settings → Linked Devices → Link a Device
|
||||
6. Exit once paired
|
||||
|
||||
## Getting a Second Number (Bot Mode)
|
||||
|
||||
| Option | Cost | Notes |
|
||||
|--------|------|-------|
|
||||
| WhatsApp Business app + dual-SIM | Free (if you have dual-SIM) | Install alongside personal WhatsApp, no second phone needed |
|
||||
| Google Voice | Free (US only) | voice.google.com, verify WhatsApp via the Google Voice app |
|
||||
| Prepaid SIM | $3-10/month | Any carrier; verify once, phone can go in a drawer on WiFi |
|
||||
|
||||
## Starting the Gateway
|
||||
|
||||
```bash
|
||||
hermes gateway # Foreground
|
||||
hermes gateway install # Or install as a system service
|
||||
```
|
||||
|
||||
The gateway starts the WhatsApp bridge automatically using the saved session.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
```bash
|
||||
WHATSAPP_ENABLED=true
|
||||
WHATSAPP_MODE=bot # "bot" or "self-chat"
|
||||
WHATSAPP_ALLOWED_USERS=15551234567 # Comma-separated phone numbers with country code
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Agent responses are prefixed with "⚕ **Hermes Agent**" for easy identification
|
||||
- WhatsApp Web sessions can disconnect if WhatsApp updates their protocol
|
||||
- The gateway reconnects automatically
|
||||
- If you see persistent failures, re-pair with `hermes whatsapp`
|
||||
|
||||
:::info Re-pairing
|
||||
If WhatsApp Web sessions disconnect (protocol updates, phone reset), re-pair with `hermes whatsapp`. The gateway handles temporary disconnections automatically.
|
||||
:::
|
||||
|
||||
## Voice Messages
|
||||
|
||||
Voice messages sent on WhatsApp are automatically transcribed (requires `VOICE_TOOLS_OPENAI_KEY`). TTS audio is sent as MP3 file attachments.
|
||||
|
||||
## Security
|
||||
|
||||
:::warning
|
||||
Always set `WHATSAPP_ALLOWED_USERS` with phone numbers (including country code) to restrict who can use the bot.
|
||||
:::
|
||||
120
website/docusaurus.config.ts
Normal file
120
website/docusaurus.config.ts
Normal file
@@ -0,0 +1,120 @@
|
||||
import {themes as prismThemes} from 'prism-react-renderer';
|
||||
import type {Config} from '@docusaurus/types';
|
||||
import type * as Preset from '@docusaurus/preset-classic';
|
||||
|
||||
const config: Config = {
|
||||
title: 'Hermes Agent',
|
||||
tagline: 'An AI agent that grows with you',
|
||||
favicon: 'img/favicon.svg',
|
||||
|
||||
url: 'https://hermes-agent.nousresearch.com',
|
||||
baseUrl: '/docs/',
|
||||
|
||||
organizationName: 'NousResearch',
|
||||
projectName: 'hermes-agent',
|
||||
|
||||
onBrokenLinks: 'warn',
|
||||
|
||||
markdown: {
|
||||
hooks: {
|
||||
onBrokenMarkdownLinks: 'warn',
|
||||
},
|
||||
},
|
||||
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: ['en'],
|
||||
},
|
||||
|
||||
presets: [
|
||||
[
|
||||
'classic',
|
||||
{
|
||||
docs: {
|
||||
routeBasePath: '/', // Docs at the root of /docs/
|
||||
sidebarPath: './sidebars.ts',
|
||||
editUrl: 'https://github.com/NousResearch/hermes-agent/edit/main/website/',
|
||||
},
|
||||
blog: false,
|
||||
theme: {
|
||||
customCss: './src/css/custom.css',
|
||||
},
|
||||
} satisfies Preset.Options,
|
||||
],
|
||||
],
|
||||
|
||||
themeConfig: {
|
||||
image: 'img/hermes-agent-banner.png',
|
||||
colorMode: {
|
||||
defaultMode: 'dark',
|
||||
respectPrefersColorScheme: true,
|
||||
},
|
||||
navbar: {
|
||||
title: 'Hermes Agent',
|
||||
logo: {
|
||||
alt: 'Hermes Agent',
|
||||
src: 'img/favicon.svg',
|
||||
},
|
||||
items: [
|
||||
{
|
||||
type: 'docSidebar',
|
||||
sidebarId: 'docs',
|
||||
position: 'left',
|
||||
label: 'Docs',
|
||||
},
|
||||
{
|
||||
href: 'https://hermes-agent.nousresearch.com',
|
||||
label: 'Home',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: 'https://github.com/NousResearch/hermes-agent',
|
||||
label: 'GitHub',
|
||||
position: 'right',
|
||||
},
|
||||
{
|
||||
href: 'https://discord.gg/NousResearch',
|
||||
label: 'Discord',
|
||||
position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Docs',
|
||||
items: [
|
||||
{ label: 'Getting Started', to: '/getting-started/installation' },
|
||||
{ label: 'User Guide', to: '/user-guide/cli' },
|
||||
{ label: 'Developer Guide', to: '/developer-guide/architecture' },
|
||||
{ label: 'Reference', to: '/reference/cli-commands' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
items: [
|
||||
{ label: 'Discord', href: 'https://discord.gg/NousResearch' },
|
||||
{ label: 'GitHub Discussions', href: 'https://github.com/NousResearch/hermes-agent/discussions' },
|
||||
{ label: 'Skills Hub', href: 'https://agentskills.io' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'More',
|
||||
items: [
|
||||
{ label: 'GitHub', href: 'https://github.com/NousResearch/hermes-agent' },
|
||||
{ label: 'Nous Research', href: 'https://nousresearch.com' },
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Built by <a href="https://nousresearch.com">Nous Research</a> · MIT License · ${new Date().getFullYear()}`,
|
||||
},
|
||||
prism: {
|
||||
theme: prismThemes.github,
|
||||
darkTheme: prismThemes.dracula,
|
||||
additionalLanguages: ['bash', 'yaml', 'json', 'python', 'toml'],
|
||||
},
|
||||
} satisfies Preset.ThemeConfig,
|
||||
};
|
||||
|
||||
export default config;
|
||||
18448
website/package-lock.json
generated
Normal file
18448
website/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
47
website/package.json
Normal file
47
website/package.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "website",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
"start": "docusaurus start",
|
||||
"build": "docusaurus build",
|
||||
"swizzle": "docusaurus swizzle",
|
||||
"deploy": "docusaurus deploy",
|
||||
"clear": "docusaurus clear",
|
||||
"serve": "docusaurus serve",
|
||||
"write-translations": "docusaurus write-translations",
|
||||
"write-heading-ids": "docusaurus write-heading-ids",
|
||||
"typecheck": "tsc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/core": "3.9.2",
|
||||
"@docusaurus/preset-classic": "3.9.2",
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"clsx": "^2.0.0",
|
||||
"prism-react-renderer": "^2.3.0",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docusaurus/module-type-aliases": "3.9.2",
|
||||
"@docusaurus/tsconfig": "3.9.2",
|
||||
"@docusaurus/types": "3.9.2",
|
||||
"typescript": "~5.6.2"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.5%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 3 chrome version",
|
||||
"last 3 firefox version",
|
||||
"last 5 safari version"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0"
|
||||
}
|
||||
}
|
||||
71
website/sidebars.ts
Normal file
71
website/sidebars.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
|
||||
|
||||
const sidebars: SidebarsConfig = {
|
||||
docs: [
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Getting Started',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'getting-started/installation',
|
||||
'getting-started/quickstart',
|
||||
'getting-started/updating',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'User Guide',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'user-guide/cli',
|
||||
'user-guide/configuration',
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Messaging Gateway',
|
||||
items: [
|
||||
'user-guide/messaging/index',
|
||||
'user-guide/messaging/telegram',
|
||||
'user-guide/messaging/discord',
|
||||
'user-guide/messaging/slack',
|
||||
'user-guide/messaging/whatsapp',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Features',
|
||||
items: [
|
||||
'user-guide/features/tools',
|
||||
'user-guide/features/skills',
|
||||
'user-guide/features/memory',
|
||||
'user-guide/features/mcp',
|
||||
'user-guide/features/cron',
|
||||
'user-guide/features/hooks',
|
||||
'user-guide/features/delegation',
|
||||
'user-guide/features/code-execution',
|
||||
'user-guide/features/tts',
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Developer Guide',
|
||||
items: [
|
||||
'developer-guide/architecture',
|
||||
'developer-guide/adding-tools',
|
||||
'developer-guide/creating-skills',
|
||||
'developer-guide/contributing',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'category',
|
||||
label: 'Reference',
|
||||
items: [
|
||||
'reference/cli-commands',
|
||||
'reference/environment-variables',
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default sidebars;
|
||||
156
website/src/css/custom.css
Normal file
156
website/src/css/custom.css
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Hermes Agent — Custom Docusaurus Theme
|
||||
* Matches the landing page branding: amber-on-dark, terminal aesthetic
|
||||
* Colors from landingpage/style.css
|
||||
*/
|
||||
|
||||
/* Import fonts to match landing page */
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');
|
||||
|
||||
:root {
|
||||
/* Gold/Amber palette from landing page */
|
||||
--ifm-color-primary: #FFD700;
|
||||
--ifm-color-primary-dark: #E6C200;
|
||||
--ifm-color-primary-darker: #D9B700;
|
||||
--ifm-color-primary-darkest: #B39600;
|
||||
--ifm-color-primary-light: #FFDD33;
|
||||
--ifm-color-primary-lighter: #FFE14D;
|
||||
--ifm-color-primary-lightest: #FFEB80;
|
||||
|
||||
--ifm-font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||
--ifm-font-family-monospace: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', monospace;
|
||||
|
||||
--ifm-code-font-size: 90%;
|
||||
--ifm-heading-font-weight: 600;
|
||||
}
|
||||
|
||||
/* Dark mode — the PRIMARY mode, matches landing page */
|
||||
[data-theme='dark'] {
|
||||
--ifm-color-primary: #FFD700;
|
||||
--ifm-color-primary-dark: #E6C200;
|
||||
--ifm-color-primary-darker: #D9B700;
|
||||
--ifm-color-primary-darkest: #B39600;
|
||||
--ifm-color-primary-light: #FFDD33;
|
||||
--ifm-color-primary-lighter: #FFE14D;
|
||||
--ifm-color-primary-lightest: #FFEB80;
|
||||
|
||||
--ifm-background-color: #07070d;
|
||||
--ifm-background-surface-color: #0f0f18;
|
||||
--ifm-navbar-background-color: #07070dEE;
|
||||
--ifm-footer-background-color: #050509;
|
||||
--ifm-color-emphasis-100: #14142a;
|
||||
--ifm-color-emphasis-200: #1a1a30;
|
||||
|
||||
--ifm-font-color-base: #e8e4dc;
|
||||
--ifm-font-color-secondary: #9a968e;
|
||||
|
||||
--ifm-link-color: #FFD700;
|
||||
--ifm-link-hover-color: #FFBF00;
|
||||
|
||||
--ifm-code-background: #0f0f18;
|
||||
|
||||
--ifm-toc-border-color: rgba(255, 215, 0, 0.08);
|
||||
--ifm-hr-border-color: rgba(255, 215, 0, 0.08);
|
||||
|
||||
--docusaurus-highlighted-code-line-bg: rgba(255, 215, 0, 0.08);
|
||||
}
|
||||
|
||||
/* Subtle dot grid background matching landing page */
|
||||
[data-theme='dark'] .main-wrapper {
|
||||
background-image: radial-gradient(rgba(255, 215, 0, 0.02) 1px, transparent 1px);
|
||||
background-size: 32px 32px;
|
||||
}
|
||||
|
||||
/* Navbar styling */
|
||||
.navbar {
|
||||
backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid rgba(255, 215, 0, 0.08);
|
||||
}
|
||||
|
||||
.navbar__title {
|
||||
font-weight: 600;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
/* Sidebar tweaks */
|
||||
[data-theme='dark'] .menu {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
[data-theme='dark'] .menu__link--active:not(.menu__link--sublist) {
|
||||
background-color: rgba(255, 215, 0, 0.08);
|
||||
border-left: 3px solid #FFD700;
|
||||
padding-left: calc(var(--ifm-menu-link-padding-horizontal) - 3px);
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
[data-theme='dark'] .prism-code {
|
||||
background-color: #0a0a12 !important;
|
||||
border: 1px solid rgba(255, 215, 0, 0.06);
|
||||
}
|
||||
|
||||
/* Admonitions — gold-tinted */
|
||||
[data-theme='dark'] .alert--info {
|
||||
--ifm-alert-background-color: rgba(255, 215, 0, 0.05);
|
||||
--ifm-alert-border-color: rgba(255, 215, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Table styling */
|
||||
[data-theme='dark'] table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
[data-theme='dark'] table th {
|
||||
background-color: rgba(255, 215, 0, 0.06);
|
||||
border-color: rgba(255, 215, 0, 0.12);
|
||||
}
|
||||
|
||||
[data-theme='dark'] table td {
|
||||
border-color: rgba(255, 215, 0, 0.06);
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
border-top: 1px solid rgba(255, 215, 0, 0.08);
|
||||
}
|
||||
|
||||
.footer a {
|
||||
color: #9a968e;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.footer a:hover {
|
||||
color: #FFD700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* Scrollbar */
|
||||
[data-theme='dark'] ::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
[data-theme='dark'] ::-webkit-scrollbar-track {
|
||||
background: #07070d;
|
||||
}
|
||||
|
||||
[data-theme='dark'] ::-webkit-scrollbar-thumb {
|
||||
background: #1a1a30;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
[data-theme='dark'] ::-webkit-scrollbar-thumb:hover {
|
||||
background: #2a2a40;
|
||||
}
|
||||
|
||||
/* Search bar */
|
||||
[data-theme='dark'] .DocSearch-Button {
|
||||
background-color: #0f0f18;
|
||||
border: 1px solid rgba(255, 215, 0, 0.08);
|
||||
}
|
||||
|
||||
/* Hero banner for docs landing if needed */
|
||||
.hero--hermes {
|
||||
background: linear-gradient(135deg, #07070d 0%, #0f0f18 100%);
|
||||
padding: 4rem 0;
|
||||
}
|
||||
0
website/static/.nojekyll
Normal file
0
website/static/.nojekyll
Normal file
3
website/static/img/favicon.svg
Normal file
3
website/static/img/favicon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<text y=".9em" font-size="90">⚕</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 113 B |
BIN
website/static/img/hermes-agent-banner.png
Normal file
BIN
website/static/img/hermes-agent-banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
website/static/img/nous-logo.png
Normal file
BIN
website/static/img/nous-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
8
website/tsconfig.json
Normal file
8
website/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
// This file is not used in compilation. It is here just for a nice editor experience.
|
||||
"extends": "@docusaurus/tsconfig",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "."
|
||||
},
|
||||
"exclude": [".docusaurus", "build"]
|
||||
}
|
||||
Reference in New Issue
Block a user