hermes-agent/website/i18n/zh-Hans/docusaurus-plugin-content-docs/current/developer-guide/adding-tools.md
Teknium b24ff550c3
docs: Plugins subcategory under Extending + secret-source plugin guide + 1Password sidebar fix (#59613)
* docs(secrets): secret-source plugin developer guide + sidebar registration for 1Password page

- New developer-guide/secret-source-plugin.md: SecretSource contract
  (never raises/prompts, fetch-only, timeout budget), framework-vs-plugin
  ownership table, mapped-vs-bulk shape guidance, run_secret_cli()
  subprocess-safety, registration + timing note, conformance kit usage,
  ErrorKind reference.
- Register user-guide/secrets/onepassword in the sidebar (page shipped
  in #59498 but was not listed, so it was unreachable from nav).
- Cross-link the user-guide plugin section to the new dev guide.

* docs: group all plugin guides under a Plugins subcategory in Extending

- Move guides/build-a-hermes-plugin.md -> developer-guide/plugins/index.md
  (both locales) and make it the category landing page (slug pinned to
  /developer-guide/plugins).
- New sidebar subcategory Developer Guide > Extending > Plugins holding
  the general guide + all 8 provider-plugin docs (llm-access, memory,
  context-engine, secret-source, model, image-gen, video-gen, web-search);
  provider-doc URLs unchanged.
- Client redirect /guides/build-a-hermes-plugin -> /developer-guide/plugins.
- Update 30 cross-links across both locales.
2026-07-06 12:11:31 -07:00

6.5 KiB
Raw Blame History

sidebar_position title description
2 添加工具 如何向 Hermes Agent 添加新工具——schema、handler、注册与 toolset

添加工具

在编写工具之前,先问自己:这是否应该是一个 skill

:::warning 仅限内置核心工具 本页面用于向仓库本身添加 Hermes 内置工具。 如果你想要个人专用、项目本地或其他自定义工具,而不修改 Hermes 核心,请使用插件方式:

大多数自定义工具创建场景默认使用插件。只有当你明确希望在 tools/toolsets.py 中发布新的内置工具时,才遵循本页面。 :::

以下情况应创建 Skill:该能力可以通过指令 + shell 命令 + 现有工具来实现(如 arXiv 搜索、git 工作流、Docker 管理、PDF 处理)。

以下情况应创建 Tool:需要与 API 密钥进行端到端集成、自定义处理逻辑、二进制数据处理或流式传输如浏览器自动化、TTS、视觉分析

概述

添加一个工具涉及 2 个文件

  1. tools/your_tool.py — handler、schema、check 函数、registry.register() 调用
  2. toolsets.py — 将工具名称添加到 _HERMES_CORE_TOOLS(或特定 toolset

任何包含顶层 registry.register() 调用的 tools/*.py 文件都会在启动时被自动发现——无需手动维护导入列表。

第一步:创建内置工具文件

每个工具文件遵循相同的结构:

# 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"],
)

关键规则

:::danger 重要

  • Handler 必须返回 JSON 字符串(通过 json.dumps()),不得返回原始 dict
  • 错误必须{"error": "message"} 形式返回,不得抛出异常
  • check_fn 在构建工具定义时被调用——若返回 False,该工具将被静默排除
  • handler 接收 (args: dict, **kwargs),其中 args 是 LLM 的工具调用参数 :::

第二步:将内置工具添加到 Toolset

toolsets.py 中添加工具名称:

# 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": []
},

第三步:添加发现导入(不再需要)

包含顶层 registry.register() 调用的工具模块会由 tools/registry.py 中的 discover_builtin_tools() 自动发现。无需手动维护导入列表——只需在 tools/ 中创建文件,启动时即可自动加载。

异步 Handler

如果你的 handler 需要异步代码,使用 is_async=True 标记:

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
)

registry 会透明地处理异步桥接——你无需自己调用 asyncio.run()

需要 task_id 的 Handler

管理每个会话状态的工具通过 **kwargs 接收 task_id

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 循环拦截工具

某些工具(todomemorysession_searchdelegate_task)需要访问每个会话的 agent 状态。这些工具在到达 registry 之前会被 run_agent.py 拦截。registry 仍然保存它们的 schema但如果绕过拦截dispatch() 会返回一个回退错误。

可选Setup Wizard 集成

如果你的工具需要 API 密钥,将其添加到 hermes_cli/config.py

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,
    },
}

检查清单

  • 已创建包含 handler、schema、check 函数和注册调用的工具文件
  • 已在 toolsets.py 中添加到适当的 toolset
  • 已确认该工具确实应为内置/核心工具而非插件
  • Handler 返回 JSON 字符串,错误以 {"error": "..."} 形式返回
  • 可选:已将 API 密钥添加到 hermes_cli/config.pyOPTIONAL_ENV_VARS
  • 可选:已添加到 toolset_distributions.py 以支持批量处理
  • 已通过 hermes chat -q "Use the weather tool for London" 测试