docs: default custom tool creation to plugins

Steers custom tool creation toward the plugin route by default.
The adding-tools.md guide is now explicitly for built-in core Hermes
tools only.

Key fixes:
- Plugin quickstart: ctx.register_tool() now uses correct keyword-arg
  API (name=, toolset=, schema=, handler=) instead of broken 3-arg call
- Handler signature: (params, **kwargs) instead of (params)
- Handler return: json.dumps({...}) instead of plain string
- AGENTS.md: mentions plugin route before built-in tool instructions
- learning-path.md: plugins listed before core tool development
- contributing.md: separates plugin vs core tool paths

Based on PR #13138 by @helix4u.
This commit is contained in:
helix4u 2026-05-04 18:22:41 +05:30 committed by kshitij
parent 74c1b946e0
commit eeb05cf556
5 changed files with 55 additions and 15 deletions

View file

@ -8,6 +8,18 @@ description: "How to add a new tool to Hermes Agent — schemas, handlers, regis
Before writing a tool, ask yourself: **should this be a [skill](creating-skills.md) instead?**
:::warning Built-in Core Tools Only
This page is for adding a **built-in Hermes tool** to the repository itself.
If you want a personal, project-local, or otherwise custom tool without
modifying Hermes core, use the plugin route instead:
- [Plugins](/docs/user-guide/features/plugins)
- [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin)
Default to plugins for most custom tool creation. Only follow this page when
you explicitly want to ship a new built-in tool in `tools/` and `toolsets.py`.
:::
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).
@ -21,7 +33,7 @@ Adding a tool touches **2 files**:
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 Built-in Tool File
Every tool file follows the same structure:
@ -106,7 +118,7 @@ registry.register(
- The `handler` receives `(args: dict, **kwargs)` where `args` is the LLM's tool call arguments
:::
## Step 2: Add to a Toolset
## Step 2: Add the Built-in Tool to a Toolset
In `toolsets.py`, add the tool name:
@ -192,6 +204,7 @@ OPTIONAL_ENV_VARS = {
- [ ] Tool file created with handler, schema, check function, and registration
- [ ] Added to appropriate toolset in `toolsets.py`
- [ ] Confirmed this really should be a built-in/core tool and not a plugin
- [ ] 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

View file

@ -22,7 +22,8 @@ We value contributions in this order:
## Common contribution paths
- Building a new tool? Start with [Adding Tools](./adding-tools.md)
- Building a custom/local tool without modifying Hermes core? Start with [Build a Hermes Plugin](../guides/build-a-hermes-plugin.md)
- Building a new built-in core tool for Hermes itself? Start with [Adding Tools](./adding-tools.md)
- Building a new skill? Start with [Creating Skills](./creating-skills.md)
- Building a new inference provider? Start with [Adding Providers](./adding-providers.md)

View file

@ -80,15 +80,18 @@ Cron jobs let Hermes Agent run tasks on a schedule — daily summaries, periodic
Extend Hermes Agent with your own tools and reusable skill packages.
1. [Tools Overview](/docs/user-guide/features/tools)
2. [Skills Overview](/docs/user-guide/features/skills)
3. [MCP (Model Context Protocol)](/docs/user-guide/features/mcp)
4. [Architecture](/docs/developer-guide/architecture)
5. [Adding Tools](/docs/developer-guide/adding-tools)
6. [Creating Skills](/docs/developer-guide/creating-skills)
1. [Plugins](/docs/user-guide/features/plugins)
2. [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin)
3. [Tools Overview](/docs/user-guide/features/tools)
4. [Skills Overview](/docs/user-guide/features/skills)
5. [MCP (Model Context Protocol)](/docs/user-guide/features/mcp)
6. [Architecture](/docs/developer-guide/architecture)
7. [Adding Tools](/docs/developer-guide/adding-tools)
8. [Creating Skills](/docs/developer-guide/creating-skills)
:::tip
Tools are individual functions the agent can call. Skills are bundles of tools, prompts, and configuration packaged together. Start with tools, graduate to skills.
For most custom tool creation, start with plugins. The [Adding Tools](/docs/developer-guide/adding-tools)
page is for built-in Hermes core development, not the usual user/custom-tool path.
:::
### "I want to train models"

View file

@ -9,6 +9,11 @@ description: "Extend Hermes with custom tools, hooks, and integrations via the p
Hermes has a plugin system for adding custom tools, hooks, and integrations without modifying core code.
If you want to create a custom tool for yourself, your team, or one project,
this is usually the right path. The developer guide's
[Adding Tools](/docs/developer-guide/adding-tools) page is for built-in Hermes
core tools that live in `tools/` and `toolsets.py`.
**→ [Build a Hermes Plugin](/docs/guides/build-a-hermes-plugin)** — step-by-step guide with a complete working example.
## Quick overview
@ -42,6 +47,8 @@ description: A minimal example plugin
```python
"""Minimal Hermes plugin — registers a tool and a hook."""
import json
def register(ctx):
# --- Tool: hello_world ---
@ -60,11 +67,18 @@ def register(ctx):
},
}
def handle_hello(params):
def handle_hello(params, **kwargs):
del kwargs
name = params.get("name", "World")
return f"Hello, {name}! 👋 (from the hello-world plugin)"
return json.dumps({"success": True, "greeting": f"Hello, {name}!"})
ctx.register_tool("hello_world", schema, handle_hello)
ctx.register_tool(
name="hello_world",
toolset="hello_world",
schema=schema,
handler=handle_hello,
description="Return a friendly greeting for the given name.",
)
# --- Hook: log every tool call ---
def on_tool_call(tool_name, params, result):
@ -81,7 +95,7 @@ Project-local plugins under `./.hermes/plugins/` are disabled by default. Enable
| Capability | How |
|-----------|-----|
| Add tools | `ctx.register_tool(name, schema, handler)` |
| Add tools | `ctx.register_tool(name=..., toolset=..., schema=..., handler=...)` |
| Add hooks | `ctx.register_hook("post_tool_call", callback)` |
| Add slash commands | `ctx.register_command(name, handler, description)` — adds `/name` in CLI and gateway sessions |
| Add CLI commands | `ctx.register_cli_command(name, help, setup_fn, handler_fn)` — adds `hermes <plugin> <subcommand>` |