mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 06:51:16 +08:00
docs: update tool-adding instructions for auto-discovery
- AGENTS.md: 3 files → 2 files, remove _discover_tools() step - adding-tools.md: remove Step 3, note auto-discovery - architecture.md: update discovery description - tools-runtime.md: replace manual list with discover_builtin_tools() docs - hermes-agent skill: remove manual import step
This commit is contained in:
@@ -13,7 +13,7 @@ source venv/bin/activate # ALWAYS activate before running Python
|
|||||||
```
|
```
|
||||||
hermes-agent/
|
hermes-agent/
|
||||||
├── run_agent.py # AIAgent class — core conversation loop
|
├── run_agent.py # AIAgent class — core conversation loop
|
||||||
├── model_tools.py # Tool orchestration, _discover_tools(), handle_function_call()
|
├── model_tools.py # Tool orchestration, discover_builtin_tools(), handle_function_call()
|
||||||
├── toolsets.py # Toolset definitions, _HERMES_CORE_TOOLS list
|
├── toolsets.py # Toolset definitions, _HERMES_CORE_TOOLS list
|
||||||
├── cli.py # HermesCLI class — interactive CLI orchestrator
|
├── cli.py # HermesCLI class — interactive CLI orchestrator
|
||||||
├── hermes_state.py # SessionDB — SQLite session store (FTS5 search)
|
├── hermes_state.py # SessionDB — SQLite session store (FTS5 search)
|
||||||
@@ -181,7 +181,7 @@ if canonical == "mycommand":
|
|||||||
|
|
||||||
## Adding New Tools
|
## Adding New Tools
|
||||||
|
|
||||||
Requires changes in **3 files**:
|
Requires changes in **2 files**:
|
||||||
|
|
||||||
**1. Create `tools/your_tool.py`:**
|
**1. Create `tools/your_tool.py`:**
|
||||||
```python
|
```python
|
||||||
@@ -204,9 +204,9 @@ registry.register(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
**2. Add import** in `model_tools.py` `_discover_tools()` list.
|
**2. Add to `toolsets.py`** — either `_HERMES_CORE_TOOLS` (all platforms) or a new toolset.
|
||||||
|
|
||||||
**3. Add to `toolsets.py`** — either `_HERMES_CORE_TOOLS` (all platforms) or a new toolset.
|
Auto-discovery: any `tools/*.py` file with a top-level `registry.register()` call is imported automatically — no manual import list to maintain.
|
||||||
|
|
||||||
The registry handles schema collection, dispatch, availability checking, and error wrapping. All handlers MUST return a JSON string.
|
The registry handles schema collection, dispatch, availability checking, and error wrapping. All handlers MUST return a JSON string.
|
||||||
|
|
||||||
|
|||||||
@@ -650,9 +650,9 @@ registry.register(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
**2. Add import** in `model_tools.py` → `_discover_tools()` list.
|
**2. Add to `toolsets.py`** → `_HERMES_CORE_TOOLS` list.
|
||||||
|
|
||||||
**3. Add to `toolsets.py`** → `_HERMES_CORE_TOOLS` list.
|
Auto-discovery: any `tools/*.py` file with a top-level `registry.register()` call is imported automatically — no manual list needed.
|
||||||
|
|
||||||
All handlers must return JSON strings. Use `get_hermes_home()` for paths, never hardcode `~/.hermes`.
|
All handlers must return JSON strings. Use `get_hermes_home()` for paths, never hardcode `~/.hermes`.
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,12 @@ Make it a **Tool** when it requires end-to-end integration with API keys, custom
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Adding a tool touches **3 files**:
|
Adding a tool touches **2 files**:
|
||||||
|
|
||||||
1. **`tools/your_tool.py`** — handler, schema, check function, `registry.register()` call
|
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)
|
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
|
|
||||||
|
Any `tools/*.py` file with a top-level `registry.register()` call is auto-discovered at startup — no manual import list required.
|
||||||
|
|
||||||
## Step 1: Create the Tool File
|
## Step 1: Create the Tool File
|
||||||
|
|
||||||
@@ -124,19 +125,9 @@ _HERMES_CORE_TOOLS = [
|
|||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step 3: Add Discovery Import
|
## ~~Step 3: Add Discovery Import~~ (No longer needed)
|
||||||
|
|
||||||
In `model_tools.py`, add the module to the `_discover_tools()` list:
|
Tool modules with a top-level `registry.register()` call are auto-discovered by `discover_builtin_tools()` in `tools/registry.py`. No manual import list to maintain — just create your file in `tools/` and it's picked up at startup.
|
||||||
|
|
||||||
```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
|
## Async Handlers
|
||||||
|
|
||||||
|
|||||||
@@ -275,4 +275,4 @@ model_tools.py (imports tools/registry + triggers tool discovery)
|
|||||||
run_agent.py, cli.py, batch_runner.py, environments/
|
run_agent.py, cli.py, batch_runner.py, environments/
|
||||||
```
|
```
|
||||||
|
|
||||||
This chain means tool registration happens at import time, before any agent instance is created. Adding a new tool requires an import in `model_tools.py`'s `_discover_tools()` list.
|
This chain means tool registration happens at import time, before any agent instance is created. Any `tools/*.py` file with a top-level `registry.register()` call is auto-discovered — no manual import list needed.
|
||||||
|
|||||||
@@ -42,37 +42,23 @@ registry.register(
|
|||||||
|
|
||||||
Each call creates a `ToolEntry` stored in the singleton `ToolRegistry._tools` dict keyed by tool name. If a name collision occurs across toolsets, a warning is logged and the later registration wins.
|
Each call creates a `ToolEntry` stored in the singleton `ToolRegistry._tools` dict keyed by tool name. If a name collision occurs across toolsets, a warning is logged and the later registration wins.
|
||||||
|
|
||||||
### Discovery: `_discover_tools()`
|
### Discovery: `discover_builtin_tools()`
|
||||||
|
|
||||||
When `model_tools.py` is imported, it calls `_discover_tools()` which imports every tool module in order:
|
When `model_tools.py` is imported, it calls `discover_builtin_tools()` from `tools/registry.py`. This function scans every `tools/*.py` file using AST parsing to find modules that contain top-level `registry.register()` calls, then imports them:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
_modules = [
|
# tools/registry.py (simplified)
|
||||||
"tools.web_tools",
|
def discover_builtin_tools(tools_dir=None):
|
||||||
"tools.terminal_tool",
|
tools_path = Path(tools_dir) if tools_dir else Path(__file__).parent
|
||||||
"tools.file_tools",
|
for path in sorted(tools_path.glob("*.py")):
|
||||||
"tools.vision_tools",
|
if path.name in {"__init__.py", "registry.py", "mcp_tool.py"}:
|
||||||
"tools.mixture_of_agents_tool",
|
continue
|
||||||
"tools.image_generation_tool",
|
if _module_registers_tools(path): # AST check for top-level registry.register()
|
||||||
"tools.skills_tool",
|
importlib.import_module(f"tools.{path.stem}")
|
||||||
"tools.skill_manager_tool",
|
|
||||||
"tools.browser_tool",
|
|
||||||
"tools.cronjob_tools",
|
|
||||||
"tools.rl_training_tool",
|
|
||||||
"tools.tts_tool",
|
|
||||||
"tools.todo_tool",
|
|
||||||
"tools.memory_tool",
|
|
||||||
"tools.session_search_tool",
|
|
||||||
"tools.clarify_tool",
|
|
||||||
"tools.code_execution_tool",
|
|
||||||
"tools.delegate_tool",
|
|
||||||
"tools.process_registry",
|
|
||||||
"tools.send_message_tool",
|
|
||||||
# "tools.honcho_tools", # Removed — Honcho is now a memory provider plugin
|
|
||||||
"tools.homeassistant_tool",
|
|
||||||
]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
This auto-discovery means new tool files are picked up automatically — no manual list to maintain. The AST check only matches top-level `registry.register()` calls (not calls inside functions), so helper modules in `tools/` are not imported.
|
||||||
|
|
||||||
Each import triggers the module's `registry.register()` calls. Errors in optional tools (e.g., missing `fal_client` for image generation) are caught and logged — they don't prevent other tools from loading.
|
Each import triggers the module's `registry.register()` calls. Errors in optional tools (e.g., missing `fal_client` for image generation) are caught and logged — they don't prevent other tools from loading.
|
||||||
|
|
||||||
After core tool discovery, MCP tools and plugin tools are also discovered:
|
After core tool discovery, MCP tools and plugin tools are also discovered:
|
||||||
|
|||||||
Reference in New Issue
Block a user