
Hermes Agent
- 552 installs
- Updated April 12, 2026
- wihy/hermes-agent-skill
hermes-agent is a Claude Code skill that invokes NousResearch Hermes Agent for developers who need delegated sub-agents with durable memory, MCP access, browser work, and sandboxed code execution.
About
hermes-agent is a Claude Code skill that bridges your primary coding agent to NousResearch Hermes Agent for task delegation beyond a single session's limits. Hermes Agent adds durable memory, dynamic skill creation, MCP server integration, browser automation, and sandboxed code runs as a secondary agent layer. Developers reach for hermes-agent when a coding task needs persistent context across delegations, external tool access through MCP, or isolated execution environments the parent agent cannot safely provide. The skill packages Hermes invocation patterns so the main agent can offload research, browsing, and multi-step workflows without reimplementing agent orchestration.
- CLI integration for hermes run, delegate, memory, and skills workflows
- Self-improving skill system that materializes reusable skills from completed tasks
- Persistent memory with FTS5 search plus LLM summarization
- Sub-agent delegation for isolated or parallel tasks
- Bidirectional MCP, browser automation, code execution, and web research in one runtime
Hermes Agent by the numbers
- 552 all-time installs (skills.sh)
- +4 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #1,669 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 27, 2026 (Skillselion catalog sync)
npx skills add https://github.com/wihy/hermes-agent-skill --skill hermes-agentAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 552 |
|---|---|
| Security audit | 1 / 3 scanners passed |
| Last updated | April 12, 2026 |
| Repository | wihy/hermes-agent-skill ↗ |
How do you delegate tasks to Hermes Agent?
Invoke NousResearch Hermes Agent from your coding agent for delegation, durable memory, skill creation, MCP, browser work, and sandboxed code runs.
Who is it for?
Claude Code users who need NousResearch Hermes Agent for delegation, durable memory, MCP tools, browser work, or sandboxed runs.
Skip if: Simple single-shot coding edits that the primary agent can complete without sub-agent delegation or persistent memory.
When should I use this skill?
The user needs Hermes Agent for delegation, durable memory, skill creation, MCP integration, browser automation, or sandboxed execution.
What you get
Hermes Agent delegations, durable memory updates, MCP-connected tool runs, browser session results, and sandboxed execution outputs.
- Delegated agent task results
- Persistent memory artifacts
- Browser and sandbox execution outputs
Files
Hermes Agent Skill v2.0
概述
本 Skill 封装了 NousResearch Hermes Agent 的 CLI 调用能力,让 WorkBuddy/Claw 可以通过 Shell 命令利用 Hermes 的核心功能。
v2.0 改进:完全可移植,无硬编码路径,支持任意实例一键安装。
---
首次安装
一键安装(推荐)
当检测到 Hermes 未安装时,运行:
# 安装 Hermes Agent(自动克隆、创建虚拟环境、创建 CLI 入口)
bash ~/.workbuddy/skills/hermes-agent/scripts/install_hermes.sh
# 或自定义安装目录
bash ~/.workbuddy/skills/hermes-agent/scripts/install_hermes.sh --prefix ~/custom/path安装脚本会自动: 1. ✅ 检测 Python 3.11+ 环境 2. ✅ 克隆 Hermes Agent 源码 3. ✅ 创建 Python 虚拟环境并安装依赖 4. ✅ 创建 ~/.local/bin/hermes CLI 入口 5. ✅ 初始化 ~/.hermes/ 配置目录 6. ✅ 生成默认 .env 配置模板
安装后配置 API Key
# 编辑配置文件,填入你的 API Key
nano ~/.hermes/.env可选提供商(任选其一):
# 智谱 AI(推荐国内用户)
GLM_API_KEY=your-key-here
# OpenRouter(支持多种模型)
OPENROUTER_API_KEY=sk-or-v1-your-key-here
# Anthropic
ANTHROPIC_API_KEY=sk-ant-your-key-here
# OpenAI
OPENAI_API_KEY=sk-your-key-here验证安装
# 确认 PATH 包含 hermes
export PATH="$HOME/.local/bin:$PATH"
hermes --version
# 运行诊断
hermes doctor---
迁移到其他 Claw 实例
将整个 Skill 目录复制到目标实例即可:
# 在目标实例上执行:
cp -r /path/to/hermes-agent ~/.workbuddy/skills/hermes-agent
bash ~/.workbuddy/skills/hermes-agent/scripts/install_hermes.sh
# 然后配置 API Key---
核心工作流
1. 调用模式速查
| 场景 | 命令 | 说明 |
|---|---|---|
| 快速问答 | hermes run "问题" --non-interactive --no-stream | 最简调用 |
| 带上下文 | hermes run "问题" --context-file ./ctx.md --non-interactive | 注入项目上下文 |
| 子代理委托 | 使用 scripts/hermes_delegate.sh | 复杂任务分解 |
| 技能查询 | hermes skills list | 查看已学技能 |
| 记忆搜索 | hermes memory search "关键词" | 检索历史知识 |
| 状态检查 | hermes status 或 hermes doctor | 诊断安装状态 |
2. CLI 命令完整参考
基础命令
# 启动交互式对话
hermes
# 单轮执行(WorkBuddy 集成首选)
hermes run "prompt" [选项]
# 非交互模式选项
--non-interactive # 关闭交互式 TUI(必需)
--no-stream # 禁用流式输出,返回完整结果
--context-file PATH # 注入上下文文件
--toolset NAME # 限制使用的工具集
--model MODEL # 指定模型
--timeout SECONDS # 超时时间(默认300秒)子代理委托
# 通过 wrapper 脚本调用(推荐)
./scripts/hermes_delegate.sh \
--task "分析竞品A和B的产品特性" \
--tools "web_search,browser,file_write" \
--timeout 300 \
--output ./result.md
# 直接在 hermes run 中使用 delegate_task 工具
hermes run '使用delegate_task工具,任务是:分析XXX,工具限制:web_search,browser' \
--non-interactive --no-stream记忆管理
# 搜索历史记忆
hermes memory search "关键词"
# 查看所有笔记
hermes memory notes list
# 添加手动笔记
hermes memory notes add "重要发现:..."
# 导出/导入记忆
hermes memory export ./backup/
hermes memory import ./backup/技能管理
hermes skills list # 列出所有技能
hermes skills create my-skill --description "描述" # 创建新技能
hermes skills edit my-skill # 编辑技能
hermes skills remove my-skill # 删除技能插件管理
hermes plugins list # 列出插件
hermes plugins install user/repo # 安装插件
hermes plugins enable/disable/update/remove plugin-name定时任务 (Cron)
hermes cron list # 列出定时任务
hermes cron add --name "日报" --cron "0 9 * * *" --message "生成总结"
hermes cron pause/resume/remove TASK_IDMCP 集成
hermes mcp serve --port 8080 # 启动 MCP Server
hermes mcp connect <server-config> # 连接外部 MCP 服务---
Wrapper 脚本
scripts/hermes_wrapper.sh
统一的 CLI 封装脚本,提供 JSON 格式化输出和错误处理:
./scripts/hermes_wrapper.sh [命令] [参数...]
# 示例
./scripts/hermes_wrapper.sh run "分析内容" --timeout 60
./scripts/hermes_wrapper.sh memory search "关键词"
./scripts/hermes_wrapper.sh status输出格式:JSON(包含 success, output, error, duration_ms 字段)
scripts/hermes_delegate.sh
子代理委托专用脚本:
./scripts/hermes_delegate.sh --task "任务描述" [选项]
# 可选选项
--tools "tool1,tool2" # 限制可用工具集
--timeout 300 # 超时时间(秒)
--output ./result.md # 输出文件路径
--max-concurrent 3 # 最大并发数(默认3)
--context-file ./ctx.md # 额外上下文文件
-v # 详细输出scripts/install_hermes.sh
一键安装脚本(详见上方「首次安装」章节):
bash scripts/install_hermes.sh [--skip-deps] [--prefix DIR]---
模型配置
运行交互式配置向导:
hermes model或直接编辑 ~/.hermes/config.yaml:
model:
provider: zai # 可选: openrouter, anthropic, openai, zai, gemini 等
default: "glm-5" # 默认模型
base_url: "https://api.z.ai/api/paas/v4" # 自定义 API 地址支持的提供商:openrouter, anthropic, openai, gemini, zai, kimi-coding, nous, custom
---
最佳实践
✅ 推荐做法
1. 始终使用 `--non-interactive --no-stream`:避免 TUI 阻塞 2. 设置合理的超时时间:简单任务 60s,复杂任务 300s 3. 限制工具集:用 --toolset 减少 Token 消耗 4. 使用上下文文件:将大段背景信息放入文件,而非 prompt 中 5. 错误重试机制:网络问题时自动重试 1-2 次
⚠️ 注意事项
1. Token 成本:每次调用都有成本 2. 并发限制:最多 3 个并发子代理 3. 超时保护:长时间运行的任务必须设置 timeout 4. API Key 安全:不要在 Skill 文件中硬编码密钥 5. Python 版本:确保使用 Python 3.11+
---
故障排除
| 问题 | 解决方案 |
|---|---|
command not found: hermes | 运行 export PATH="$HOME/.local/bin:$PATH" 或重新执行 install_hermes.sh |
TypeError: unsupported operand | 确保 Python 3.11+ |
| API Key 错误 | 检查 ~/.hermes/.env 配置 |
| 连接超时 | 检查网络,或更换 LLM 提供商 |
| 子代理失败 | 减少 --max-concurrent 或增加 --timeout |
| 安装脚本失败 | 运行 hermes doctor 诊断 |
---
文件结构
hermes-agent/
├── SKILL.md # 本文件(Skill 说明文档)
├── _meta.json # Skill 元数据(可移植性声明)
├── scripts/
│ ├── install_hermes.sh # 一键安装脚本(通用)
│ ├── hermes_wrapper.sh # 统一 CLI 封装(动态路径检测)
│ └── hermes_delegate.sh # 子代理委托脚本(动态路径检测)
└── references/ # 参考文档---
更新日志
- v2.0.0 (2026-04-12): 完全可移植版 — 移除所有硬编码路径,添加一键安装脚本,支持任意 Claw 实例迁移
- v1.0.0 (2026-04-11): 初始版本,支持基础 CLI 调用、子代理委托、记忆/技能管理
{
"name": "hermes-agent",
"version": "2.0.0",
"description": "NousResearch Hermes Agent 通用集成 Skill - 通过 CLI 调用 Hermes Agent 的核心能力(自改进技能、持久化记忆、子代理委托、MCP集成等)。支持一键安装,可在任意 WorkBuddy/Claw 实例间迁移。",
"author": "WorkBuddy AI",
"keywords": ["hermes", "agent", "ai", "nousresearch", "self-improving", "memory", "delegation", "mcp", "portable"],
"triggers": ["hermes", "使用 hermes", "调用 hermes", "hermes agent", "子代理委托", "技能学习", "记忆查询", "hermes run", "hermes delegate", "hermes memory", "hermes skills", "安装 hermes"],
"category": "ai-agents",
"permissions": {
"files": ["read", "write"],
"network": ["hermes-cli", "llm-providers", "github.com"],
"commands": ["bash"]
},
"dependencies": {
"required": [
{
"name": "hermes-cli",
"check": "command -v hermes && hermes --version || echo NOT_INSTALLED",
"install": "bash scripts/install_hermes.sh",
"install_docs": "运行 Skill 目录下的 scripts/install_hermes.sh 即可一键安装"
}
],
"optional": [
{
"name": "jq",
"check": "command -v jq || echo NOT_INSTALLED",
"purpose": "JSON 输出格式化(可选,脚本有 fallback)"
},
{
"name": "ripgrep",
"check": "command -v rg || echo NOT_INSTALLED",
"purpose": "更快的文件搜索(可选,Hermes 会 fallback 到 grep)"
}
]
},
"config": {
"config_dir": "~/.hermes",
"cli_entry": "~/.local/bin/hermes",
"default_timeout": 300,
"max_concurrent_delegates": 3,
"install_script": "scripts/install_hermes.sh",
"supported_providers": [
"openrouter",
"anthropic",
"openai",
"gemini",
"zai",
"kimi-coding",
"nous",
"custom"
]
},
"portability": {
"type": "full",
"description": "完全可移植。包含一键安装脚本,任意 Claw 实例加载此 Skill 后运行 install_hermes.sh 即可使用。",
"migration_steps": [
"1. 将整个 hermes-agent Skill 目录复制到目标实例的 ~/.workbuddy/skills/",
"2. 运行 scripts/install_hermes.sh 安装 Hermes CLI",
"3. 配置 ~/.hermes/.env 添加 API Key",
"4. 运行 hermes doctor 验证安装"
]
},
"created_at": "2026-04-11T20:46:00Z",
"updated_at": "2026-04-12T00:35:00Z"
}
MIT No Attribution (MIT-0)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Hermes Agent Skill 🏥
通用可移植的 Hermes Agent 集成 Skill,适用于 WorkBuddy / Claude Code / Cursor 等 AI Agent 平台。
![Version]() ![License]() ![Hermes]()
✨ 功能特性
- 🚀 自改进技能系统 — 从任务中自动创建可复用技能
- 🧠 持久化记忆 — FTS5 全文搜索 + LLM 摘要
- 🤖 子代理委托 — 任务隔离和并行处理
- 🔌 MCP 双向集成 — Model Context Protocol 支持
- 🌐 浏览器自动化 — Web 页面交互
- 💻 代码执行 — 沙盒内安全执行
- 🔍 网页研究 — 信息检索与分析
📦 安装
方式一:一键安装(推荐)
npx skills add chunhaixu/hermes-agent-skill@hermes-agent -g -y方式二:手动安装
# 1. 克隆仓库
git clone https://github.com/chunhaixu/hermes-agent-skill.git
# 2. 复制到 Skill 目录
cp -r hermes-agent-skill ~/.workbuddy/skills/hermes-agent
# 3. 运行安装脚本
bash ~/.workbuddy/skills/hermes-agent/scripts/install_hermes.sh
# 4. 配置 API Key
nano ~/.hermes/.env⚙️ 配置
API Key 配置
编辑 ~/.hermes/.env,添加你的 LLM 提供商密钥:
# 智谱 AI(推荐)
GLM_API_KEY=your_key_here
# 或 OpenRouter
OPENROUTER_API_KEY=your_key_here
# 或 Anthropic
ANTHROPIC_API_KEY=your_key_here模型配置
编辑 ~/.hermes/config.yaml:
model:
default: "glm-5" # 默认模型
provider: "zai" # 提供商: zai / openrouter / anthropic / ...
base_url: "https://api.z.ai/api/paas/v4"🔧 使用
安装后,在 AI Agent 中使用以下触发词:
| 触发词 | 说明 |
|---|---|
使用 hermes | 激活 Hermes Agent |
hermes run "任务" | 执行单轮任务 |
hermes memory search "关键词" | 搜索记忆 |
hermes delegate "复杂任务" | 子代理委托 |
hermes skills list | 查看已学技能 |
🏗️ 项目结构
hermes-agent-skill/
├── SKILL.md # Skill 描述文件(Agent 自动加载)
├── _meta.json # 元数据(版本、依赖、触发词等)
├── scripts/
│ ├── install_hermes.sh # 一键安装脚本
│ ├── hermes_wrapper.sh # CLI 统一封装
│ └── hermes_delegate.sh # 子代理委托脚本
└── references/
├── cli-commands.md # CLI 命令参考
├── config-guide.md # 配置指南
├── mcp-integration.md # MCP 集成
├── plugin-development.md # 插件开发
└── self-improving-integration.md # 自改进系统🔗 相关链接
📄 License
MIT License
Hermes Agent CLI 完整命令手册
版本: v0.8.0 | 最后更新: 2026-04-11
目录
1. 基础命令 2. 执行模式 3. 工具管理 4. 记忆系统 5. 技能管理 6. 插件系统 7. 消息网关 8. 定时任务 9. MCP 集成 10. 诊断与调试
---
基础命令
启动交互式会话
hermes启动 TUI(终端用户界面)交互式对话。
快捷键:
Ctrl+C- 中断当前生成Ctrl+D- 退出Tab- 自动补全↑/↓- 历史记录
查看版本信息
hermes --version
hermes -v
# 输出示例:
# Hermes Agent v0.8.0 (2026.4.8)
# Project: /path/to/hermes-agent
# Python: 3.11.15
# OpenAI SDK: 2.31.0显示帮助信息
hermes --help
hermes help <command>---
执行模式
单轮执行 (run)
hermes run "你的提示词" [选项]核心选项:
| 选项 | 简写 | 默认值 | 说明 |
|---|---|---|---|
--non-interactive | 无 | false | 关闭 TUI,适合脚本调用 |
--no-stream | 无 | false | 禁用流式输出,返回完整结果 |
--context-file | -c | null | 注入上下文文件路径 |
--toolset | -t | null | 限制使用的工具集名称 |
--model | -m | 配置默认值 | 指定模型(覆盖配置) |
--provider | 无 | 配置默认值 | 指定 LLM 提供商 |
--timeout | 无 | 300 | 超时时间(秒) |
--max-tokens | 无 | 配置默认值 | 最大输出 Token 数 |
--temperature | 无 | 配置默认值 | 温度参数 (0.0-2.0) |
使用示例:
# 最简单的单轮调用
hermes run "什么是机器学习?" --non-interactive --no-stream
# 带上下文文件
hermes run "分析这个项目的架构" \
--context-file ./AGENTS.md \
--non-interactive --no-stream
# 限制工具集
hermes run "搜索最新的 React 文档" \
--toolset web_search \
--non-interactive --no-stream
# 指定模型和超时
hermes run "写一个排序算法" \
--model gpt-4o \
--temperature 0.2 \
--timeout 60 \
--non-interactive --no-stream---
工具管理
列出所有可用工具
hermes tools list
hermes tools list --all # 包括未启用的启用/禁用工具集
# 列出可用工具集
hermes toolsets
# 启用特定工具集
hermes tools enable web_search browser file_operations
# 禁用特定工具集
hermes tools disable code_execution terminal内置工具列表
| 工具集 | 包含工具 | 用途 |
|---|---|---|
web_search | search_web, firecrawl_scrape, brave_search, searxng_search | 网页搜索和抓取 |
browser | browser_navigate, browser_click, browser_type, browser_screenshot, browser_extract | 浏览器自动化 |
file_operations | read_file, write_file, edit_file, glob_files, list_directory | 文件读写操作 |
terminal | execute_command, bash, shell | 终端命令执行 |
memory | memory_search, memory_add_note, memory_list_notes | 记忆系统访问 |
code_execution | execute_code | 代码执行沙盒 |
delegation | delegate_task | 子代理委托 |
skills | skills_list, skills_create, skills_edit, skills_remove | 技能管理 |
image_generation | generate_image, upscale_image | AI 图像生成 |
voice | text_to_speech, transcribe_audio | 语音合成与识别 |
---
记忆系统
搜索记忆
hermes memory search "关键词"
hermes memory search "用户偏好设置" --limit 10笔记管理
# 列出所有笔记
hermes memory notes list
# 添加新笔记
hermes memory notes add "重要发现:XXX"
# 搜索笔记内容
hermes memory notes search "查询内容"导入导出
# 导出所有记忆数据
hermes memory export ./backup/
# 从备份导入
hermes memory import ./backup/记忆后端切换
# 查看当前记忆后端
hermes memory status
# 切换到 Honcho 后端
hermes memory setup honcho
# 使用内置后端
hermes memory setup built-in支持的记忆后端:
| 后端 | 特点 |
|---|---|
built-in | 默认,SQLite + FTS5 全文搜索 |
honcho | AI 原生记忆,方言建模 |
mem0 | 开源记忆服务 |
openviking | 高级向量检索 |
hindsight | 时间线记忆 |
holographic | 全息记忆系统 |
retaindb | 企业级记忆存储 |
byte-rover | 轻量级本地记忆 |
---
技能管理
列出技能
hermes skills list
hermes skills ls # 短形式
# 查看技能详情
hermes skills show skill-name创建技能
# 交互式创建
hermes skills create my-skill
# 带描述创建
hermes skills create research-methodology \
--description "系统性网页研究方法论"
# 从模板创建
hermes skills create code-review --template default编辑技能
hermes skills edit my-skill
# 打开默认编辑器编辑技能 Markdown 文件删除技能
hermes skills remove my-skill
hermes skills rm old-skill # 短形式技能格式规范
每个技能是一个 Markdown 文件,位于 ~/.hermes/skills/<skill-name>/skill.md:
---
name: my-skill
description: 技能描述
triggers:
- "触发词1"
- "触发词2"
tags:
- category1
- category2
---
# 技能名称
## 步骤
1. 第一步说明
2. 第二步说明
## 最佳实践
- 注意事项
- 推荐做法---
插件系统
插件管理
# 列出已安装插件
hermes plugins list
hermes plugins ls
# 安装插件(从 Git)
hermes plugins install owner/repo
hermes plugins install https://github.com/owner/repo.git
# 更新插件
hermes plugins update plugin-name
hermes plugins update --all # 更新所有
# 卸载插件
hermes plugins remove plugin-name
hermes plugins rm plugin-name
# 启用/禁用插件(保留安装但不加载)
hermes plugins enable plugin-name
hermes plugins disable plugin-name插件类型
# 列出通用插件
hermes plugins list --type general
# 列出内存提供者
hermes plugins list --type memory
# 列出上下文引擎
hermes plugins list --type context_engine插件开发
详见 plugin-development.md
---
消息网关
网关管理
# 设置向导
hermes gateway setup
# 列出已配置的网关
hermes gateway list
# 安装特定平台网关
hermes gateway install telegram
hermes gateway install discord
hermes gateway install slack
# 启动所有网关
hermes gateway start
# 停止所有网关
hermes gateway stop
# 重启特定网关
hermes gateway restart discord支持的消息平台
| 平台 | 网关名称 | 功能 |
|---|---|---|
| Telegram | telegram | 完整支持(文字、语音、群组) |
| Discord | discord | 完整支持(含语音频道) |
| Slack | slack | 支持 |
whatsapp | 支持 | |
| Signal | signal | 支持 |
| Matrix | matrix | 支持 |
| Mattermost | mattermost | 支持 |
email | 支持 | |
| SMS | sms | 支持 |
| DingTalk (钉钉) | dingtalk | 支持 |
| Feishu (飞书) | feishu | 支持 |
| WeCom (企业微信) | wecom | 支持 |
| Home Assistant | homeassistant | 支持 |
---
定时任务 (Cron)
任务管理
# 列出所有任务
hermes cron list
# 创建任务
hermes cron add \
--name "每日新闻摘要" \
--cron "0 9 * * *" \ # 每天 9:00
--message "总结今日科技新闻" \
--skill daily-news # 可附加技能
# 暂停任务
hermes cron pause TASK_ID 或 任务名
# 恢复任务
hermes cron resume TASK_ID 或 任务名
# 编辑任务
hermes cron edit TASK_ID
# 删除任务
hermes cron remove TASK_ID
hermes cron rm TASK_ID # 短形式
# 手动触发任务
hermes cron run TASK_IDCron 表达式语法
┌───────────── 分钟 (0-59)
│ ┌───────────── 小时 (0-23)
│ │ ┌───────────── 月中天 (1-31)
│ │ │ ┌───────────── 月 (1-12)
│ │ │ │ ┌───────────── 周中天 (0-6, 0=周日)
│ │ │ │ │
* * * * *示例:
| 表达式 | 含义 |
|---|---|
* * * * * | 每分钟 |
*/15 * * * * | 每15分钟 |
0 * * * * | 每小时 |
0 9 * * * | 每天 9:00 |
0 9 * * 1 | 每周一 9:00 |
0 9 1 * * | 每月1号 9:00 |
0 9-17 * * 1-5 | 工作日 9:00-17:00 每小时 |
---
MCP 集成
Server 模式(暴露能力给 IDE)
# 启动 MCP Server
hermes mcp serve --port 8080
hermes mcp serve --stdio # 标准输入输出模式
# 配置 MCP Server
hermes mcp serve-config # 生成 IDE 配置片段Client 模式(连接外部服务)
# 连接外部 MCP 服务器
hermes mcp connect <server-config-json>
# 列出已连接的 MCP 服务
hermes mcp list
# 断开连接
hermes mcp disconnect <server-id>详见 mcp-integration.md
---
诊断与调试
状态检查
# 快速状态概览
hermes status
# 详细诊断
hermes doctor日志查看
# 实时查看日志
hermes logs --follow
hermes logs -f
# 查看最近N行
hermes logs -n 100
# 过滤日志级别
hermes logs --level ERROR
hermes logs --level WARNING
# 查看特定会话的日志
hermes logs --session SESSION_ID性能分析
# 查看最近的性能指标
hermes stats
# 查看Token使用统计
hermes stats tokens
# 查看任务耗时统计
hermes stats timing重置与清理
# 清理缓存
hermes cleanup cache
# 清理旧会话(超过N天的)
hermes cleanup sessions --older-than 30
# 重置为出厂设置(⚠️ 会删除所有数据和配置)
hermes reset --factory---
环境变量
| 变量名 | 说明 | 默认值 |
|---|---|---|
HERMES_HOME | Hermes 数据目录 | ~/.hermes |
HERMES_CONFIG | 自定义配置文件路径 | ~/.hermes/config.yaml |
HERMES_ENV_FILE | 自定义环境变量文件 | ~/.hermes/.env |
HERMES_LOG_LEVEL | 日志级别 | INFO |
HERMES_NO_COLOR | 禁用彩色输出 | false |
HERMES_ENABLE_PROJECT_PLUGINS | 启用项目级插件 | false |
HERMES_OPTIONAL_SKILLS | 自定义可选技能目录 | null |
---
退出码
| 退出码 | 含义 |
|---|---|
| 0 | 成功 |
| 1 | 一般错误 |
| 2 | 参数错误 |
| 3 | 配置错误 |
| 4 | 网络错误 |
| 5 | API 认证失败 |
| 124 | 超时(来自 timeout 命令) |
| 130 | 用户中断 (Ctrl+C) |
Hermes Agent 配置指南
版本: v0.8.0 | 最后更新: 2026-04-11
目录
1. API Key 配置 2. 模型配置 3. 提供商设置 4. 工具集配置 5. 记忆系统配置 6. 网关配置 7. 安全配置 8. 完整配置示例
---
API Key 配置
环境变量文件 (~/.hermes/.env)
这是存储所有敏感凭证的主要位置。不要将此文件提交到版本控制系统!
# ========================================
# 必需:至少配置一个 LLM 提供商
# ========================================
# OpenRouter(推荐,支持 200+ 模型)
OPENROUTER_API_KEY=sk-or-v1-your-key-here
# 或使用其他提供商:
# Anthropic (Claude)
ANTHROPIC_API_KEY=sk-ant-your-key-here
# OpenAI (GPT-4o, etc.)
OPENAI_API_KEY=sk-openai-your-key-here
# Google (Gemini)
GOOGLE_API_KEY=your-google-api-key
# ========================================
# 可选:增强功能
# ========================================
# Firecrawl - 高级网页抓取(比内置搜索更强大)
FIRECRAWL_API_KEY=fc-your-firecrawl-key
# FAL.ai - 图像生成(FLUX 模型)
FAL_KEY=your-fal-api-key
# ElevenLabs - 高级语音合成(替代免费的 Edge TTS)
ELEVENLABS_API_KEY=your-elevenlabs-key
# Brave Search - 网页搜索
BRAVE_API_KEY=your-brave-search-key
# OpenWeatherMap - 天气查询
OPENWEATHERMAP_API_KEY=your-weather-key
# GitHub Token - 用于 GitHub 集成
GITHUB_TOKEN=ghp_your-github-token
# ========================================
# 可选:消息平台
# ========================================
# Telegram Bot
TELEGRAM_BOT_TOKEN=your-telegram-bot-token
# Discord Bot
DISCORD_BOT_TOKEN=your-discord-bot-token
# Slack Bot
SLACK_BOT_TOKEN=xoxb-your-slack-bot-token
SLACK_APP_TOKEN=xapp-your-slack-app-token
# WhatsApp Bridge (需要单独配置)
# 参考文档: https://hermes-agent.nousresearch.com/docs/gateways/whatsapp/获取 API Key 的途径
| 服务 | 获取地址 | 免费额度 |
|---|---|---|
| OpenRouter | https://openrouter.ai/keys | 注册即送少量额度 |
| Anthropic | https://console.anthropic.com/ | 新用户 $5 免费 |
| OpenAI | https://platform.openai.com/api-keys | 新用户 $5 免费 |
| Google AI | https://aistudio.google.com/apikey | 免费层可用 |
| Firecrawl | https://www.firecrawl.dev/account | 500 次免费抓取 |
| FAL.ai | https://fal.ai/dashboard/keys | 每日免费额度 |
| ElevenLabs | https://elevenlabs.io/app/settings/api-keys | 每月 10k 字符免费 |
| Brave Search | https://brave.com/search/api/ | 每月 2k 次免费 |
---
模型配置
通过 CLI 选择模型
# 启动交互式模型选择向导
hermes model通过配置文件指定模型
编辑 ~/.hermes/config.yaml:
model:
# LLM 提供商
provider: openrouter
# 模型名称
# OpenRouter 格式: <provider>/<model-name>
model: anthropic/claude-sonnet-4-20250514
# 或直接使用提供商原生名称:
# model: claude-3-5-sonnet-20241022 # Anthropic 直接调用
# model: gpt-4o # OpenAI 直接调用
# 温度参数 (0.0 = 确定性, 2.0 = 最大随机性)
temperature: 0.7
# 最大输出 token 数
max_tokens: 4096
# Top P 采样参数
top_p: 1.0
# 是否启用流式输出
streaming: true推荐模型选择
性价比优先
| 模型 | 成本 ($/1M tokens) | 特点 |
|---|---|---|
openrouter/google/gemini-flash-1.5 | ~$0.07 | 最便宜,速度快 |
openrouter/meta-llama/llama-3.1-8b-instruct:free | 免费 | 开源,适合简单任务 |
anthropic/claude-haiku-4-5-20251001 | ~$0.80 | 快速,质量好 |
质量优先
| 模型 | 成本 ($/1M tokens) | 特点 |
|---|---|---|
anthropic/claude-sonnet-4-20250514 | ~$3.00 | 平衡质量和成本 |
openai/gpt-4o | ~$2.50 | 多模态能力强 |
google/gemini-2.5-pro | ~$6.25 | 推理能力强,长上下文 |
专业用途
| 用途 | 推荐模型 | 原因 |
|---|---|---|
| 代码生成 | anthropic/claude-sonnet-4-20250514 | 代码能力优秀 |
| 网页研究 | google/gemini-2.5-pro | 大上下文窗口 |
| 创意写作 | openai/gpt-4o | 文学风格多样 |
| 快速问答 | anthropic/claude-haiku-4-5-20251001 | 响应快,成本低 |
| 数据分析 | openai/o4-mini | 推理能力强 |
---
提供商设置
OpenRouter(推荐)
providers:
openrouter:
base_url: "https://openrouter.ai/api/v1"
api_key_env: OPENROUTER_API_KEY # 从 .env 读取
models:
default: "anthropic/claude-sonnet-4-20250514"
# 高级选项
timeout: 120 # 请求超时(秒)
max_retries: 3 # 重试次数
# HTTP Headers(可选)
extra_headers:
X-Title: "Hermes Agent"
HTTP-Referer: "http://localhost:8080"Anthropic 直接连接
providers:
anthropic:
api_key_env: ANTHROPIC_API_KEY
models:
default: "claude-sonnet-4-20250514"
base_url: "https://api.anthropic.com"OpenAI 直接连接
providers:
openai:
api_key_env: OPENAI_API_KEY
models:
default: "gpt-4o"
base_url: "https://api.openai.com/v1"Ollama(本地模型,零成本)
providers:
ollama:
base_url: "http://localhost:11434/v1"
models:
default: "llama3.1:8b" # 需先运行 ollama pull llama3.1:8b
api_key: "ollama" # Ollama 不需要真实 API Key
# 无需 API Key,完全离线运行---
工具集配置
启用/禁用工具集
tools:
# 全局默认启用状态
enabled_by_default: true
# 工具集定义
toolsets:
web_search:
enabled: true
tools:
- search_web
- firecrawl_scrape
browser:
enabled: true
backend: local_chrome # browserbase_cloud | browser_use_cloud | local_chrome | local_chromium
file_operations:
allowed_paths:
- /Users/chunhaixu/Projects
- /tmp
- ~/Documents
denied_paths:
- ~/.ssh
- ~/.gnupg
- /etc
terminal:
allowed_commands:
- git
- npm
- python
- cat
- ls
- grep
- find
denied_commands:
- rm -rf /
- sudo
- chmod 777
memory:
enabled: true
backend: built-in # built-in | honcho | mem0 | ...
code_execution:
enabled: true
sandbox: docker # docker | subprocess
delegation:
enabled: true
max_concurrent: 3 # 最大并发子代理数
default_timeout: 300 # 默认超时(秒)
image_generation:
enabled: false # 需要 FAL_KEY
provider: fal # fal | ...
model: flux-2-pro
upscale: true # 自动 2x 放大
voice:
enabled: true
tts_provider: edge_tts # edge_tts | elevenlabs | openai_tts | minimax | neutts
stt_provider: whisper # whisper | groq_whisper---
记忆系统配置
memory:
# 后端选择
provider: built-in # built-in | honcho | mem0 | openviking | hindsight | holographic | retaindb | byte-rover
# 内置后端特定配置
built_in:
storage_path: ~/.hermes/memory
fts_enabled: true # 启用全文搜索
max_notes: 10000 # 最大笔记数
auto_summarize: true # 自动摘要旧会话
summary_model: haiku # 用于摘要的模型
# Honcho 后端(如果使用)
honcho:
project_id: your-project-id
dialect_name: user-profile # 用户方言文件名
# 记忆保留策略
retention:
hot_memory_days: 7 # 热记忆保留天数
session_history_days: 30 # 会话历史保留天数
cold_storage_after: 90 # 天数后归档
auto_prune: true # 自动清理过期记忆---
网关配置
Telegram 示例
gateway:
telegram:
enabled: true
bot_token_env: TELEGRAM_BOT_TOKEN
allowed_users: # 限制可用的用户 ID(可选)
- 123456789
allowed_groups: # 限制群组(可选)
- -1001234567890
commands:
start: "欢迎使用 Hermes Agent!输入你的问题开始对话。"
help: "可用命令:\n/ask <问题>\n/memory search <关键词>\n/status"
features:
voice: true # 支持语音消息
image_analysis: true # 分析图片
inline_queries: true # 内联模式Discord 示例
gateway:
discord:
enabled: true
bot_token_env: DISCORD_BOT_TOKEN
command_prefix: "!" # 命令前缀
allowed_guilds: # 限制服务器
- "123456789012345678"
voice_channels: # 支持语音频道
enabled: true
features:
slash_commands: true # 斜杠命令
context_menus: true # 右键菜单
message_content: true # 内容意图(需在 Discord 开发者门户开启)---
安全配置
security:
# 提示注入防护
prompt_injection_protection:
enabled: true # v0.7.0+ 默认开启
strictness: medium # low | medium | high
# 凭证过滤
credential_filtering:
enabled: true
patterns: # 要过滤的模式
- "(?i)(api[_-]?key|token|secret|password)[=:]\s*\S+"
- "sk-[a-zA-Z0-9]{20,}"
- "ghp_[a-zA-Z0-9]{36}"
# 工具权限控制
tool_permissions:
terminal:
require_confirmation:
- "rm "
- "sudo"
- "chmod 777"
- "curl.*\\| bash"
# 日志审计
audit_logging:
enabled: true
log_tool_calls: true
log_file_access: true
log_network_requests: true
# 网络访问控制
network:
allowed_domains: # 白名单(留空则允许所有)
- "*.openai.com"
- "*.anthropic.com"
- "*.openrouter.ai"
blocked_domains: # 黑名单
- "*.malicious-site.com"---
完整配置示例
这是一个生产就绪的完整配置示例:
# ============================================
# Hermes Agent 完整配置示例
# 文件位置: ~/.hermes/config.yaml
# ============================================
# --- 核心模型设置 ---
model:
provider: openrouter
model: anthropic/claude-sonnet-4-20250514
temperature: 0.7
max_tokens: 8192
top_p: 1.0
streaming: true
# --- 提供商 ---
providers:
openrouter:
base_url: "https://openrouter.ai/api/v1"
api_key_env: OPENROUTER_API_KEY
timeout: 120
max_retries: 3
extra_headers:
X-Title: "My Hermes Instance"
# --- 工具集 ---
tools:
enabled_by_default: true
toolsets:
web_search:
enabled: true
browser:
enabled: true
backend: local_chrome
file_operations:
allowed_paths:
- ~/Projects
- /tmp
- ~/Documents
denied_paths:
- ~/.ssh
- ~/.gnupg
terminal:
enabled: true
allowed_commands:
- git
- npm
- python
- node
- make
- cat
- ls
- grep
- find
- head
- tail
- wc
- sed
- awk
memory:
enabled: true
provider: built-in
code_execution:
enabled: true
delegation:
enabled: true
max_concurrent: 3
default_timeout: 300
image_generation:
enabled: false
voice:
enabled: true
tts_provider: edge_tts
# --- 记忆系统 ---
memory:
provider: built-in
retention:
hot_memory_days: 7
session_history_days: 30
cold_storage_after: 90
auto_prune: true
# --- 安全 ---
security:
prompt_injection_protection:
enabled: true
strictness: medium
credential_filtering:
enabled: true
tool_permissions:
terminal:
require_confirmation:
- "rm -rf"
- "sudo"
- "curl.*\\| bash"
- "wget.*\\| sh"
audit_logging:
enabled: true
# --- 网关(按需启用)---
gateway:
telegram:
enabled: false
discord:
enabled: false
# --- UI 设置 ---
ui:
theme: dark # dark | light
color_output: true
show_thinking: false # 显示推理过程
timestamp_format: "%Y-%m-%d %H:%M:%S"---
常见配置问题
Q: 如何切换模型?
# 方法1:交互式
hermes model
# 方法2:命令行临时覆盖
hermes run "prompt" --model gpt-4o --non-interactive
# 方法3:编辑配置文件
nano ~/.hermes/config.yaml # 修改 model.model 字段Q: 如何降低成本?
1. 使用更便宜的模型(如 Haiku、Flash) 2. 减少最大 token 数 3. 限制启用的工具集(减少不必要的函数调用) 4. 使用缓存友好的提示词 5. 考虑 Ollama 本地模型(零 API 成本)
Q: 如何解决 "API key invalid" 错误?
1. 检查 ~/.hermes/.env 中密钥是否正确 2. 确认密钥没有过期或达到配额限制 3. 运行 hermes doctor 进行诊断 4. 尝试切换到备用提供商
Q: 如何让多个项目共享同一个 Hermes?
创建项目级 .hermes/config.yaml:
cd my-project
mkdir -p .hermes
cat > .hermes/config.yaml << EOF
model:
provider: openrouter
model: anthropic/claude-sonnet-4-20250514
EOF
HERMES_ENABLE_PROJECT_AGENTS=true hermesHermes Agent MCP 集成详解
版本: v0.8.0 | 最后更新: 2026-04-11
目录
1. MCP 协议概述 2. 双向集成架构 3. Server 模式(暴露能力) 4. Client 模式(连接外部服务) 5. 工具过滤与安全 6. IDE 配置 7. 高级用法 8. 故障排除
---
MCP 协议概述
Model Context Protocol (MCP) 是一种开放标准,允许 AI 应用与外部数据源和工具进行标准化通信。Hermes Agent 从 v0.6.0 起支持 MCP 的双向集成:
┌─────────────────────────────────────────────────────┐
│ MCP 生态 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ IDE │ ←→ │ Hermes │ ←→ │ 外部API │ │
│ │(Cursor) │ │ Agent │ │ (DB/CRM) │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ↑ ↑ ↑ │
│ MCP Client MCP Server MCP Server │
│ │
└─────────────────────────────────────────────────────┘核心概念
| 概念 | 说明 |
|---|---|
| MCP Server | 提供能力和资源的服务端 |
| MCP Client | 连接并使用 MCP Server 能力的客户端 |
| Tool | 可被 LLM 调用的函数 |
| Resource | 可被读取的数据(文件、URI等) |
| Prompt | 可被注入的提示模板 |
---
双向集成架构
架构图
┌─────────────────────────┐
│ WorkBuddy / IDE │
│ (客户端) │
└───────────┬─────────────┘
│ MCP Protocol
▼
┌────────────────────────────────┐
│ Hermes Agent │
│ │
│ ┌─────────────────────────┐ │
│ │ MCP Server Mode │ │
│ │ (暴露 Hermes 能力) │ │
│ │ - 47+ 工具 │ │
│ │ - 记忆系统 │ │
│ │ - 技能系统 │ │
│ └─────────────────────────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ MCP Client Mode │ │
│ │ (连接外部服务) │ │
│ │ - 数据库 │ │
│ │ - API 服务 │ │
│ │ - 文件系统 │ │
│ └─────────────────────────┘ │
└────────────────────────────────┘使用场景
| 场景 | 模式 | 说明 |
|---|---|---|
| IDE 集成 | Server | 在 Cursor/Windsurf 中调用 Hermes |
| 扩展能力 | Client | 让 Hermes 使用外部数据库/API |
| 双向桥接 | 两者兼用 | 同时作为 Server 和 Client |
---
Server 模式(暴露能力)
启动 MCP Server
# 方式1:标准输入输出模式(推荐用于 IDE 集成)
hermes mcp serve --stdio
# 方式2:HTTP 服务器模式
hermes mcp serve --port 8080
# 方式3:带配置选项启动
hermes mcp serve --stdio \
--allowed-tools "web_search,memory,delegation" \
--max-tokens 4096 \
--model "anthropic/claude-haiku"Server 配置选项
| 选项 | 默认值 | 说明 |
|---|---|---|
--port | 8080 | HTTP 模式端口号(仅 HTTP 模式) |
--stdio | false | 使用 stdio 模式(推荐) |
--model | 配置默认值 | 强制使用指定模型 |
--max-tokens | 配置默认值 | 最大输出 Token 数 |
--temperature | 配置默认值 | 温度参数 |
--allowed-tools | 全部 | 允许暴露的工具列表(逗号分隔) |
--blocked-tools | 无 | 禁止暴露的工具列表 |
--enable-memory | true | 是否暴露记忆相关工具 |
--enable-delegation | true | 是否暴露子代理委托工具 |
--require-authentication | false | 是否需要认证令牌 |
--auth-token | 自动生成 | 认证令牌 |
暴露的工具列表
当以 Server 模式运行时,以下工具会暴露给 MCP 客户端:
核心工具
| 工具名 | 参数 | 说明 |
|---|---|---|
run_task | task, context? | 运行完整任务(等同于 hermes run) |
search_memory | query, limit? | 搜索历史记忆 |
add_note | content, tags? | 添加新笔记 |
list_notes | tag_filter? | 列出所有笔记 |
delegate_task | task, tools?, timeout? | 创建子代理执行任务 |
list_skills | - | 列出已学技能 |
create_skill | name, description, content? | 创建新技能 |
web_search | query, num_results? | 网页搜索 |
read_file | path, offset?, limit? | 读取文件内容 |
write_file | path, content | 写入文件 |
execute_command | command, timeout? | 执行终端命令 |
browser_navigate | url | 浏览器导航到 URL |
browser_click | selector | 点击页面元素 |
browser_extract | selector, extract_type? | 提取页面数据 |
---
Client 模式(连接外部服务)
连接 MCP Server
# 方式1:通过命令行添加
hermes mcp connect --name my-database \
--type sse \
--url http://localhost:3000/sse
# 方式2:通过 JSON 配置
hermes mcp connect '{
"name": "postgres-db",
"type": "sse",
"url": "http://localhost:3000/mcp",
"headers": {"Authorization": "Bearer token123"}
}'
# 方式3:从配置文件加载
hermes mcp connect --config ./mcp-servers.json配置文件格式 (~/.hermes/mcp_servers.json)
{
"mcpServers": {
"database": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres",
"postgresql://user:pass@localhost:5432/mydb"],
"env": {}
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem",
"/path/to/allowed/directory"],
"env": {}
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..."
}
},
"slack": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-slack"],
"env": {
"SLACK_BOT_TOKEN": "xoxb-...",
"SLACK_APP_TOKEN": "xapp-..."
}
},
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"BRAVE_API_KEY": "your-key"
}
},
"puppeteer": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
},
"fetch": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-fetch"]
}
}
}管理 MCP 连接
# 列出已连接的 MCP 服务
hermes mcp list
# 显示某个服务的可用工具
hermes mcp tools database
# 断开连接
hermes mcp disconnect database
# 断开所有连接
hermes mcp disconnect --all
# 测试连接
hermes mcp test database---
工具过滤与安全
Server 端工具过滤
当 Hermes 作为 MCP Server 运行时,可以限制暴露的工具:
# 只暴露特定工具
hermes mcp serve --stdio \
--allowed-tools "run_task,search_memory,web_search"
# 排除危险工具
hermes mcp serve --stdio \
--blocked-tools "execute_command,write_file,browser_*"
# 组合使用
hermes mcp serve --stdio \
--allowed-tools "run_task,search_memory,list_notes" \
--blocked-tools ""Client 端工具命名空间
来自 MCP Client 的工具会被自动加上命名空间前缀:
# 假设连接了 postgres 和 github 两个 MCP Server
# 来自 postgres 的工具:
postgres:query
postgres:list_tables
postgres:get_schema
# 来自 github 的工具:
github:search_issues
github:create_issue
github:get_file_contents
# Hermes 内置工具保持原样:
run_task
search_memory
delegate_task安全最佳实践
# ~/.hermes/config.yaml
security:
mcp:
# Server 模式设置
server:
require_authentication: true
auth_token_env: HERMES_MCP_AUTH_TOKEN
allowed_origins: # CORS 白名单
- "vscode-webview://*"
- "windsurf://*"
# Client 模式设置
client:
allow_untrusted_servers: false # 只允许预配置的服务器
timeout_per_tool: 60 # 每个 MCP 工具超时时间
# 审计日志
audit_log:
enabled: true
log_mcp_calls: true
include_params: false # 不记录敏感参数---
IDE 配置
Cursor 配置
在 .cursor/mcp.json 中添加:
{
"mcpServers": {
"hermes": {
"command": "hermes",
"args": ["mcp", "serve", "--stdio",
"--allowed-tools", "run_task,search_memory,web_search,read_file,write_file"]
}
}
}VS Code + Claude Code 配置
在 .vscode/settings.json 或 Claude Code 配置中:
{
"mcpServers": {
"hermes-agent": {
"command": "/Users/username/.local/bin/hermes",
"args": [
"mcp",
"serve",
"--stdio",
"--model", "anthropic/claude-haiku",
"--allowed-tools", "run_task,search_memory,web_search,file_operations,execute_code"
]
}
}
}Windsurf 配置
在 .windsurf/mcp.json 中:
{
"servers": {
"hermes": {
"command": "hermes",
"args": ["mcp", "serve", "--stdio"]
}
}
}Zed 编辑器配置
在 settings.json 中:
{
"mcp_servers": {
"hermes": {
"command": "hermes",
"args": ["mcp", "serve", "--stdio"]
}
}
}---
高级用法
1. 多实例部署
同时运行多个 Hermes MCP Server,每个有不同的模型和能力配置:
# 实例1:轻量级快速任务(Haiku)
HERMES_MCP_PORT=8081 hermes mcp serve --port 8081 \
--model anthropic/claude-haiku \
--allowed-tools "run_task,search_memory" &
# 实例2:深度研究任务(Sonnet)
HERMES_MCP_PORT=8082 hermes mcp serve --port 8082 \
--model anthropic/claude-sonnet \
--allowed-tools "run_task,web_search,browser,delegation" &
# 实例3:代码任务(GPT-4o)
HERMES_MCP_PORT=8083 hermes mcp serve --port 8083 \
--model openai/gpt-4o \
--allowed-tools "run_task,file_operations,code_execution,terminal" &IDE 配置中选择不同的端口连接不同能力的实例。
2. 链式 MCP 调用
Hermes 作为中间层,串联多个 MCP 服务:
IDE → Hermes MCP Server → [Hermes 内部处理]
↓
Hermes MCP Client A → PostgreSQL
Hermes MCP Client B → GitHub API
Hermes MCP Client C → SlackHermes 可以智能地根据任务需求选择调用哪个外部 MCP 工具。
3. 自定义工具包装
将外部 MCP 工具包装为 Hermes 的原生技能:
# 包装脚本示例
def wrap_mcp_tool(ctx, tool_name, params):
"""
将 MCP 工具调用包装为 Hermes 技能
"""
result = call_mcp_client("my-server", tool_name, params)
# 后处理结果
if tool_name.startswith("db:"):
return format_as_markdown_table(result)
elif tool_name.startswith("gh:"):
return format_github_result(result)
return result
ctx.register_tool(
name="query_database_via_mcp",
schema=db_schema,
handler=lambda p: wrap_mcp_tool(ctx, f"db:query", p)
)4. 性能优化
# config.yaml
mcp:
server:
# 缓存常用查询结果
cache_enabled: true
cache_ttl: 300 # 缓存有效期(秒)
# 并发控制
max_concurrent_requests: 5
# 流式响应
streaming_enabled: true
client:
# 连接池
connection_pool_size: 10
# 重试策略
retry_attempts: 3
retry_backoff: 1s
# 请求超时
request_timeout: 30s---
故障排除
常见问题
Q: MCP Server 启动失败
# 检查依赖
hermes doctor
# 查看 MCP 相关日志
hermes logs --level ERROR | grep -i mcp
# 手动测试 stdio 模式
echo '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":1}' | hermes mcp serve --stdioQ: IDE 无法连接到 MCP Server
1. 检查路径: 确保 hermes 命令在 PATH 中 2. 检查权限: 确保 IDE 有权限执行 shell 命令 3. 检查参数: 确保 args 数组格式正确 4. 测试连接: 在终端手动运行相同命令验证
# Cursor/VSCODE 的调试方法
hermes mcp serve --stdio &
# 输入 JSON-RPC 测试消息
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}'Q: MCP Client 连接超时
# 测试外部 MCP Server 是否可达
curl -v http://localhost:3000/sse
# 检查网络配置
hermes mcp test <server-name>
# 增加超时时间
hermes mcp connect ... --timeout 120Q: 工具名称冲突
当 Hermes 内置工具和 MCP Client 工具同名时,MCP 工具会自动加前缀。如果需要自定义前缀:
mcp:
client:
namespace_prefix: true # 启用命名空间前缀(默认开启)
namespace_separator: ":" # 分隔符
conflict_resolution: "prefix" # prefix | rename | error调试模式
# 启用详细调试日志
HERMES_LOG_LEVEL=DEBUG hermes mcp serve --stdio
# 查看所有 MCP 通信
hermes logs --follow | grep -i mcp---
参考资源
- MCP 规范: https://modelcontextprotocol.io/
- 官方 SDK: https://github.com/modelcontextprotocol/python-sdk
- 社区服务器: https://mcp.so/
- Hermes MCP 源码:
mcp_serve.py
Hermes Agent 插件开发指南
版本: v0.8.0 | 最后更新: 2026-04-11
目录
1. 插件概述 2. 目录结构 3. 插件类型 4. 开发流程 5. API 参考 6. 钩子系统 7. 发布与分发 8. 示例插件
---
插件概述
Hermes 的插件系统允许用户在不修改核心代码的情况下扩展功能,支持:
| 能力 | 说明 |
|---|---|
| 自定义工具 | 添加新的 LLM 可调用工具 |
| 生命周期钩子 | 在关键事件点执行自定义逻辑 |
| CLI 命令扩展 | 添加 hermes <plugin> 子命令 |
| 技能绑定 | 随插件分发技能文件 |
| 数据文件打包 | 包含配置、模板等资源 |
---
目录结构
my-plugin/
├── plugin.yaml # 插件清单(必需)
├── __init__.py # 注册函数(必需)
├── schemas.py # 工具模式定义
├── tools.py # 工具处理器实现
├── data/ # 数据文件(可选)
│ └── config.json
└── skill.md # 绑定的技能(可选)plugin.yaml 格式
name: my-plugin-name # 插件标识符(必需)
version: "1.0.0" # 语义化版本(必需)
description: 简短描述插件的功能 # 用户可见的描述(推荐)
author: Your Name # 作者信息(可选)
requires_env: [] # 需要的环境变量(可选,安装时提示用户配置)
# 插件类型(自动检测,通常不需要手动指定)
type: general # general | memory_provider | context_engine
# 兼容性
hermes_min_version: "0.7.0" # 最低兼容版本(可选)
license: MIT # 许可证(可选)
repository: https://github.com/user/repo # Git 仓库地址(可选)__init__.py 注册函数
"""
我的 Hermes 插件 - 实现描述
"""
def register(ctx):
"""
主注册函数。Hermes 加载插件时调用此函数。
Args:
ctx (PluginContext): 插件上下文对象,提供以下 API:
- ctx.register_tool(name, schema, handler): 注册工具
- ctx.register_hook(event_name, callback): 注册钩子
- ctx.register_cli_command(name, help, setup_fn, handler_fn): 注册 CLI 命令
- ctx.inject_message(content, role="user"): 注入消息
"""
# 导入你的工具定义和处理器
from .schemas import tool_schema
from .tools import handle_tool_call
# 注册自定义工具
ctx.register_tool("my_tool_name", tool_schema, handle_tool_call)
# 注册钩子(可选)
def on_tool_complete(tool_name, params, result):
print(f"[my-plugin] Tool {tool_name} completed")
ctx.register_hook("post_tool_call", on_tool_complete)---
插件类型
1. 通用插件 (General Plugin)
最灵活的插件类型,可以添加任意数量的工具和钩子。
# plugin.yaml
name: weather-plugin
version: "1.0.0"
description: 天气查询插件# __init__.py
from .schemas import get_weather_schema
from .tools import get_weather_handler
def register(ctx):
ctx.register_tool("get_weather", get_weather_schema, get_weather_handler)2. 内存提供者 (Memory Provider)
替换或增强内置的记忆系统。
# plugin.yaml
name: custom-memory
version: "1.0.0"
description: 自定义记忆后端
type: memory_provider# __init__.py
def register(ctx):
"""
内存提供者需要实现特定接口:
- search(query) -> List[Note]
- add(note) -> Note
- list_notes() -> List[Note]
- delete(note_id) -> bool
"""
class CustomMemoryBackend:
def search(self, query):
# 你的搜索实现
pass
def add(self, content, tags=None):
# 你的添加实现
pass
ctx.set_memory_backend(CustomMemoryBackend())可用的内存提供者类型:
| 后端名 | 特点 |
|---|---|
built-in | 默认,SQLite + FTS5 |
honcho | AI 原生方言建模 |
mem0 | 开源记忆服务 |
openviking | 高级向量检索 |
hindsight | 时间线记忆 |
holographic | 全息记忆系统 |
3. 上下文引擎 (Context Engine)
替换内置的上下文压缩器。
# plugin.yaml
name: smart-context
version: "1.0.0"
description: 智能上下文压缩
type: context_engine# __init__.py
def register(ctx):
class SmartContextEngine:
def compress(self, messages, max_tokens):
# 自定义的上下文压缩逻辑
pass
def summarize(self, text, target_length):
# 自定义摘要逻辑
pass
ctx.set_context_engine(SmartContextEngine())---
开发流程
步骤 1:创建插件骨架
mkdir -p ~/.hermes/plugins/my-plugin
cd ~/.hermes/plugins/my-plugin
touch plugin.yaml __init__.py schemas.py tools.py步骤 2:编写 plugin.yaml
name: my-awesome-plugin
version: "0.1.0"
description: 我的第一款 Hermes 插件
author: Your Name步骤 3:定义工具模式 (schemas.py)
"""
工具模式定义 - LLM 看到的接口说明
"""
tool_schema = {
"name": "awesome_tool",
"description": "这个工具做什么的详细描述",
"parameters": {
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "参数1的说明",
},
"param2": {
"type": "integer",
"description": "参数2的说明",
"default": 10,
},
"options": {
"type": "array",
"items": {"type": "string"},
"description": "可选选项列表",
}
},
"required": ["param1"],
}
}步骤 4:实现工具处理器 (tools.py)
"""
工具处理器 - 实际执行逻辑
"""
import json
def handle_tool_call(params: dict) -> str:
"""
处理工具调用。
Args:
params: 从 LLM 调用中接收到的参数字典
Returns:
str: 返回给 LLM 的结果字符串(会被添加到对话历史中)
"""
param1 = params.get("param1", "")
param2 = params.get("param2", 10)
options = params.get("options", [])
try:
# === 在这里实现你的业务逻辑 ===
result = f"处理结果: param1={param1}, param2={param2}"
if options:
result += f", options={', '.join(options)}"
return result
except Exception as e:
# 错误处理:返回有意义的错误信息给 LLM
return f"错误: 执行失败 - {str(e)}"
# 如果有多个工具,可以定义多个 schema/handler 对
another_tool_schema = {
"name": "another_tool",
"description": "另一个工具",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "查询内容"}
},
"required": ["query"]
}
}
def another_handler(params: dict) -> str:
query = params.get("query", "")
return f"查询 '{query}' 的结果是..."步骤 5:在 __init__.py 中注册
"""My Awesome Plugin for Hermes Agent."""
def register(ctx):
"""Register all tools and hooks with Hermes."""
# 导入本地模块
from .schemas import tool_schema, another_tool_schema
from .tools import handle_tool_call, another_handler
# 注册工具 1
ctx.register_tool(
name="awesome_tool",
schema=tool_schema,
handler=handle_tool_call
)
# 注册工具 2
ctx.register_tool(
name="another_tool",
schema=another_tool_schema,
handler=another_handler
)
# 注册钩子(可选)
def log_tool_usage(tool_name, params, result):
"""记录每次工具调用到日志文件"""
import json
from datetime import datetime
log_entry = {
"timestamp": datetime.now().isoformat(),
"tool": tool_name,
"params": params,
"success": not str(result).startswith("错误")
}
with open("/tmp/plugin-tool-usage.log", "a") as f:
f.write(json.dumps(log_entry) + "\n")
ctx.register_hook("post_tool_call", log_tool_usage)
# 注册 CLI 命令(可选)
def setup_parser(parser):
"""设置 CLI 参数解析器"""
parser.add_argument("--verbose", action="store_true")
parser.add_argument("--output-format", choices=["json", "text"], default="text")
def cmd_handler(args):
"""处理 CLI 命令"""
print(f"My plugin running with verbose={args.verbose}")
ctx.register_cli_command(
name="my-plugin",
help="我的插件的自定义命令",
setup_fn=setup_parser,
handler_fn=cmd_handler
)步骤 6:安装和测试
# 安装插件(从本地路径)
hermes plugins install /path/to/my-plugin
# 或从 Git 安装
hermes plugins install https://github.com/you/my-plugin.git
# 启用插件
hermes plugins enable my-plugin
# 测试插件是否加载
hermes plugins list
# 在对话中测试
hermes run "使用 awesome_tool 工具,参数 param1=test" --non-interactive --no-stream---
API 参考
PluginContext API
ctx.register_tool(name, schema, handler)
注册一个可供 LLM 调用的工具。
参数:
name(str): 工具名称,全局唯一schema(dict): JSON Schema 格式的工具定义handler(callable): 处理函数(params: dict) -> str
示例:
ctx.register_tool("my_tool", {...}, lambda p: "result")ctx.register_hook(event_name, callback)
注册生命周期钩子。
可用事件:
| 事件名 | 回调签名 | 触发时机 |
|---|---|---|
pre_tool_call | (tool_name, params) | 工具执行前 |
post_tool_call | (tool_name, params, result) | 工具执行后 |
pre_llm_call | (messages, kwargs) | LLM 调用前,可返回 {"context": "..."} 注入上下文 |
post_llm_call | (response, messages) | LLM 调用成功后 |
on_session_start | (session_id) | 新会话创建时 |
on_session_end | (session_id) | 会话结束时 |
ctx.register_cli_command(name, help, setup_fn, handler_fn)
注册 CLI 子命令。
参数:
name(str): 命令名称(如my-cmd,调用方式为hermes my-cmd)help(str): 帮助文本setup_fn(callable): 设置参数解析器(parser) -> Nonehandler_fn(callable): 处理命令(args) -> None
ctx.inject_message(content, role="user")
向当前会话注入消息。
示例:
ctx.inject_message("注意:用户偏好是使用中文回复。", role="system")---
钩子系统
钩子执行顺序
用户输入 → pre_llm_call → [LLM 调用] → post_llm_call
↓
解析工具调用
↓
pre_tool_call → [工具执行] → post_tool_call
↓
返回响应高级钩子用法
1. 上下文注入
在每次 LLM 调用前注入额外的上下文信息:
def inject_user_preferences(messages, kwargs):
"""注入用户偏好的上下文"""
preferences = load_user_preferences() # 你自己的函数
context_text = (
f"当前用户偏好:\n"
f"- 语言: {preferences['language']}\n"
f"- 时区: {preferences['timezone']}\n"
f"- 专业领域: {preferences['domain']}\n"
)
return {"context": context_text}
ctx.register_hook("pre_llm_call", inject_user_preferences)2. 工具调用审计
记录所有工具调用的完整日志:
def audit_tool_calls(tool_name, params, result):
"""审计所有工具调用"""
import logging
logger = logging.getLogger("plugin.audit")
logger.info({
"tool": tool_name,
"params": params,
"result_length": len(str(result)),
"timestamp": time.time()
})
ctx.register_hook("post_tool_call", audit_tool_calls)3. 敏感操作确认
对危险操作进行二次确认:
def confirm_destructive_actions(tool_name, params):
"""拦截破坏性操作"""
destructive_patterns = [
("file_delete", ["rm", "delete"]),
("execute_command", ["rm -rf", "sudo"]),
]
for t_tool, t_keywords in destructive_patterns:
if tool_name == t_tool:
for kw in t_keywords:
params_str = str(params).lower()
if kw in params_str:
raise PermissionError(
f"⚠️ 危险操作被拦截: {tool_name} 包含关键词 '{kw}'"
)
ctx.register_hook("pre_tool_call", confirm_destructive_actions)---
发布与分发
本地安装
# 从本地目录安装
hermes plugins install /path/to/my-plugin
# 或直接复制到插件目录
cp -r my-plugin ~/.hermes/plugins/
hermes plugins enable my-plugin通过 Git 分发
# 从 GitHub 安装
hermes plugins install owner/repo
hermes plugins install https://github.com/owner/repo.git
# 从私有仓库安装(需认证)
hermes plugins install git@github.com:owner/private-repo.git通过 Pip 分发
在 pyproject.toml 中添加入口点:
[project.entry-points."hermes_agent.plugins"]
my_plugin = "my_package:register"用户通过 pip install your-package 即可安装。
更新插件
# 更新单个插件
hermes plugins update my-plugin
# 更新所有已安装的插件
hermes plugins update --all---
示例插件
示例 1:天气查询插件
# plugin.yaml
name: weather-plugin
version: "1.0.0"
description: 使用 OpenWeatherMap API 查询天气
requires_env: [OPENWEATHERMAP_API_KEY]
author: Example Author# __init__.py
"""Weather Query Plugin for Hermes Agent."""
import os
def register(ctx):
from .schemas import weather_schema, forecast_schema
from .tools import get_current_weather, get_forecast
ctx.register_tool("get_current_weather", weather_schema, get_current_weather)
ctx.register_tool("get_weather_forecast", forecast_schema, get_forecast)# schemas.py
weather_schema = {
"name": "get_current_weather",
"description": "获取指定城市的当前天气情况",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如 'Beijing'、'New York'"
},
"units": {
"type": "string",
"enum": ["metric", "imperial"],
"default": "metric",
"description": "温度单位"
}
},
"required": ["city"]
}
}
forecast_schema = {
"name": "get_weather_forecast",
"description": "获取未来几天的天气预报",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
},
"days": {
"type": "integer",
"description": "预报天数(1-7)",
"default": 3
}
},
"required": ["city"]
}
}# tools.py
"""Weather tool implementations."""
import os
import requests
API_KEY = os.environ.get("OPENWEATHERMAP_API_KEY", "")
BASE_URL = "https://api.openweathermap.org/data/2.5"
def get_current_weather(params: dict) -> str:
city = params["city"]
units = params.get("units", "metric")
url = f"{BASE_URL}/weather?q={city}&appid={API_KEY}&units={units}"
response = requests.get(url, timeout=10)
if response.status_code != 200:
return f"无法获取天气信息: {response.json().get('message', '未知错误')}"
data = response.json()
temp_unit = "°C" if units == "metric" else "°F"
return (
f"{city} 当前天气:\n"
f"- 温度: {data['main']['temp']}{temp_unit}\n"
f"- 体感温度: {data['main']['feels_like']}{temp_unit}\n"
f"- 湿度: {data['main']['humidity']}%\n"
f"- 风速: {data['wind'].get('speed', 0)} m/s\n"
f"- 天气状况: {data['weather'][0]['description']}\n"
f"- 能见度: {data.get('visibility', 'N/A')} m"
)
def get_forecast(params: dict) -> string:
city = params["city"]
days = min(max(params.get("days", 3), 1), 7) # 限制在 1-7 天
url = f"{BASE_URL}/forecast?q={city}&appid={API_KEY}&units=metric&cnt={days * 8}" # 每3小时一个数据点
response = requests.get(url, timeout=10)
if response.status_code != 200:
return f"无法获取预报: {response.json().get('message', '未知错误')}"
data = response.json()
result = f"{city} 未来{days}天预报:\n\n"
for item in data["list"][:days * 8]: # 取前 N 天的数据
dt = item["dt_txt"]
temp = item["main"]["temp"]
desc = item["weather"][0]["description"]
result += f"{dt}: {temp}°C, {desc}\n"
return result示例 2:数据库查询插件
# __init__.py
"""Database Query Plugin - 安全地执行 SQL 查询。"""
import sqlite3
def register(ctx):
db_schema = {
"name": "query_database",
"description": "在 SQLite 数据库中执行只读 SQL 查询",
"parameters": {
"type": "object",
"properties": {
"db_path": {
"type": "string",
"description": "数据库文件路径"
},
"query": {
"type": "string",
"description": "SQL SELECT 查询语句"
},
"limit": {
"type": "integer",
"description": "最大返回行数(默认100)",
"default": 100
}
},
"required": ["db_path", "query"]
}
}
def execute_query(params: dict) -> str:
db_path = params["db_path"]
query = params["query"].strip()
limit = params.get("limit", 100)
# 安全检查:只允许 SELECT 语句
if not query.upper().startswith("SELECT"):
return "错误: 只允许 SELECT 查询语句"
# 检查危险关键字
dangerous = ["DROP", "DELETE", "UPDATE", "INSERT", "ALTER", "--", ";"]
for word in dangerous:
if word.upper() in query.upper():
return f"错误: 查询包含不安全的关键字 '{word}'"
try:
conn = sqlite3.connect(db_path)
conn.row_factory = sqlite3.Row
# 自动添加 LIMIT
if "LIMIT" not in query.upper():
query += f"\nLIMIT {limit}"
cursor = conn.execute(query)
rows = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
conn.close()
if not rows:
return "查询返回空结果集"
# 格式化输出为表格
header = " | ".join(columns)
separator = "-+-".join(["-" * len(c) for c in columns])
lines = [header, separator]
for row in rows[:limit]:
line = " | ".join(str(v) for v in row)
lines.append(line)
return "\n".join(lines)
except sqlite3.Error as e:
return f"SQL 错误: {str(e)}"
except Exception as e:
return f"执行错误: {str(e)}"
ctx.register_tool("query_database", db_schema, execute_query)Hermes Agent 与 Self-Improving Agent CN 集成指南
版本: v1.0.0 | 最后更新: 2026-04-11
概述
本集成方案让 Hermes Agent 和 Self-Improving Agent CN 形成完整的正负反馈闭环:
┌─────────────────────────────────────────────────────────────┐
│ 自改进学习循环 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────┐ ┌──────────────────────────┐ │
│ │ Hermes Agent │ │ Self-Improving Agent │ │
│ │ │ │ CN │ │
│ │ ✅ 成功任务 → │ │ ❌ 失败/纠正 → │ │
│ │ 提取可复用技能 │ ←→ │ 记录错误教训 │ │
│ │ │ │ │ │
│ │ 存储位置: │ │ 存储位置: │ │
│ │ ~/.hermes/skills/ │ │ ~/.openclaw/memory/ │ │
│ └───────────────────┘ │ self-improving/ │ │
│ └──────────────────────────┘ │
│ │
│ Wrapper/Delegate 脚本自动触发错误回调 │
│ │
└─────────────────────────────────────────────────────────────┘---
集成方式
自动错误回调机制(已内置)
hermes_wrapper.sh 和 hermes_delegate.sh 已内置 error_callback() 函数:
触发条件: 1. 命令执行失败(退出码非0) 2. 任务超时(退出码124) 3. 并发限制达到 4. 其他运行时错误
回调行为:
- 将错误信息记录到
~/.openclaw/memory/self-improving/learnings.jsonl - 包含时间戳、错误类型、任务描述、原始命令等上下文
- 预留
lesson字段供后续分析填充
错误记录格式
{
"timestamp": "2026-04-11T20:46:00Z",
"error_type": "TIMEOUT",
"error_message": "任务执行超时 (300s): 研究竞品产品特性",
"task": "研究竞品产品特性",
"command": "hermes run '...' --non-interactive --no-stream --timeout 300",
"source": "hermes-delegate",
"context": {
"hermes_version": "Hermes Agent v0.8.0 (2026.4.8)",
"platform": "Darwin",
"user": "chunhaixu"
},
"lesson": "TODO: 待分析此错误的根本原因和解决方案"
}---
配置与使用
启用自动记录(默认启用)
# 错误回调默认启用,无需额外配置
# 记录文件位置: ~/.openclaw/memory/self-improving/learnings.jsonl查看学习记录
# 查看所有错误记录
cat ~/.openclaw/memory/self-improving/learnings.jsonl | jq .
# 按日期过滤
cat ~/.openclaw/memory/self-improving/learnings.jsonl \
| jq 'select(.timestamp | startswith("2026-04"))'
# 按错误类型统计
cat ~/.openclaw/memory/self-improving/learnings.jsonl \
| jq -r '.error_type' | sort | uniq -c | sort -rn
# 查看最近的错误
tail -5 ~/.openclaw/memory/self-improving/learnings.jsonl | jq .手动添加教训(填充 lesson 字段)
当分析出错误原因后,更新记录:
# 使用 jq 更新特定记录的 lesson 字段
RECORD_ID=$(tail -1 learnings.jsonl | jq '.timestamp')
jq "if .timestamp == \"$RECORD_ID\" then .lesson = \"应该增加超时时间到600秒或简化任务范围\" else . end" \
learnings.jsonl > tmp.jsonl && mv tmp.jsonl learnings.jsonl在 WorkBuddy 中使用
WorkBuddy 加载 self-improving-agent-cn Skill 后会自动:
1. 执行前检查:读取 learnings.jsonl 中的历史错误 2. 模式匹配:识别当前任务是否与历史错误相似 3. 预防性建议:根据历史教训给出建议
---
最佳实践
1. 定期审查错误日志
建议每周检查一次学习记录:
#!/bin/bash
# review_errors.sh - 审查本周 Hermes 错误
ERROR_FILE="$HOME/.openclaw/memory/self-improving/learnings.jsonl"
THIS_WEEK=$(date +%Y-%W)
echo "=== 本周 ($THIS_WEEK) Hermes 错误报告 ==="
echo ""
if [ -f "$ERROR_FILE" ]; then
# 统计错误数量
TOTAL=$(grep -c "" "$ERROR_FILE" 2>/dev/null || echo 0)
# 统计各类错误
echo "📊 错误类型分布:"
cat "$ERROR_FILE" | jq -r '.error_type' | sort | uniq -c | sort -rn | while read count type; do
echo " $count x $type"
done
echo ""
echo "📝 未解决的教训 (lesson 为 TODO):"
cat "$ERROR_FILE" | jq -r 'select(.lesson | startswith("TODO")) | "- \(.error_type): \(.task)"'
else
echo "✅ 无错误记录"
fi2. 从错误中提取技能
当同一类型的错误重复出现 3+ 次,考虑将其转化为 Hermes 技能:
#!/bin/bash
# extract_skill_from_errors.sh - 从错误中提取技能模板
ERROR_FILE="$HOME/.openclaw/memory/self-improving/learnings.jsonl"
SKILLS_DIR="$HOME/.hermes/skills"
# 找出最频繁的错误类型
TOP_ERROR=$(cat "$ERROR_FILE" | jq -r '.error_type' | sort | uniq -c | sort -rn | head -1 | awk '{print $2}')
echo "检测到高频错误类型: $TOP_ERROR"
case $TOP_ERROR in
TIMEOUT)
SKILL_NAME="timeout-handling"
echo "建议创建技能: $SKILL_NAME"
mkdir -p "$SKILLS_DIR/$SKILL_NAME"
cat > "$SKILLS_DIR/$SKILL_NAME/skill.md" << EOF
---
name: timeout-handling
description: 处理可能超时的长时间任务
triggers:
- 超时任务
- 大量数据查询
- 复杂研究
---
# 超时处理技能
## 策略
1. **分解任务**: 将大任务拆分为多个小步骤
2. **设置合理超时**: 简单任务60s, 中等300s, 复杂600s+
3. **工具集限制**: 只启用必要的工具减少 Token 消耗
4. **增量保存**: 每完成一步就保存中间结果
5. **重试机制**: 失败后自动重试1次
## 最佳实践
\`\`\`bash
# 推荐参数
hermes run "任务" --toolset web_search --timeout 120
\`\`\`
EOF
echo "✅ 技能已创建: $SKILLS_DIR/$SKILL_NAME/skill.md"
;;
esac3. 双向同步
让 Hermes 的技能系统和 Self-Improving 的错误系统互相感知:
# 可选的高级集成代码示例
def sync_hermes_with_self_improving():
"""
定期同步 Hermes 技能和 Self-Improving 记录
"""
import json
skills_dir = Path("~/.hermes/skills").expanduser()
errors_file = Path("~/.openclaw/memory/self-improving/learnings.jsonl").expanduser()
# 1. 将新技能通知给 Self-Improving
for skill_file in skills_dir.glob("**/skill.md"):
skill_name = skill_file.parent.name
# 标记为从成功经验中学到的能力
log_success(f"New skill available: {skill_name}")
# 2. 分析错误模式并建议技能改进
if errors_file.exists():
with open(errors_file) as f:
errors = [json.loads(line) for line in f]
# 按错误类型分组
from collections import Counter
error_types = Counter(e['error_type'] for e in errors)
for error_type, count in error_types.most_common(3):
if count >= 3 and not any(s.name == f"{error_type}-handling"
for s in list_skills()):
suggest_skill_creation(error_type, errors)---
故障排除
Q: 错误记录文件不存在?
mkdir -p ~/.openclaw/memory/self-improving/
touch ~/.openclaw/memory/self-improving/learnings.jsonlQ: jq 命令不可用?
# macOS 安装 jq
brew install jq
# 或使用 Python 替代
python3 -c "
import json
with open('learnings.jsonl') as f:
for line in f:
print(json.dumps(json.loads(line), indent=2))
"Q: 如何禁用错误回调?
临时禁用:
HERMES_DISABLE_SELF_IMPROVING=true hermes_wrapper.sh run "prompt"永久修改脚本中的 error_callback() 调用处即可。
---
总结
| 维度 | Hermes Agent | Self-Improving Agent CN |
|---|---|---|
| 学习来源 | ✅ 成功任务 | ❌ 失败/纠正 |
| 存储格式 | Markdown 技能文件 | JSONL 记录文件 |
| 触发时机 | 任务完成后 | 用户纠正/失败时 |
| 优化频率 | 每15个任务评估 | 每次执行前检查 |
| 内容类型 | 可复用方法论 | 应避免的错误 |
两者互补,形成完整的正负反馈闭环,让 Agent 系统越用越智能!
#!/bin/bash
# ============================================================================
# Hermes Agent Delegate Script for WorkBuddy
# ============================================================================
# 子代理委托专用脚本,支持:
# - 任务描述注入和格式化
# - 工具集限制(减少 Token 消耗)
# - 超时控制和自动终止
# - 输出解析和结构化返回
# - 并发管理(上限3个,符合 Hermes 限制)
# - 错误回调接口(集成 Self-Improving Agent CN)
#
# 用法:
# ./hermes_delegate.sh --task "任务描述" [选项]
#
# 示例:
# ./hermes_delegate.sh \
# --task "分析竞品A和B的产品特性差异" \
# --tools "web_search,browser,file_write" \
# --timeout 300 \
# --output ./result.md
# ============================================================================
set -euo pipefail
# ============================================================================
# 配置常量(动态检测,无硬编码路径)
# ============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HERMES_CMD="${HERMES_CMD:-hermes}"
# 动态搜索 hermes 命令
if ! command -v "$HERMES_CMD" &> /dev/null; then
for candidate in \
"$HOME/.local/bin/hermes" \
"$HOME/.local/hermes-agent/.venv/bin/hermes" \
"$HOME/.workbuddy/binaries/python/envs/default/bin/hermes" \
"$(which hermes 2>/dev/null)"; do
if [ -x "$candidate" ]; then
HERMES_CMD="$candidate"
break
fi
done
fi
DEFAULT_TIMEOUT=300
MAX_CONCURRENT_DELEGATES=3
# 使用用户目录下的临时目录(而非 /tmp,更可靠)
LOCK_DIR="${TMPDIR:-/tmp}/hermes_delegates_$(id -u)"
SELF_IMPROVING_MEMORY="${HOME}/.workbuddy/memory/self-improving/learnings.jsonl"
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
MAGENTA='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'
# ============================================================================
# 日志函数
# ============================================================================
log_info() { echo -e "${BLUE}[DELEGATE-INFO]${NC} $(date '+%H:%M:%S') $*" >&2; }
log_success() { echo -e "${GREEN}[DELEGATE-SUCCESS]${NC} $*" >&2; }
log_error() { echo -e "${RED}[DELEGATE-ERROR]${NC} $*" >&2; }
log_warn() { echo -e "${YELLOW}[DELEGATE-WARN]${NC} $*" >&2; }
log_debug() { [[ "${DEBUG:-false}" == "true" ]] && echo -e "${MAGENTA}[DEBUG]${NC} $*" >&2 || true; }
# ============================================================================
# 工具函数
# ============================================================================
# 检查依赖
check_dependencies() {
log_debug "检查依赖..."
if ! command -v "$HERMES_CMD" &> /dev/null; then
log_error "Hermes 命令未找到: $HERMES_CMD"
return 1
fi
if ! command -v timeout &> /dev/null; then
log_warn "timeout 命令不可用,将使用后台进程方式处理超时"
fi
log_debug "依赖检查通过"
return 0
}
# 创建锁文件用于并发控制
acquire_lock() {
local task_id="$1"
mkdir -p "$LOCK_DIR"
# 检查当前运行的 delegate 数量
local current_count=$(find "$LOCK_DIR" -name "*.lock" -type f 2>/dev/null | wc -l | tr -d ' ')
if [ "$current_count" -ge "$MAX_CONCURRENT_DELEGATES" ]; then
log_error "已达到最大并发数 ($MAX_CONCURRENT_DELEGATES),当前运行: $current_count 个任务"
return 1
fi
# 创建锁文件
local lock_file="$LOCK_DIR/${task_id}.lock"
echo "$(date +%s)" > "$lock_file"
echo "$task_id" >> "$lock_file"
log_debug "获取锁: $lock_file (当前: $((current_count + 1))/$MAX_CONCURRENT_DELEGATES)"
return 0
}
# 释放锁
release_lock() {
local task_id="$1"
local lock_file="$LOCK_DIR/${task_id}.lock"
rm -f "$lock_file" 2>/dev/null || true
log_debug "释放锁: $lock_file"
}
# 清理所有过期锁(超过1小时的视为过期)
cleanup_stale_locks() {
local now=$(date +%s)
find "$LOCK_DIR" -name "*.lock" -type f -mmin +60 -delete 2>/dev/null || true
}
# 生成唯一任务ID
generate_task_id() {
echo "delegate_$(date '+%Y%m%d_%H%M%S')_$$_${RANDOM}"
}
# 构建委托提示词
build_delegate_prompt() {
local task="$1"
local tools="${2:-}"
local context_content="${3:-}"
local constraints="${4:-}"
local prompt=""
prompt+="你是一个专业的子代理。请使用 delegate_task 工具完成以下任务。\n\n"
prompt+="## 任务描述\n\n$task\n\n"
if [ -n "$tools" ]; then
prompt+="## 可用工具限制\n\n"
prompt+="本次任务仅可使用以下工具:$tools\n\n"
fi
if [ -n "$context_content" ]; then
prompt+="## 额外上下文\n\n$context_content\n\n"
fi
if [ -n "$constraints" ]; then
prompt+="## 执行约束\n\n$constraints\n\n"
fi
prompt+="## 输出要求\n\n"
prompt+="- 请直接执行任务并返回完整结果\n"
prompt+="- 结果应包含关键发现、数据或结论\n"
prompt+="- 如果遇到错误,请详细说明错误原因\n"
prompt+="- 使用 Markdown 格式组织输出\n"
echo -e "$prompt"
}
# 解析输出结果(提取关键信息)
parse_output() {
local raw_output="$1"
local output_file="${2:-}"
# 如果指定了输出文件,写入原始输出
if [ -n "$output_file" ]; then
mkdir -p "$(dirname "$output_file")" 2>/dev/null || true
echo -e "$raw_output" > "$output_file"
log_success "结果已保存到: $output_file"
fi
# 返回原始输出(由调用方决定是否解析)
echo -e "$raw_output"
}
# 错误回调:记录到 Self-Improving 记录
error_callback() {
local error_type="$1"
local error_message="$2"
local task_description="${3:-}"
local original_command="${4:-}"
log_info "触发错误回调 (Self-Improving)..."
# 确保目录存在
mkdir -p "$(dirname "$SELF_IMPROVING_MEMORY")" 2>/dev/null || true
# 检查 jq 是否可用
if ! command -v jq &> /dev/null; then
log_warn "jq 不可用,跳过 Self-Improving 记录"
return 0
fi
# 构建 JSONL 记录
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
local record=$(cat << EOF
{
"timestamp": "$timestamp",
"error_type": "$error_type",
"error_message": $(echo "$error_message" | jq -Rs .),
"task": $(echo "$task_description" | jq -Rs .),
"command": $(echo "$original_command" | jq -Rs .),
"source": "hermes-delegate",
"context": {
"hermes_version": "$($HERMES_CMD --version 2>/dev/null | head -1 || echo "unknown")",
"platform": "$(uname -s)",
"user": "$(whoami)"
},
"lesson": "TODO: 待分析此错误的根本原因和解决方案"
}
EOF
)
# 追加到记录文件
echo "$record" >> "$SELF_IMPROVING_MEMORY" 2>/dev/null || {
log_warn "无法写入 Self-Improving 记录文件"
return 0
}
log_success "错误记录已保存到: $SELF_IMPROVING_MEMORY"
return 0
}
# 格式化 JSON 输出
format_json_result() {
local success="$1"
local output="$2"
local error="$3"
local duration_ms="$4"
local task_id="$5"
local output_path="$6"
cat << EOF
{
"success": $success,
"task_id": "$task_id",
"output": $(echo "$output" | jq -Rs . 2>/dev/null || echo "\"$(echo "$output" | head -c 1000 | sed 's/"/\\"/g' | tr '\n' ' ')\""),
"error": $(echo "$error" | jq -Rs . 2>/dev/null || echo "\"$(echo "$error" | sed 's/"/\\"/g' | tr '\n' ' ')\""),
"duration_ms": ${duration_ms:-0},
"output_file": "${output_path:-}",
"timestamp": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"hermes_version": "$($HERMES_CMD --version 2>/dev/null | head -1 || echo "unknown")"
}
EOF
}
# ============================================================================
# 主执行函数
# ============================================================================
execute_delegate() {
local task="$1"
local tools="$2"
local timeout_sec="$3"
local context_file="$4"
local output_file="$5"
local max_concurrent="$6"
local verbose="$7"
# 生成任务 ID
local task_id
task_id=$(generate_task_id)
log_info "========== 开始委托任务 =========="
log_info "任务 ID: $task_id"
log_info "任务内容: $task"
[ -n "$tools" ] && log_info "工具限制: $tools"
log_info "超时设置: ${timeout_sec}s"
[ -n "$output_file" ] && log_info "输出文件: $output_file"
log_info "======================================="
# 清理过期锁
cleanup_stale_locks
# 获取并发锁
if ! acquire_lock "$task_id"; then
error_callback "CONCURRENT_LIMIT_REACHED" "达到最大并发限制 ($max_concurrent)" "$task" "hermes_delegate"
format_json_result false "" "并发限制: 无法获取执行锁,已有 $max_concurrent 个任务在运行。稍后重试。" 0 "$task_id" "$output_file"
return 1
fi
# 确保退出时释放锁
trap 'release_lock "$task_id"' EXIT
# 读取上下文文件(如果存在)
local context_content=""
if [ -n "$context_file" ] && [ -f "$context_file" ]; then
context_content=$(cat "$context_file")
log_debug "已加载上下文文件: $context_file ($(wc -c < "$context_file") bytes)"
fi
# 构建提示词
local prompt
prompt=$(build_delegate_prompt "$task" "$tools" "$context_content" "")
[ "$verbose" = true ] && log_debug "生成的提示词:\n$prompt"
# 构建命令
local cmd="$HERMES_CMD run '$prompt' --non-interactive --no-stream --timeout $timeout_sec"
[ -n "$tools" ] && cmd+=" --toolset '$tools'"
[ -n "$context_file" ] && cmd+=" --context-file '$context_file'"
log_info "执行命令: hermes run <prompt> --non-interactive --no-stream --timeout $timeout_sec"
# 记录开始时间
local start_time=$(date +%s%N 2>/dev/null || date +%s)
# 执行命令(带超时保护)
local raw_output=""
local exit_code=0
if command -v timeout &> /dev/null; then
raw_output=$(timeout "$timeout_sec" bash -c "$cmd" 2>&1) || exit_code=$?
else
# fallback: 使用后台进程 + 等待
raw_output=$(bash -c "$cmd" 2>&1) &
local pid=$!
# 等待完成(带手动超时检查)
local waited=0
while kill -0 $pid 2>/dev/null; do
sleep 5
waited=$((waited + 5))
if [ "$waited" -ge "$timeout_sec" ]; then
kill -9 $pid 2>/dev/null || true
exit_code=124 # timeout exit code
break
fi
done
[ $exit_code -eq 0 ] && wait $pid 2>/dev/null || exit_code=$?
raw_output=$(cat "${TMPDIR:-/tmp}/hermes_delegate_out_$$" 2>/dev/null || true)
fi
# 计算耗时
local end_time=$(date +%s%N 2>/dev/null || date +%s)
local duration_ms=0
if [[ "$start_time" =~ ^[0-9]{13}$ ]] && [[ "$end_time" =~ ^[0-9]{13}$ ]]; then
duration_ms=$(( (end_time - start_time) / 1000000 ))
else
duration_ms=$(( (end_time - start_time) * 1000 ))
fi
# 处理结果
case $exit_code in
0)
log_success "任务完成 (${duration_ms}ms)"
# 解析并可能写入文件
parse_output "$raw_output" "$output_file" >/dev/null
format_json_result true "$raw_output" "" "$duration_ms" "$task_id" "$output_file"
;;
124)
log_error "任务超时 (${timeout_sec}s)"
error_callback "TIMEOUT" "任务执行超时 (${timeout_sec}s): $task" "$task" "$cmd"
format_json_result false "" "任务超时: 已等待 ${timeout_sec}s 但任务未完成。建议: 1) 简化任务范围, 2) 增加 --timeout 参数, 3) 减少工具集以降低复杂度。" "$duration_ms" "$task_id" "$output_file"
;;
*)
log_error "任务失败 (退出码: $exit_code)"
[ "$verbose" = true ] && log_error "错误输出: $raw_output"
error_callback "EXECUTION_ERROR" "命令失败 (退出码: $exit_code): ${raw_output:0:500}" "$task" "$cmd"
format_json_result false "$raw_output" "执行失败 (退出码 $exit_code)。可能原因: API Key 无效、网络问题、模型不支持等。运行 \`hermes doctor\` 诊断。" "$duration_ms" "$task_id" "$output_file"
;;
esac
# 释放锁
release_lock "$task_id"
trap - EXIT
return $exit_code
}
# ============================================================================
# 参数解析
# ============================================================================
show_help() {
cat << 'EOF'
Hermes Agent Delegate Script v1.0.0
===================================
用法:
hermes_delegate.sh --task "任务描述" [选项]
必需选项:
--task, -t 任务描述(必需)
可选选项:
--tools, --toolset 限制的工具集(逗号分隔)
可用值: web_search, browser, file_operations,
terminal, memory, code_execution 等
--timeout 超时时间(秒,默认: 300)
--output, -o 输出文件路径(保存原始输出)
--max-concurrent 最大并发数(默认: 3,最大: 3)
--context-file, -c 额外上下文文件路径
-v, --verbose 显示详细调试信息
--dry-run 只显示将要执行的命令,不实际执行
-h, --help 显示帮助信息
示例:
# 基础用法
hermes_delegate.sh --t "研究 React 和 Vue 的性能对比"
# 限制工具和超时
hermes_delegate.sh -t "分析网站 SEO 问题" \
--tools web_search,browser \
--timeout 120
# 带输出文件
hermes_delegate.sh -t "编写单元测试" \
--tools file_operations,code_execution,terminal \
--output ./test_results.md
# 带上下文文件
hermes_delegate.sh -t "根据代码审查反馈修改" \
-c ./review_comments.md \
-o ./changes.md
环境变量:
HERMES_CMD Hermes 命令名称(默认: hermes)
MAX_CONCURRENT_DELEGATES 最大并发数覆盖(默认: 3)
输出格式:
JSON (包含 success, task_id, output, error, duration_ms, output_file 字段)
错误回调:
当任务失败或超时时,自动记录到 Self-Improving 记录文件:
~/.workbuddy/memory/self-improving/learnings.jsonl
限制:
- 最大并发子代理数: 3(Hermes 内部限制)
- 最小超时时间: 10 秒
- 最大超时时间: 3600 秒(1小时)
EOF
}
# ============================================================================
# 入口点
# ============================================================================
main() {
# 默认值
local task=""
local tools=""
local timeout=$DEFAULT_TIMEOUT
local output_file=""
local max_concurrent=$MAX_CONCURRENT_DELEGATES
local context_file=""
local verbose=false
local dry_run=false
# 解析参数
while [[ $# -gt 0 ]]; do
case $1 in
--task|-t)
shift; task="$1"
;;
--tools|--toolset)
shift; tools="$1"
;;
--timeout)
shift
# 验证超时值
if [[ "$1" =~ ^[0-9]+$ ]] && [ "$1" -ge 10 ] && [ "$1" -le 3600 ]; then
timeout="$1"
else
log_error "无效的超时值: $1 (允许范围: 10-3600秒)"
exit 1
fi
;;
--output|-o)
shift; output_file="$1"
;;
--max-concurrent)
shift
if [[ "$1" =~ ^[0-9]+$ ]] && [ "$1" -ge 1 ] && [ "$1" -le 3 ]; then
max_concurrent="$1"
else
log_error "无效的并发数: $1 (允许范围: 1-3)"
exit 1
fi
;;
--context-file|-c)
shift; context_file="$1"
;;
-v|--verbose)
verbose=true
export DEBUG="true"
;;
--dry-run)
dry_run=true
;;
-h|--help|--version)
show_help
exit 0
;;
-*)
log_error "未知选项: $1"
show_help
exit 1
;;
*)
# 第一个非选项参数作为 task
if [ -z "$task" ]; then
task="$1"
else
log_warn "忽略多余参数: $1"
fi
;;
esac
shift
done
# 验证必需参数
if [ -z "$task" ]; then
log_error "缺少必需的 --task 参数"
echo ""
show_help
exit 1
fi
# Dry run 模式
if [ "$dry_run" = true ]; then
log_info "[DRY RUN] 将要执行的委托任务:"
log_info " 任务: $task"
log_info " 工具限制: ${tools:-无限制}"
log_info " 超时: ${timeout}s"
log_info " 输出文件: ${output_file:-无}"
log_info " 上下文文件: ${context_file:-无}"
log_info " 最大并发: $max_concurrent"
exit 0
fi
# 检查依赖
check_dependencies || exit 1
# 执行委托
execute_delegate "$task" "$tools" "$timeout" "$context_file" "$output_file" "$max_concurrent" "$verbose"
}
# 执行主函数
main "$@"
#!/bin/bash
# ============================================================================
# Hermes Agent Wrapper Script for WorkBuddy
# ============================================================================
# 统一的 CLI 封装脚本,提供格式化输出、错误处理和超时保护。
#
# 用法:
# ./hermes_wrapper.sh [命令] [参数...]
#
# 示例:
# ./hermes_wrapper.sh run "分析这个URL的内容" --timeout 60
# ./hermes_wrapper.sh memory search "用户偏好"
# ./hermes_wrapper.sh status
#
# 输出格式: JSON (success, output, error, duration, command)
# ============================================================================
set -euo pipefail
# ============================================================================
# 配置(动态检测,无硬编码路径)
# ============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HERMES_CMD="${HERMES_CMD:-hermes}"
# 按优先级搜索 hermes 安装位置
if ! command -v "$HERMES_CMD" &> /dev/null; then
for candidate in \
"$HOME/.local/bin/hermes" \
"$HOME/.local/hermes-agent/.venv/bin/hermes" \
"$HOME/.workbuddy/binaries/python/envs/default/bin/hermes" \
"$(which hermes 2>/dev/null)"; do
if [ -x "$candidate" ]; then
HERMES_CMD="$candidate"
break
fi
done
fi
DEFAULT_TIMEOUT=300
OUTPUT_MODE="text" # text | json | raw
# 颜色(终端输出时使用)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# ============================================================================
# 工具函数
# ============================================================================
log_info() {
echo -e "${BLUE}[INFO]${NC} $*" >&2
}
log_success() {
echo -e "${GREEN}[OK]${NC} $*" >&2
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $*" >&2
}
# 检查 Hermes 是否安装
check_hermes() {
if ! command -v "$HERMES_CMD" &> /dev/null; then
log_error "Hermes Agent 未找到。"
log_error "请运行安装脚本: bash scripts/install_hermes.sh"
log_error "或将 ~/.local/bin 添加到 PATH: export PATH=\"\$HOME/.local/bin:\$PATH\""
return 1
fi
return 0
}
# 执行 hermes 命令并捕获输出
run_hermes() {
local cmd="$@"
local start_time=$(date +%s%N 2>/dev/null || date +%s)
local exit_code=0
local output=""
local error=""
# 使用临时文件捕获输出和错误
local tmp_output=$(mktemp)
local tmp_error=$(mktemp)
trap 'rm -f "$tmp_output" "$tmp_error"' RETURN
# 执行命令
set +e
eval "$cmd" > "$tmp_output" 2> "$tmp_error" &
local pid=$!
# 等待完成(带超时检查由调用方控制)
wait $pid 2>/dev/null
exit_code=$?
set -e
# 读取输出
output=$(cat "$tmp_output" 2>/dev/null || true)
error=$(cat "$tmp_error" 2>/dev/null || true)
# 计算耗时
local end_time=$(date +%s%N 2>/dev/null || date +%s)
local duration=0
if [[ "$start_time" =~ ^[0-9]{13}$ ]] && [[ "$end_time" =~ ^[0-9]{13}$ ]]; then
duration=$(( (end_time - start_time) / 1000000 )) # 转换为毫秒
else
duration=$(( end_time - start_time ))
fi
# 返回结果
echo "{\"success\":$([ $exit_code -eq 0 ] && echo "true" || echo "false"),\"output\":$(echo "$output" | jq -Rs . 2>/dev/null || echo "\"$(echo "$output" | sed 's/"/\\"/g' | tr '\n' ' ')\""),\"error\":$(echo "$error" | jq -Rs . 2>/dev/null || echo "\"$(echo "$error" | sed 's/"/\\"/g' | tr '\n' ' ')\""),\"exit_code\":$exit_code,\"duration_ms\":$duration,\"command\":\"$(echo "$cmd" | sed 's/"/\\"/g' | head -c 200)\"}"
}
# JSON 格式输出辅助函数
json_output() {
local success="$1"
local output="$2"
local error="$3"
local duration="$4"
local command="$5"
cat << EOF
{
"success": $success,
"output": $(echo "$output" | jq -Rs . 2>/dev/null || echo "\"$(echo "$output" | sed 's/"/\\"/g')\""),
"error": $(echo "$error" | jq -Rs . 2>/dev/null || echo "\"$(echo "$error" | sed 's/"/\\"/g')\""),
"duration_ms": ${duration:-0},
"command": "$(echo "${command:-}" | sed 's/"/\\"/g')"
}
EOF
}
# ============================================================================
# 命令处理
# ============================================================================
# 处理 'run' 命令(单轮执行)
handle_run() {
local prompt=""
local timeout=$DEFAULT_TIMEOUT
local context_file=""
local toolset=""
local model=""
local no_stream=true
local non_interactive=true
local args=()
# 解析参数
while [[ $# -gt 0 ]]; do
case $1 in
--timeout) shift; timeout="${1:-$DEFAULT_TIMEOUT}" ;;
--context-file|-c) shift; context_file="$1" ;;
--toolset|-t) shift; toolset="$1" ;;
--model|-m) shift; model="$1" ;;
--no-stream) no_stream=true ;;
--stream) no_stream=false ;;
--non-interactive) non_interactive=true ;;
--interactive) non_interactive=false ;;
-*|*) args+=("$1") ;; # 收集其他参数作为 prompt 或选项
esac
shift
done
# 第一个非选项参数是 prompt
if [ ${#args[@]} -gt 0 ] && [[ ! "${args[0]}" == -* ]]; then
prompt="${args[0]}"
fi
if [ -z "$prompt" ]; then
json_output false "" "缺少必需的 prompt 参数。用法: hermes_wrapper.sh run \"你的提示词\"" 0 "run"
return 1
fi
log_info "执行 Hermes run: $prompt"
log_info "超时: ${timeout}s, 工具集: ${toolset:-默认}"
# 构建命令
local cmd="$HERMES_CMD run \"$prompt\" --non-interactive"
[ "$no_stream" = true ] && cmd+=" --no-stream"
[ -n "$context_file" ] && cmd+=" --context-file \"$context_file\""
[ -n "$toolset" ] && cmd+=" --toolset \"$toolset\""
[ -n "$model" ] && cmd+=" --model \"$model\""
cmd+=" --timeout $timeout"
# 带超时执行
local result
result=$(timeout $timeout bash -c "$cmd" 2>&1) || true
local exit_code=$?
if [ $exit_code -eq 124 ]; then
json_output false "" "命令超时 (${timeout}s)" "$timeout" "hermes run"
elif [ $exit_code -ne 0 ]; then
json_output false "$result" "命令失败,退出码: $exit_code" 0 "hermes run"
else
json_output true "$result" "" 0 "hermes run"
fi
}
# 处理 'memory' 命令
handle_memory() {
local subcmd="${1:-}"
shift 2>/dev/null || true
case "$subcmd" in
search)
local query="${1:-}"
if [ -z "$query" ]; then
json_output false "" "缺少搜索关键词。用法: hermes_wrapper.sh memory search \"关键词\"" 0 "memory search"
return 1
fi
log_info "搜索记忆: $query"
run_hermes "$HERMES_CMD memory search \"$query\""
;;
list|notes)
log_info "列出记忆笔记"
run_hermes "$HERMES_CMD memory notes list"
;;
add)
local note="${1:-}"
if [ -z "$note" ]; then
json_output false "" "缺少笔记内容。用法: hermes_wrapper.sh memory add \"内容\"" 0 "memory add"
return 1
fi
log_info "添加记忆笔记"
run_hermes "$HERMES_CMD memory notes add \"$note\""
;;
export)
local path="${1:-./memory_backup}"
log_info "导出记忆到: $path"
run_hermes "$HERMES_CMD memory export \"$path\""
;;
import)
local path="${1:-}"
if [ -z "$path" ]; then
json_output false "" "缺少导入路径。用法: hermes_wrapper.sh memory import ./path" 0 "memory import"
return 1
fi
log_info "从路径导入记忆: $path"
run_hermes "$HERMES_CMD memory import \"$path\""
;;
*)
json_output false "" "未知的 memory 子命令: $subcmd. 可用: search, list, add, export, import" 0 "memory"
return 1
;;
esac
}
# 处理 'skills' 命令
handle_skills() {
local subcmd="${1:-list}"
shift 2>/dev/null || true
case "$subcmd" in
list|ls)
log_info "列出所有技能"
run_hermes "$HERMES_CMD skills list"
;;
create)
local name="${1:-}"
local desc="${2:-}"
if [ -z "$name" ]; then
json_output false "" "缺少技能名称。用法: hermes_wrapper.sh skills create 名称 [--description 描述]" 0 "skills create"
return 1
fi
log_info "创建技能: $name"
if [ -n "$desc" ]; then
run_hermes "$HERMES_CMD skills create \"$name\" --description \"$desc\""
else
run_hermes "$HERMES_CMD skills create \"$name\""
fi
;;
edit)
local name="${1:-}"
if [ -z "$name" ]; then
json_output false "" "缺少技能名称。用法: hermes_wrapper.sh skills edit 名称" 0 "skills edit"
return 1
fi
log_info "编辑技能: $name"
run_hermes "$HERMES_CMD skills edit \"$name\""
;;
remove|rm|delete)
local name="${1:-}"
if [ -z "$name" ]; then
json_output false "" "缺少技能名称。用法: hermes_wrapper.sh skills remove 名称" 0 "skills remove"
return 1
fi
log_warn "删除技能: $name"
run_hermes "$HERMES_CMD skills remove \"$name\""
;;
*)
json_output false "" "未知的 skills 子命令: $subcmd. 可用: list, create, edit, remove" 0 "skills"
return 1
;;
esac
}
# 处理 'delegate' 命令(委托给子代理)
handle_delegate() {
local task=""
local tools=""
local timeout=300
local output_file=""
local max_concurrent=3
local context_file=""
local verbose=false
while [[ $# -gt 0 ]]; do
case $1 in
--task|-t) shift; task="$1" ;;
--tools|--toolset) shift; tools="$1" ;;
--timeout) shift; timeout="$1" ;;
--output|-o) shift; output_file="$1" ;;
--max-concurrent) shift; max_concurrent="$1" ;;
--context-file|-c) shift; context_file="$1" ;;
-v|--verbose) verbose=true ;;
*)
if [ -z "$task" ]; then
task="$1"
fi
;;
esac
shift
done
if [ -z "$task" ]; then
cat << EOF
{
"success": false,
"output": "",
"error": "缺少必需的任务描述。用法:\n hermes_wrapper.sh delegate --task \"任务描述\" [选项]\n\n选项:\n --task, -t 任务描述(必需)\n --tools 限制的工具集(逗号分隔)\n --timeout 超时时间(秒,默认300)\n --output, -o 输出文件路径\n --max-concurrent 最大并发数(默认3)\n --context-file 上下文文件\n -v, --verbose 详细输出",
"duration_ms": 0,
"command": "delegate"
}
EOF
return 1
fi
log_info "委托任务: $task"
[ "$verbose" = true ] && log_info "工具限制: ${tools:-无}, 超时: ${timeout}s"
# 构建提示词
local prompt="请使用 delegate_task 工具完成以下任务:\n\n任务: $task"
[ -n "$tools" ] && prompt+="\n可用工具: $tools"
prompt+="\n\n请直接执行任务并返回完整结果。"
# 构建命令
local cmd="$HERMES_CMD run \"$prompt\" --non-interactive --no-stream --timeout $timeout"
[ -n "$context_file" ] && cmd+=" --context-file \"$context_file\""
[ -n "$tools" ] && cmd+=" --toolset \"$tools\""
# 执行
local result
result=$(timeout $timeout bash -c "$cmd" 2>&1) || true
local exit_code=$?
# 如果指定了输出文件,写入文件
if [ -n "$output_file" ]; then
mkdir -p "$(dirname "$output_file")" 2>/dev/null || true
echo "$result" > "$output_file" 2>/dev/null || true
fi
if [ $exit_code -eq 124 ]; then
json_output false "$result" "委托任务超时 (${timeout}s)" "$timeout" "delegate"
elif [ $exit_code -ne 0 ]; then
json_output false "$result" "委托任务失败,退出码: $exit_code" 0 "delegate"
else
json_output true "$result" "" 0 "delegate"
fi
}
# 处理 'status' 和 'doctor' 命令
handle_status() {
log_info "检查 Hermes 状态..."
run_hermes "$HERMES_CMD status" 2>/dev/null || run_hermes "$HERMES_CMD doctor"
}
# 处理 'plugins' 命令
handle_plugins() {
local subcmd="${1:-list}"
shift 2>/dev/null || true
run_hermes "$HERMES_CMD plugins $subcmd $*"
}
# 处理 'cron' 命令
handle_cron() {
local subcmd="${1:-list}"
shift 2>/dev/null || true
run_hermes "$HERMES_CMD cron $subcmd $*"
}
# 显示帮助信息
show_help() {
cat << 'EOF'
Hermes Agent Wrapper Script v1.0.0
===============================
用法:
hermes_wrapper.sh <command> [options]
命令:
run 单轮执行(推荐用于 WorkBuddy 集成)
delegate 委托任务给子代理
memory 记忆管理(search/list/add/export/import)
skills 技能管理(list/create/edit/remove)
plugins 插件管理
cron 定时任务管理
status 检查状态
doctor 运行诊断
help 显示此帮助信息
示例:
hermes_wrapper.sh run "分析这个网页的内容" --timeout 60
hermes_wrapper.sh delegate --t "研究竞品产品" --tools web_search,browser
hermes_wrapper.sh memory search "用户偏好设置"
hermes_wrapper.sh skills list
hermes_wrapper.sh status
环境变量:
HERMES_CMD Hermes 命令路径(默认: 自动检测)
DEFAULT_TIMEOUT 默认超时时间秒数(默认: 300)
输出格式: JSON (包含 success, output, error, duration_ms, command 字段)
EOF
}
# ============================================================================
# 主程序
# ============================================================================
main() {
local command="${1:-help}"
shift 2>/dev/null || true
# 检查是否需要 Hermes(help 和 version 不需要)
if [[ ! "$command" =~ ^(help|--help|-h|version|--version)$ ]]; then
check_hermes || exit 1
fi
# 分发命令
case "$command" in
run|r) handle_run "$@" ;;
delegate|d) handle_delegate "$@" ;;
memory|m) handle_memory "$@" ;;
skills|skill|s) handle_skills "$@" ;;
plugins|p) handle_plugins "$@" ;;
cron|c) handle_cron "$@" ;;
status|st) handle_status ;;
doctor|diag) run_hermes "$HERMES_CMD doctor" ;;
help|--help|-h) show_help ;;
version|--version|-v) run_hermes "$HERMES_CMD --version" ;;
*)
json_output false "" "未知命令: $command。运行 'hermes_wrapper.sh help' 查看帮助。" 0 "$command"
exit 1
;;
esac
}
# 执行主函数
main "$@"
Related skills
How it compares
Choose hermes-agent when sub-agent delegation with durable memory beats doing everything in the primary Claude Code session.
FAQ
What is Hermes Agent in hermes-agent skill?
Hermes Agent is NousResearch's agent runtime that hermes-agent invokes from Claude Code. It handles delegation, durable memory, MCP connections, browser work, and sandboxed code runs as a secondary agent layer.
When should developers use hermes-agent?
hermes-agent fits multi-step tasks needing persistent memory, external MCP tools, browser automation, or isolated code execution that exceed a single Claude Code session's scope.
Is Hermes Agent safe to install?
skills.sh reports 1 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.