# Hermes Agent 中文社区 Full Context Site URL: https://hermesagent.org.cn/ Docs Index JSON: https://hermesagent.org.cn/docs-index.json Releases JSON: https://hermesagent.org.cn/releases.json ## Releases - Hermes Agent v0.17.0(2026-06-19) URL: /docs/releases/v0-17-0 Summary: The Reach release:新增 iMessage via Photon 与 Raft agent network,桌面端补强快捷键、通知、子代理 watch-window、模型预设、VS Code 主题和远程媒体;后台子代理、image_generate 图像编辑、Automation Blueprints、xAI Grok Composer、Dashboard Profile Builder、Skills Hub 预览与安全扫描、memory 原子批量操作、WhatsApp Business Cloud API、Telegram 富文本、Curator 零日常 token 成本以及安全 / Windows / Docker 修复同步落地。 - Hermes Agent v0.16.0(2026-06-05) URL: /docs/releases/v0-16-0 Summary: The Surface release:原生桌面端覆盖 macOS / Linux / Windows,支持应用内自更新、拖拽文件、状态栏模型选择器、多 profile 并发和远程 Gateway 登录;Web Dashboard 升级为完整管理面板,桌面端完成简体中文,Quick Setup via Nous Portal、默认 Skill 瘦身、NVIDIA/skills 可信 tap、全端模糊模型选择、/undo [N] 与 2 个 P0 + 62 个 P1 + 16 个 security-tagged 修复同步落地。 - Hermes Agent v0.15.2(2026-05-29.2) URL: /docs/releases/v0-15-2 Summary: 补丁发布:修复 Python wheel 与 sdist 未携带内置 plugin.yaml manifest 的打包问题,确保通过包管理器安装后内置插件元数据可被正常发现。 - Hermes Agent v0.15.1(2026-05-29) URL: /docs/releases/v0-15-1 Summary: The Patch release:修复 v0.15.0 Dashboard loopback 401 无限刷新、Docker --insecure 显式环境变量、Docker 内 MCP npx/npm/node PATH、Kanban worker SIGTERM、Skills 页面分类、skills.sh 完整 19,932 条目录、/model 与 /yolo 等后续问题。 - Hermes Agent v0.15.0(2026-05-28) URL: /docs/releases/v0-15-0 Summary: The Velocity release:run_agent.py 从 16k 行缩到 3.8k 行、Kanban 多代理平台成熟(自动拆解 / swarm 拓扑 / 定时任务 / worktree-per-task / 每任务模型覆盖)、冷启动继续提速、每轮函数调用减少 47%、session_search 4,500x 且无 LLM 成本、Promptware / Brainworm 防御、Bitwarden Secrets Manager、ntfy 第 23 个消息平台、Skill bundles、TUI 多会话编排、Krea 2 Medium / Large 与 FAL image_gen 插件化、Nous-approved MCP catalog、OpenHands skill、xAI 深度集成、15 个 P0 + 65 个 P1 修复。 - Hermes Agent v0.14.0(2026-05-16) URL: /docs/releases/v0-14-0 Summary: The Foundation release:PyPI 安装、依赖瘦身与 lazy-deps、原生 Windows early beta、SuperGrok OAuth + Grok 1M 上下文、hermes proxy OpenAI-compatible 本地代理、x_search、Teams 端到端、LINE / SimpleX Chat、冷启动少约 19 秒、browser_console 180x、Claude 跨会话 1h prompt cache、/handoff 实时会话转交、LSP 写入诊断、video_generate、computer_use cua-driver、9 个新 optional skill、12 个 P0 + 50 个 P1 修复。 - Hermes Agent v0.13.0(2026-05-07) URL: /docs/releases/v0-13-0 Summary: The Tenacity release:多代理 Kanban 协作板(heartbeat / reclaim / 幻觉门)、/goal 持久目标 Ralph loop、Checkpoints v2、Gateway 会话自动恢复、8 个 P0 安全修复(脱敏默认开 / Discord guild 范围授权 / WhatsApp 默认拒绝陌生人 / MCP OAuth TOCTOU)、Google Chat 第 20 个平台、可插拔 provider、7 国语言 i18n、video_analyze 视频理解、xAI Custom Voices 语音克隆。 - Hermes Agent v0.12.0(2026-04-30) URL: /docs/releases/v0-12-0 Summary: The Curator release:自治 Curator 后台代理、自我改进回路重写、ComfyUI v5 与 TouchDesigner-MCP 默认装备、4 条新推理路径、Microsoft Teams 与腾讯元宝两个新平台、Spotify / Google Meet 原生集成、TUI 冷启动减少 ~57%。 - Hermes Agent v0.11.0(2026-04-23) URL: /docs/releases/v0-11-0 Summary: The Interface release:React/Ink 重写的 TUI、可插拔传输层、原生 AWS Bedrock 与 5 条新推理路径、Codex OAuth 直连 GPT-5.5、QQBot、Dashboard 插件化、/steer 中途干预。 - Hermes Agent v0.10.0(2026-04-16) URL: /docs/releases/v0-10-0 Summary: Nous Tool Gateway:Nous Portal 订阅可直连网页搜索、图像生成、TTS 与浏览器自动化,无需额外 API Key。 - Hermes Agent v0.9.0(2026-04-13) URL: /docs/releases/v0-9-0 Summary: 本地 Web Dashboard、Fast Mode、微信 / 企业微信、iMessage、Termux / Android、备份与导入。 - Hermes Agent v0.8.0(2026-04-08) URL: /docs/releases/v0-8-0 Summary: 后台任务自动通知、/model 动态切换、Gemini 原生支持、MCP OAuth 2.1、日志与配置校验。 - Hermes Agent v0.7.0(2026-04-03) URL: /docs/releases/v0-7-0 Summary: 可插拔记忆提供者、同提供方密钥池、Camofox 浏览器、Inline Diff、API Server 会话连续性。 - 官方 GitHub Releases URL: https://github.com/NousResearch/hermes-agent/releases Summary: 官方版本页,包含标签、时间线和完整英文发布说明。 - 官方 README URL: https://github.com/NousResearch/hermes-agent/blob/main/README.md Summary: Hermes Agent 官方 README 和项目概览。 ## Daily Digest (43) Daily community digest — original WeChat / Feishu group highlights, model benchmarks, Agent / Skill / MCP practice. Each entry: https://hermesagent.org.cn/daily/. Index JSON: https://hermesagent.org.cn/daily-reports.json. - Hermes Agent 中文社区日报 6月26日 URL: https://hermesagent.org.cn/daily/2026-06-26 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月22日 URL: https://hermesagent.org.cn/daily/2026-06-22 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月18日 URL: https://hermesagent.org.cn/daily/2026-06-18 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月17日 URL: https://hermesagent.org.cn/daily/2026-06-17 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月16日 URL: https://hermesagent.org.cn/daily/2026-06-16 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月15日 URL: https://hermesagent.org.cn/daily/2026-06-15 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月11日 URL: https://hermesagent.org.cn/daily/2026-06-11 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月10日 URL: https://hermesagent.org.cn/daily/2026-06-10 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月9日 URL: https://hermesagent.org.cn/daily/2026-06-09 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月4日 URL: https://hermesagent.org.cn/daily/2026-06-04 Summary: 今日汇总 21 条消息,共约 2318 字,预计需要 5 分钟阅读。 - Hermes Agent 中文社区日报 6月3日 URL: https://hermesagent.org.cn/daily/2026-06-03 Summary: Hermes Agent 官方桌面版发布与 Intel Mac 兼容性提醒;跨境电商多 Agent 分工、总指挥 + 执行者协作和从单 Agent 起步的架构建议;群友开源 Kestrel Agent 与轻量级外挂记忆库 AgentMemory;国家超算 Coding Plan、OpenCodeGo 低成本模型接入和主流生图视频模型成本对比;Win10 WSL 特殊字符、低价云服务器 Swap 爆盘、云服务器 24 小时运行、Hermes Linux 内存占用与 4 核 4G 部署建议;Tavily 搜索工具、多模态识别转 Markdown + Office COM 图文排版工作流,以及手写识别能力边界。 - Hermes Agent 中文社区日报 6月2日 URL: https://hermesagent.org.cn/daily/2026-06-02 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 6月1日 URL: https://hermesagent.org.cn/daily/2026-06-01 Summary: Hermes Agent 中文社区启动下一阶段垂直行业群建设并公示入群指南;推荐借助 Claude Code 或 Codex 辅助排查 Hermes 异常并配置 helper profile;提升Hermes浏览器表单操作稳定性的三种实践方案;开源项目 iHermes 支持通过手机端直接控制 Hermes Agent;企业级Hermes私有化部署与数据安全合规实践;Hermes 架构稳定适合生产环境,附 OpenClaw 更新避坑指南;社区推荐 mem0 与 tencentdb-agent-memory 作为 Agent 记忆管理方案;GPT 在 Hermes 中对 soul 人格定义的遵循度优于 DeepSeek;Agent不遵循提示词和调用Skill不积极的根因分析及优化方案;获取A股实时数据推荐Tushare付费接口,网页爬虫易触发IP封禁;利用Hermes Agent配置启发式教学角色辅导作业,结合视觉模型实现拍照解题;利用AI实现电商自动上品的模型选择与工具建议;搜索工具配置建议与Skill资源站分享;Skill机制原理与多Skill加载的Token消耗影响;主流大模型Token消耗效率横向对比;工业场景AI落地建议聚焦固定流程RPA化,避免自主决策;Claude Code 升级至 v2.1.153+ 后第三方模型接口报错,降级至 v2.1.148 可恢复;马维斯与Hermes定位差异及Windows部署建议;配置Hermes生图能力需接入外部API或配置生图Skill,推荐GPT-Image-2结合Seedance2的视频工作流;开源短视频自动生成项目MoneyPrinterTurbo分享;开源工具 SkillClaw 支持 Hermes 持续集体技能进化;推荐RTK终端输出Token压缩代理工具;开源规则管理工具rulesink分享;Claude Code Workflow功能支持固化多Agent长任务流程;OpenAI Codex Pro 额度限时加倍活动持续至 5 月 31 日,具体剩余额度以官方面板为准;Codex Computer use功能支持自动化页面测试,DeepSeek需结合curl测API;开源项目codex-bridge实现Claude Code与DeepSeek模型桥接 - Hermes Agent 中文社区日报 5月29日 URL: https://hermesagent.org.cn/daily/2026-05-29 Summary: 每天 1 分钟,了解 AI Agent 最新资讯。 - Hermes Agent 中文社区日报 5月27日 URL: https://hermesagent.org.cn/daily/2026-05-27 Summary: EchoMind Memory.skill 发布 v1.1.0 版本,支持永久记忆与防幻觉污染;字节开源Agent框架Eino具备低运行时开销与企业级开箱即用特性;分享基于Claude的自动化工作流:自动分析Issue、生成PR并完成Review闭环;推荐AI前端开发工作流:使用GPT Image生成UI设计图,再交由Claude或DS V4 Flash编写代码;法律文书实体提取:本地大模型与纯算法方案对比;配置 Tavily 等第三方 Web Search API 可解决 Hermes 搜索失效问题;OpenCode平台DeepSeek V4 Flash模型免费使用;电商客服场景下通过AI生成正则表达式提取链接SPU信息 - Hermes Agent 中文社区日报 5月26日 URL: https://hermesagent.org.cn/daily/2026-05-26 Summary: Neo4j知识图谱在Agent记忆中的应用;推荐使用 workbuddy 辅助排查与处理 Hermes 运行时的报错问题;Hermes可接入Holographic记忆系统实现纯本地外置记忆;文档与条款分析场景推荐DeepSeek Pro模型;LLM Wiki 知识库挂载由系统自动处理无需手动干预;腾讯推出 Agent 长期记忆服务 TencentDB Agent Memory;视觉模型推荐Doubao-seed-2.0-pro与智谱glm-4.6v-flash;AI小说生成推荐采用多Agent分工架构与RAG知识库结合 - Hermes Agent 中文社区日报 5月25日 URL: https://hermesagent.org.cn/daily/2026-05-25 Summary: Hermes无人值守安全审批的三种模式及配置建议;推荐 Gemini 与 Kimi 作为具备图像识别能力的低成本大模型选项;Hermes Agent 桌面端尝鲜版已发布,正式版预计下周上线;Hermes-web-ui 支持网页端对话功能;Hermes 桌面版已发布,内置完整内核无需命令行安装;实测小米 Mimo 额度可运行 Hermes 但消耗较高;更新后启动变慢可能与Skills文件IO读取有关,建议通过打点排查耗时环节;长会话导致单次请求Token超12w的优化建议 - Hermes Agent 中文社区日报 5月22日 URL: https://hermesagent.org.cn/daily/2026-05-22 Summary: Hermes Agent 中文社区日报 5月22日 · 共 16 条社区摘录,覆盖 AI 模型、Agent 工程实践、本地部署与社区动态。 - Hermes Agent 中文社区日报|5月21日 URL: https://hermesagent.org.cn/daily/2026-05-21 Summary: 搜索功能可配置 Gemini Search API,免费额度已足够日常使用;CLI 中模型修改代码未生效时,可提示其通过 Git 读取未提交变更;Hermes Agent桌面版支持在无WSL的Windows环境直接安装;提示词中需明确卸载目标对象以防Agent误删全部组件;分享Agent开发工作流:先用“grill me”提示词梳理需求与设计,再让Agent直接生成代码;推荐通过CLI接口替代GUI自动化控制飞书等应用;Hermes安装后无需强制配置SOUL.md等文件即可直接使用;社区实测推荐DeepSeek作为高性价比模型接入方案;Hermes Agent多智能体协作配置经验与delegate_task使用避坑;16G显存本地部署Hermes的显存估算与模型选择建议;结合scale-engine工程化工作流构建Hermes智能体;将受限任务封装至 MCP 工具可解决 Hermes 直接输出被拦截的问题;使用 /goal 指令可改善 Hermes 任务中途停止或过度劝阻的现象;开源 Hermes 飞书客户端汉化项目 hermes-feishu-zh;Minimax模型易触发限流报错,建议切换至DeepSeek作为主力;推荐API中转站及cc-switch多节点配置方案;Hermes接入Gemini的OAuth登录配置方法;安装Codex需配置网络代理环境;利用KV-Cache命中与AI总结优化长上下文成本与响应速度;主流大模型API计费模式对比与包月套餐避坑指南;社区推荐第三方Hermes桌面客户端hermes-desktop;OpenRouter连接失败可能因账单地址设为国内导致;Hermes接微信识别图片需确认模型多模态能力与路由配置;Hermes调用DeepSeek V4 Pro需确认API权限已开通;利用Hermes读取源码自动生成LLM智能路由Skill;本地部署多智能体硬件配置与MTP加速避坑指南;魔搭社区API Key获取路径指引;复杂逻辑与高并发场景的模型选型建议;分享 SpiderDemo 专属 GPT 免费 API 额度(1314U)及调用地址;提供飞书知识库文档链接,适用于社区内容沉淀与教程整理;Hermes v2.8结合MT5实盘量化交易策略分享与性能追踪;WSL环境下Hermes读取Ollama本地模型的网络配置排查;Hermes原生支持语音交互及本地模型网页搜索配置要点;配置API Key报401错误的排查与解决;Hermes安装失败常见原因及替代方案;官方提供免登录MCP Server辅助文档查询;微信接入可行性及PC端机器人显示问题;本地大模型部署建议与免费图像识别方案;Windows环境下Hermes操作本地文件主要依赖内置系统脚本命令而非MCP;利用网页版大模型替代API调用可节省费用但仅支持纯文本对话;Hermes多Agent协作需通过agent.md明确边界并配合kanban管理;WSL环境配置需进入安装目录编辑文件且DeepSeek Key支持多实例复用;企业级Agent记忆系统架构建议与上下文管理方案;多Profile与多飞书机器人网关部署方案;飞书流式卡片插件开源项目与配置指南;Docker容器内Gateway启动限制与排错指南;使用免费API中转站的安全风险提示;主流大模型API计费模式与性价比对比;核显运行辅助模型可行性与DeepSeek接口配置避坑;解决Hermes记忆丢失可外接Hindsight或Holographic项目;Windows环境安装Hermes推荐直接使用Git Bash替代WSL;飞书端表格渲染异常可通过安装流式卡片插件解决;为Hermes添加语音输入功能可接入企业微信机器人;Hermes内置os-c-use技能仅支持macOS暂无Windows方案;推荐AI音乐生成工具Suno支持提示词直接创作;Hermes WebUI修复MD文档误注入全量会话上下文问题;调用大模型API防429限流的并发控制经验;Hermes Agent记忆插件推荐gbrain替代方案;Gemini Deep Research更新支持通过MCP对接专有数据;VS Code ACP插件连接云端Agent的配置指南;Hermes飞书客户端汉化及工程化工作流开源项目 - Hermes Agent 中文社区日报|5月20日 URL: https://hermesagent.org.cn/daily/2026-05-20 Summary: Hermes可通过飞书CLI读写飞书文档;企业客服场景建议优先使用Wiki结构化知识库替代纯RAG;推荐Scrapling库解决Agent网页操作反爬验证问题;主流模型指令遵循能力对比与DeepSeek缓存优化建议;Hermes搜索功能配置方案与推荐引擎;推荐OpenAI Computer Use用于视觉自动化调试,开源多模态模型在屏幕控制任务上仍落后于闭源模型;垂直领域科研建议采用“通用大模型+专业数据库/MCP服务”架构;群友评测最近发布的 OpenHuman 开源项目;分享两款适用于Hermes的开源Skill:图像生成与Peekaboo监控;DeepSeek API限时折扣至5月31日;阿里云Coding Plan Lite已下线抢购页面仅为前端展示;海外开发者正在开发 Hermes Agent iOS 版本;多Agent协作前清空Hermes记忆可解决上下文污染导致的性能下降问题;Hermes 微信机器人当前未开放添加到公开群的功能;分享前端UI设计优化资源与Claude Code实战经验;开源项目 browser-use 已适配 Hermes 生态;手动触发上下文压缩指令与Profile技能拆分方案;利用Codex自动化Rebase实现Hermes魔改内核平滑升级 - Hermes Agent 中文社区日报|5月19日 URL: https://hermesagent.org.cn/daily/2026-05-19 Summary: 安全与工程实践并重:提醒警惕来路不明的免费 API 中转站泄露密钥与敏感请求数据;社区分享 AI UI 原型灵感库、每日 Markdown 归档长期任务记忆、按项目维度管理资料提升 Agent 检索效率;金融与数据侧包括东方财富模拟组合、CanIRun.ai 本地模型硬件评估;模型与工具方面整理 DeepSeek V4 Flash 文本模型 + 多模态辅助模型、MiniMax M2.7 高速版、last30days-cn 国内搜索 Skill、知乎开放平台、OpenHuman 本地优先桌面 Agent;工作流实践涵盖 CLI + 飞书 / CalDAV 定时提醒、Google A2A 多智能体协作、Obsidian Markdown 知识库、ui-ux-pro-max-skill 前端设计,以及企业级 Hermes 多网关共享配置的高并发与高可用探索。 - Hermes Agent 中文社区日报 5月15日 URL: https://hermesagent.org.cn/daily/2026-05-15 Summary: Hermes Agent 中文社区日报 5月15日 · 共 14 条社区摘录,覆盖 AI 模型、Agent 工程实践、本地部署与社区动态。 - Hermes Agent 中文社区日报|5月14日 URL: https://hermesagent.org.cn/daily/2026-05-14 Summary: 供应链安全警示:PyPI 包 mistralai 被植入恶意代码,依赖该库的 Hermes 实例需检查并升级;社区开源密集发布 — EchoMind 跨框架长期记忆 Skill(OpenClaw / Hermes / Claude Code / OpenCode 通吃,六类记忆 + 用户反馈强化学习自动调权重)、MiniMax 全模态创作 Hermes Skill(飞书内生图 / 视频 / 语音 / 音乐 MIT 开源)、Frida 游戏逆向 MCP、基于 AstrBot 的 Hermes 企业级单点部署多人共用方案;云端 ComfyUI + Hermes Agent 自动写提示词与分镜,本地无 NVIDIA 显卡也能跑生图视频流水线;多 Agent 协作 — 主从 Agent + 飞书 CLI 实现文档同步与团队协同 / 独立部署 Deerflow 做任务拆解与上下文维护再分发主 Agent;国内 Docker 镜像源现状 + 1Panel 镜像 / 毫秒加速推荐;小米 Mimo API 开放免费额度(审批 2 小时但看账单流水,活动剩 2 周);豆包 Seed 模型 GUI 元素定位能力突出适合自动化操作 Agent;红队自动化走 Claude Code + Opus-4.6 + Kali + 渗透工具 MCP,蓝方建议态势感知 / 蜜罐通过 MCP 接入 Agent;腾讯元宝支持总结手动转发的微信聊天记录;Agent 配置纪律 — soul / memory 遵循「少而精」避免 Token 冗余与权重稀释、顶级模型先跑通 0-1 技能再交弱模型多轮迭代以提升综合能力;金融量化 — XGBoost 权重 / PCA 降维防多因子过拟合、Tushare Pro + QMT + 东方财富妙想多源 + MCP 封装、券商 API 选型 + 盈透 IBKR 免费实时行情;Qwen3-ASR-1.7B 本地部署适合常规但流式长文易报错;树莓派 8GB 可流畅跑多个 Hermes 实例约 15W 适合边缘常驻等。 - Hermes Agent 中文社区日报|5月13日 URL: https://hermesagent.org.cn/daily/2026-05-13 Summary: 社区开源密集发布:Hermes Team Deploy 单服务器 + SSH + 多 Profile 实现团队多用户低成本隔离部署、Scale-Engine 跨 16 个 Agent 平台的工作流引擎、Codex Skill Universe / CODEX Skill UI 提供 Skill 可视化管理 + 按需组合 + 自动推荐与部署链接生成、super-publisher 多平台内容自动化发布;社区维护的 hermes-webui-cn 被推荐为比桌面版更稳定的 Web 交互替代方案;多 Agent 架构经验 — 主模型越权处理子任务走单会话单议题隔离 + DeepSeek V4 Flash + Minimax 双 Agent 组合、本地 Docker 化多实例编排 + 内网 IM Bot 自主协作(参考 ClawManager)、管理与执行节点拆分模型且控制子节点汇报频率防 context 爆;电商 AI 客服自建 vs SaaS 3 万 / 年性价比 + 批量改图擦除 + AI 重绘走 GPT Image 2 或 ComfyUI 工作流;Mac M3 Ultra 256G 本地跑 DeepSeek-V4-Flash GGUF 实测约 26 token/s;DeepSeek 等纯文本模型在 Hermes 看图 → 自动装 Minimax MCP 或切 Qwen 辅助视觉模型、WebUI 图片交互异常时切 IM 端测试;腾讯混元 3D 模型生成服务开放申请;记忆管理 menOS / hindsight / honcho 弥补 Hermes 原生历史会话检索盲区;LLM 桥接路由误配 8 小时烧 2 亿 Token 警示 → 测试阶段必开用量监控与硬限额;量化金融 MT5 + Python + Yahoo Finance 免费实时数据接口;社区版 WebUI 同步上游冲突走强制 Rebase;推荐前端设计 AI 工具 Stitch、上下文管理工具 Spec-Kit、浏览器自动化框架 agent-browser / browser-use 等。 - Hermes Agent 中文社区日报|5月12日 URL: https://hermesagent.org.cn/daily/2026-05-12 Summary: v0.13 自然语言指令直接生成独立子 Agent + 三层架构 + 档案袋方案应对长上下文截断、看板工作流(Kanban v0.13.0)+ 定时任务解耦多 Agent 通信避免 Token 浪费与等待延迟;AgentKey 一 key 聚合 Tavily / Brave / Perplexity + 微博 / 小红书 / B 站 / 知乎 / 抖音等社交搜索数据、本地目录 + LightRAG + ES 实现文档增量知识沉淀;电商全流程结合 RPA 自动上架 + 前置图片分类、ERP 表格批量导入规避长流程上下文丢失、看板架构多智能体独立运行;部门内多用户走虚拟机 / Docker 隔离 + 权限管控、云服务器 + Git 同步实现安全异步开发与本地联动、Mac Mini M4 16G 入门优先 + Windows 走 WSL 兼容;DeepSeek v4Pro 缓存命中率 96%(1.1 亿 Token 不到 15 元)、GLM-5.1 国产代码能力突出、DeepSeek v4 半价仅剩半月 + 智谱 Pro 限流严 + 第三方中转兼容性差、Step 3.5 快但易错 / Minimax 2.7 居中 / DeepSeek v4 质优的 Agent 任务模型实测;多 Gateway 分端口解决多端冲突 + 记忆胶囊跨窗口共享、MiniMax 国内 / 国际版控制台配置区分 + TTS 独立计费效果好、模型工具调用失效排查 + DeepSeek 无视觉走 minimax 辅助;冗余 Skill / Hook / MCP 加剧 Token 消耗 → 让 Agent 自检自动卸载闲置组件控本;推荐 Claude Code 编码 + Hermes 验收 + Trae 轻量需求的分工模式、fireworks-tech-graph 终端架构图工具、Bob macOS 开源翻译工具等。 - Hermes Agent 中文社区日报|5月11日 URL: https://hermesagent.org.cn/daily/2026-05-11 Summary: 社区启动 Hermes Web UI 项目国内本地化适配与镜像加速、一键安装提示词已发布;编程多模型成本对比(DeepSeek V4 Flash 性价比领先、Kimi 限流明显、GLM 价高难抢、商汤偏弱)+ 群友常用模型组合(CC+Opus 4.7 / Hermes+Qwen 3.6 / Codex+GPT 5.5);商汤日日新、OpenRouter、英伟达官网免费额度盘点 + LiteLLM Proxy 精确监控 Token;DeepSeek 通过 API 调 Minimax 补多模态识图、MiniMax 全模态 MCP 服务接入图片理解与网络搜索;SOUL.md + 本地 Markdown 实现跨端对话上下文衔接、hermes profile 配置多模型路由与角色分工 + 多 Profile 隔离实现各消息平台独立模型;本地部署走 vLLM MTP 推测解码提速 1.5-2 倍、云服务器 / NAS / Mac mini 24 小时运行选型(轻量云年费百元内)、hermes backup / import 一键迁移、Windows 原生 early beta 已上线;竖排繁体字 OCR 切割预处理提升识别率、群友开源 multi-agent-chat 多智能体广播群聊 CLI、飞书长文本断联与 MD 表格渲染异常临时解、第三方 EKKOLearnAI/hermes-web-ui 开源 WebUI 推荐等。 - Hermes Agent 中文社区日报 5月9日 URL: https://hermesagent.org.cn/daily/2026-05-09 Summary: Hermes Agent 中文社区日报 5月9日 · 共 18 条社区摘录,覆盖 AI 模型、Agent 工程实践、本地部署与社区动态。 - Hermes Agent 中文社区日报 5月8日 URL: https://hermesagent.org.cn/daily/2026-05-08 Summary: Hermes Agent 中文社区日报 5月8日 · 共 18 条社区摘录,覆盖 AI 模型、Agent 工程实践、本地部署与社区动态。 - Hermes Agent 中文社区日报|5月7日 URL: https://hermesagent.org.cn/daily/2026-05-07 Summary: 硅基流动 16 元注册余额 + 美团 Longcat 每日 5000 万 token 免费额度;DGX Spark 单台跑 Gemma4 31B FP16 约 7tok/s、26B A4B NVFP4 量化 52tok/s、Qwen3.6-35B-A3B 建议开 NVFP4;复杂工具调用 MCP 比原生 Skill 稳,Skill 不触发时让 Agent 自我审计或换模型;社区开源 hermes-control-interface 控制层 UI、cc-switch 多密钥免登录、hermes-web-ui 第三方面板、天枢 mineru-tianshu 多模态预处理;Coding Agent 架构建议(Hermes 当 PM、Claude Code/Codex 执行、OpenSpec 做 SDD、Python + CLI/Server 原子化)、量化 Agent 策略与决策分离 + 因子去重 + LLM 直出 JSON;火山引擎 mem0 免费记忆、browser-harness 加速浏览器自动化、Hermes 接入个人微信 + clawBot 安卓常驻、deepseek-v4-flash + Minimax + Opencode GO 订阅性价比、memory.md 精简 + Skill 完善大于换模型,以及本地部署上下文 ≥64K 与 CORS 配置等社区实战。 - Hermes Agent 中文社区日报|5月6日 URL: https://hermesagent.org.cn/daily/2026-05-06 Summary: Hermes 2026.5.3 测试版发布(内置 16MB 文件传输插件、/steer 与 /side 命令、启动提速 40%);DeepSeek 缓存调优把 prompt 长度对齐 128 倍数命中率到 98%;多模型路由 LiteLLM + 9router、Obsidian + LiteLLM 构建外部知识库与免费额度调度;云端大模型带本地小模型的混合架构、2 核 2G 轻量云足够跑 Hermes;soul.md 提升拟人化、Kami 控制输出格式、nuwa-skill 一键打包推 GitHub;以及飞书权限 / 扫码授权坑、跨渠道会话隔离、企微适配器源码修复、个人订阅号半自动化 docx 导草稿等社区实战。 - Hermes Agent 中文社区日报|5月5日 URL: https://hermesagent.org.cn/daily/2026-05-05 Summary: 企业级 Agent 架构选型(OpenFang / Dify / Slock.ai)、TradingAgents 多智能体量化框架、AI 浏览器 Tabbit 网页采集,以及商汤 / 富途 / 智云 AI STORE / 小米 MiMo / 英伟达 / 阿里百炼等多家免费 Token 与 API 资源整理;mem0 记忆系统魔改、html-ppt / guizang-ppt 两款 PPT Skill、Agent 人格三层结构、yolo 自动确认、/new 重置会话;以及 Hermes 多 Agent 配置、模型自动切换与 V4-Flash / V4-Pro / GLM-5.1 多模型路由、hermes-web-ui / hermes-desktop 与 awesome-openclaw-usecases 的社区实战。 - Hermes Agent 中文社区日报|5月4日 URL: https://hermesagent.org.cn/daily/2026-05-04 Summary: 开源 AI 法律平台 mike 拿到 1.4k star,社区站上线文档 MCP 端点;Claude Code 与 Hermes Agent 的场景区分、Agent 记忆分层与遗忘机制、多 Agent 通信受限的替代方案,以及 Skill 工具索引占 token 的隔离办法;外加飞书 API 免费额度接入、长消息自动分段、MiniMax 套餐对比与 Tavily / Agent Browser 等工具实战。 - Hermes Agent 中文社区日报|5月3日 URL: https://hermesagent.org.cn/daily/2026-05-03 Summary: 4 款开源 Skill 首发(mark-heartflow / gpt-image-2 / flowboost / wechat-qq-sender),ComfyUI 联调与 GGUF 量化部署、反爬方案组合(Tavily / DuckDuckGo / Crawl4AI / CDP)、双区记忆优化与 DeepSeek 缓存命中策略,以及多 Agent 架构反思、Warp / LM Studio / DeepSeek-TUI 等社区工具实战。 - Hermes Agent 中文社区日报|4月30日 URL: https://hermesagent.org.cn/daily/2026-04-30 Summary: ICLR 2026「推理陷阱」论文、中美 AI 体系控制博弈、国产算力芯片商业化拐点,以及腾讯 Hy3-Preview 免费模型、doctor 自诊断命令、飞书知识库问答机器人与 Workspace 多 profile 管理的社区实战。 - Hermes Agent 中文社区日报|4月29日 URL: https://hermesagent.org.cn/daily/2026-04-29 Summary: llama.cpp 长上下文崩溃、多 Agent 协作架构、MiMo 百万亿 Token 激励、HeartFlow 心理分析技能,以及 TTS 接入、Docker 浏览器、Skill 精简与记忆系统排障的社区实战。 - Hermes Agent 中文社区日报|4月28日 URL: https://hermesagent.org.cn/daily/2026-04-28 Summary: Claude Agent Memory、OpenAI AGI 五原则框架,以及 Hermes 高级配置、DeepSeek-V4 选型、WSL 本地部署、ex-skill 等社区实战。 - Hermes Agent 中文社区日报|4月27日 URL: https://hermesagent.org.cn/daily/2026-04-27 Summary: GPT-5.5 Spud 发布、DeepSeek V4 开源、Anthropic Mythos 泄露、GPT-Image-2 登顶,以及飞书集成、本地部署与模型选型的社区实战经验。 - Hermes Agent 中文社区日报|4月24日 URL: https://hermesagent.org.cn/daily/2026-04-24 Summary: Awesome Hermes Agent 清单上线、DeepSeek-V4 开源,SCALE OS、反幻觉四原则技能库,以及本地部署与模型切换的社区观察。 - Hermes Agent 中文社区日报|4月23日 URL: https://hermesagent.org.cn/daily/2026-04-23 Summary: Nous Portal 限免 Kimi K2.6 24 小时、腾讯混元 Hy3-preview 开放,阿里/MiniMax/小米多家 Coding Plan 与本地部署经验整理。 - Hermes Agent 中文社区日报|4月22日 URL: https://hermesagent.org.cn/daily/2026-04-22 Summary: DESIGN.md、Scarf、Obscura,以及本地部署、模型切换与企业微信配置的最新社区观察。 - Hermes Agent 中文社区日报|4月21日 URL: https://hermesagent.org.cn/daily/2026-04-21 Summary: 上下文管理、Web UI、多模态 MCP 与本地模型部署经验汇总。 - Hermes Agent 中文社区日报 4月20日 URL: https://hermesagent.org.cn/daily/2026-04-20 Summary: Hermes Agent 中文社区日报 4月20日 · 共 23 条社区摘录,覆盖 AI 模型、Agent 工程实践、本地部署与社区动态。 - Hermes Agent 中文社区日报 4月19日 URL: https://hermesagent.org.cn/daily/2026-04-19 Summary: Hermes Agent 中文社区日报 4月19日 · 共 19 条社区摘录,覆盖 AI 模型、Agent 工程实践、本地部署与社区动态。 ## All Docs (361) ### ACP 内部结构 - URL: https://hermesagent.org.cn/docs/developer-guide/acp-internals - Path: developer-guide/acp-internals.md - Category: developer-guide - Description: ACP 适配器的工作原理:生命周期、会话、事件桥接、审批流程以及工具渲染 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/acp-internals.md - Translated At: 2026-04-11T03:21:26.042Z - Headings: 启动流程 | 主要组件 | HermesACPAgent | SessionManager | 事件桥接 | 权限桥接 | 工具渲染辅助函数 | 会话生命周期 | 取消操作 | 分叉操作 | 提供者/认证行为 | 工作目录绑定 # ACP 内部机制 {#acp-internals} ACP 适配器将 Hermes 的同步 `AIAgent` 包装为一个异步 JSON-RPC 标准输入/输出(stdio)服务器。 关键实现文件: - `acp_adapter/entry.py` - `acp_adapter/server.py` - `acp_adapter/session.py` - `acp_adapter/events.py` - `acp_adapter/permissions.py` - `acp_adapter/tools.py` - `acp_adapter/auth.py` - `acp_registry/agent.json` ## 启动流程 {#boot-flow} ```text hermes acp / hermes-acp / python -m acp_adapter -> acp_adapter.entry.main() -> load ~/.hermes/.env -> configure stderr logging -> construct HermesACPAgent -> acp.run_agent(agent) ``` 标准输出(stdout)保留用于 ACP JSON-RPC 传输。人类可读的日志输出到标准错误(stderr)。 ## 主要组件 {#major-components} ### `HermesACPAgent` {#hermesacpagent} `acp_adapter/server.py` 实现了 ACP Agent 协议。 职责包括: - 初始化 / 认证 - 新建 / 加载 / 恢复 / 分叉 / 列出 / 取消会话方法 - 提示执行 - 会话模型切换 - 将同步的 `AIAgent` 回调连接到 ACP 的异步通知机制 ### `SessionManager` {#sessionmanager} `acp_adapter/session.py` 跟踪当前活跃的 ACP 会话。 每个会话存储以下信息: - `session_id` - `agent` - `cwd` - `model` - `history` - `cancel_event` 该管理器是线程安全的,支持: - 创建 - 获取 - 移除 - 分叉 - 列出 - 清理 - 工作目录(cwd)更新 ### 事件桥接 {#event-bridge} `acp_adapter/events.py` 将 `AIAgent` 的回调转换为 ACP 的 `session_update` 事件。 桥接的回调包括: - `tool_progress_callback` - `thinking_callback` - `step_callback` - `message_callback` 由于 `AIAgent` 在工作线程中运行,而 ACP I/O 在主线程事件循环中运行,因此桥接使用: ```python asyncio.run_coroutine_threadsafe(...) ``` ### 权限桥接 {#permission-bridge} `acp_adapter/permissions.py` 将危险的终端确认提示转换为 ACP 的权限请求。 映射关系如下: - `allow_once` → Hermes `once` - `allow_always` → Hermes `always` - 拒绝选项 → Hermes `deny` 超时或桥接失败时,默认拒绝。 ### 工具渲染辅助函数 {#tool-rendering-helpers} `acp_adapter/tools.py` 将 Hermes 工具映射到 ACP 工具类型,并构建面向编辑器的显示内容。 示例: - `patch` / `write_file` → 文件差异(diff) - `terminal` → Shell 命令文本 - `read_file` / `search_files` → 文本预览 - 大型结果 → 截断的文本块,确保 UI 安全 ## 会话生命周期 {#session-lifecycle} ```text new_session(cwd) -> create SessionState -> create AIAgent(platform="acp", enabled_toolsets=["hermes-acp"]) -> bind task_id/session_id to cwd override prompt(..., session_id) -> extract text from ACP content blocks -> reset cancel event -> install callbacks + approval bridge -> run AIAgent in ThreadPoolExecutor -> update session history -> emit final agent message chunk ``` ### 取消操作 {#cancelation} `cancel(session_id)`: - 设置会话取消事件 - 若可用则调用 `agent.interrupt()` - 导致提示响应返回 `stop_reason="cancelled"` ### 分叉操作 {#forking} `fork_session()` 将消息历史深度复制到一个新的活跃会话中,保留对话状态,同时为分叉会话分配独立的 `session_id` 和 `cwd`。 ## 提供者/认证行为 {#providerauth-behavior} ACP 未实现自己的认证存储。 而是复用 Hermes 的运行时解析器: - `acp_adapter/auth.py` - `hermes_cli/runtime_provider.py` 因此,ACP 宣告并使用当前配置的 Hermes 提供者/凭证。 ## 工作目录绑定 {#working-directory-binding} ACP 会话携带编辑器的工作目录(cwd)。 会话管理器通过任务作用域的终端/文件覆盖机制,将该 cwd 绑定到 ACP 会话 ID,使得文件和终端工具的操作均相对于编辑器工作区进行。 ## 同名工具调用重复问题 {#duplicate-same-name-tool-calls} 事件桥接按工具名称维护 FIFO 队列(先进先出),而非仅每个名称一个 ID。这一点对于以下情况至关重要: - 并行的同名调用 - 单步中重复的同名调用 若无 FIFO 队列,完成事件将错误地关联到错误的工具调用。 ## 批准回调恢复 {#approval-callback-restoration} ACP 在提示执行期间临时安装一个终端工具的批准回调,执行完成后恢复之前的回调。这避免了将 ACP 会话特定的批准处理器永久全局安装。 ## 当前限制 {#current-limitations} - 从 ACP 服务器的角度看,ACP 会话是进程本地的 - 非文本提示块目前在请求文本提取时被忽略 - 编辑器特定的用户体验因 ACP 客户端实现而异 ## 相关文件 {#related-files} - `tests/acp/` — ACP 测试套件 - `toolsets.py` — `hermes-acp` 工具集定义 - `hermes_cli/main.py` — `hermes acp` CLI 子命令 - `pyproject.toml` — `[acp]` 可选依赖项 + `hermes-acp` 脚本 --- ### 添加平台适配器 { adding a platform adapter} - URL: https://hermesagent.org.cn/docs/developer-guide/adding-platform-adapters - Path: developer-guide/adding-platform-adapters.md - Category: developer-guide - Description: 本指南介绍如何向 Hermes 网关添加新的消息传递平台。平台适配器将 Hermes 连接到外部消息服务(Telegram、Discord、企业微信等),以便用户可以通过该服务与代理进行交互。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/adding-platform-adapters.md - Translated At: 2026-05-03T17:15:39.940Z - Headings: 架构概述 | 逐步检查清单 | 1. 平台枚举 | 2. 适配器文件 | 3. 网关配置 (gateway/config.py) | 4. 网关运行器 (gateway/run.py) | 5. 跨平台交付 | 6. CLI 集成 | 7. 工具 | 8. 工具集 | 9. 可选:平台提示 | 10. 测试 # 添加平台适配器 {#adding-a-platform-adapter} 本指南介绍如何向 Hermes 网关添加新的消息传递平台。平台适配器将 Hermes 连接到外部消息服务(Telegram、Discord、企业微信等),以便用户可以通过该服务与代理进行交互。 :::tip 添加平台适配器会涉及代码、配置和文档中 20 多个文件。请将本指南用作检查清单——适配器文件本身通常只占工作量的 40%。 ::: ## 架构概述 {#architecture-overview} ``` User ↔ Messaging Platform ↔ Platform Adapter ↔ Gateway Runner ↔ AIAgent ``` 每个适配器都扩展自 `gateway/platforms/base.py` 中的 `BasePlatformAdapter` 并实现以下方法: - **`connect()`** — 建立连接(WebSocket、长轮询、HTTP 服务器等) - **`disconnect()`** — 干净关闭 - **`send()`** — 向聊天发送文本消息 - **`send_typing()`** — 显示输入指示器(可选) - **`get_chat_info()`** — 返回聊天元数据 入站消息由适配器接收,并通过 `self.handle_message(event)` 转发,基类将其路由到网关运行器。 ## 逐步检查清单 {#step-by-step-checklist} ### 1. 平台枚举 {#1-platform-enum} 在 `gateway/config.py` 的 `Platform` 枚举中添加你的平台: ```python class Platform(str, Enum): # ... existing platforms ... NEWPLAT = "newplat" ``` ### 2. 适配器文件 {#2-adapter-file} 创建 `gateway/platforms/newplat.py`: ```python from gateway.config import Platform, PlatformConfig from gateway.platforms.base import ( BasePlatformAdapter, MessageEvent, MessageType, SendResult, ) def check_newplat_requirements() -> bool: """Return True if dependencies are available.""" return SOME_SDK_AVAILABLE class NewPlatAdapter(BasePlatformAdapter): def __init__(self, config: PlatformConfig): super().__init__(config, Platform.NEWPLAT) # Read config from config.extra dict extra = config.extra or {} self._api_key = extra.get("api_key") or os.getenv("NEWPLAT_API_KEY", "") async def connect(self) -> bool: # Set up connection, start polling/webhook self._mark_connected() return True async def disconnect(self) -> None: self._running = False self._mark_disconnected() async def send(self, chat_id, content, reply_to=None, metadata=None): # Send message via platform API return SendResult(success=True, message_id="...") async def get_chat_info(self, chat_id): return {"name": chat_id, "type": "dm"} ``` 对于入站消息,构建一个 `MessageEvent` 并调用 `self.handle_message(event)`: ```python source = self.build_source( chat_id=chat_id, chat_name=name, chat_type="dm", # or "group" user_id=user_id, user_name=user_name, ) event = MessageEvent( text=content, message_type=MessageType.TEXT, source=source, message_id=msg_id, ) await self.handle_message(event) ``` ### 3. 网关配置 (`gateway/config.py`) {#3-gateway-config-gatewayconfigpy} 三个接触点: 1. **`get_connected_platforms()`** — 添加对你平台所需凭据的检查 2. **`load_gateway_config()`** — 添加令牌环境变量映射条目:`Platform.NEWPLAT: "NEWPLAT_TOKEN"` 3. **`_apply_env_overrides()`** — 将所有 `NEWPLAT_*` 环境变量映射到配置 ### 4. 网关运行器 (`gateway/run.py`) {#4-gateway-runner-gatewayrunpy} 五个接触点: 1. **`_create_adapter()`** — 添加 `elif platform == Platform.NEWPLAT:` 分支 2. **`_is_user_authorized()` allowed_users 映射** — `Platform.NEWPLAT: "NEWPLAT_ALLOWED_USERS"` 3. **`_is_user_authorized()` allow_all 映射** — `Platform.NEWPLAT: "NEWPLAT_ALLOW_ALL_USERS"` 4. **早期环境变量检查 `_any_allowlist` 元组** — 添加 `"NEWPLAT_ALLOWED_USERS"` 5. **早期环境变量检查 `_allow_all` 元组** — 添加 `"NEWPLAT_ALLOW_ALL_USERS"` 6. **`_UPDATE_ALLOWED_PLATFORMS` 冻结集合 (frozenset)** — 添加 `Platform.NEWPLAT` ### 5. 跨平台交付 {#5-cross-platform-delivery} 1. **`gateway/platforms/webhook.py`** — 将 `"newplat"` 添加到交付类型元组中 2. **`cron/scheduler.py`** — 添加到 `_KNOWN_DELIVERY_PLATFORMS` 冻结集合和 `_deliver_result()` 平台映射中 ### 6. CLI 集成 {#6-cli-integration} 1. **`hermes_cli/config.py`** — 将所有 `NEWPLAT_*` 变量添加到 `_EXTRA_ENV_KEYS` 2. **`hermes_cli/gateway.py`** — 在 `_PLATFORMS` 列表中添加条目,包含键、标签、emoji、token_var、setup_instructions 和 vars 3. **`hermes_cli/platforms.py`** — 添加带有 label 和 default_toolset 的 `PlatformInfo` 条目(由 `skills_config` 和 `tools_config` TUI 使用) 4. **`hermes_cli/setup.py`** — 添加 `_setup_newplat()` 函数(可以委托给 `gateway.py`)并将元组添加到消息传递平台列表中 5. **`hermes_cli/status.py`** — 添加平台检测条目:`"NewPlat": ("NEWPLAT_TOKEN", "NEWPLAT_HOME_CHANNEL")` 6. **`hermes_cli/dump.py`** — 在平台检测字典中添加 `"newplat": "NEWPLAT_TOKEN"` ### 7. 工具 {#7-tools} 1. **`tools/send_message_tool.py`** — 在平台映射中添加 `"newplat": Platform.NEWPLAT` 2. **`tools/cronjob_tools.py`** — 在交付目标描述字符串中添加 `newplat` ### 8. 工具集 {#8-toolsets} 1. **`toolsets.py`** — 使用 `_HERMES_CORE_TOOLS` 添加 `"hermes-newplat"` 工具集定义 2. **`toolsets.py`** — 将 `"hermes-newplat"` 添加到 `"hermes-gateway"` 包含列表中 ### 9. 可选:平台提示 {#9-optional-platform-hints} **`agent/prompt_builder.py`** — 如果你的平台有特定的渲染限制(无 markdown、消息长度限制等),请在 `_PLATFORM_HINTS` 字典中添加条目。这会将平台特定的指导注入系统提示中: ```python _PLATFORM_HINTS = { # ... "newplat": ( "You are chatting via NewPlat. It supports markdown formatting " "but has a 4000-character message limit." ), } ``` 并非所有平台都需要提示——仅当代理的行为应有所不同时才添加。 ### 10. 测试 {#10-tests} 创建 `tests/gateway/test_newplat.py`,涵盖: - 从配置构建适配器 - 构建消息事件 - 发送方法(模拟外部 API) - 平台特定功能(加密、路由等) ### 11. 文档 {#11-documentation} | 文件 | 添加内容 | |------|-------------| | `website/docs/user-guide/messaging/newplat.md` | 完整的平台设置页面 | | `website/docs/user-guide/messaging/index.md` | 平台比较表、架构图、工具集表、安全部分、下一步链接 | | `website/docs/reference/environment-variables.md` | 所有 NEWPLAT_* 环境变量 | | `website/docs/reference/toolsets-reference.md` | hermes-newplat 工具集 | | `website/docs/integrations/index.md` | 平台链接 | | `website/sidebars.ts` | 文档页面的侧边栏条目 | | `website/docs/developer-guide/architecture.md` | 适配器计数 + 列表 | | `website/docs/developer-guide/gateway-internals.md` | 适配器文件列表 | ## 一致性审计 {#parity-audit} 在将新平台 PR 标记为完成之前,针对已建立的平台运行一致性审计: ```bash # Find every .py file mentioning the reference platform search_files "bluebubbles" output_mode="files_only" file_glob="*.py" # Find every .py file mentioning the new platform search_files "newplat" output_mode="files_only" file_glob="*.py" # Any file in the first set but not the second is a potential gap ``` 对 `.md` 和 `.ts` 文件重复此操作。调查每个差距——它是平台枚举(需要更新)还是平台特定引用(跳过)? ## 常见模式 {#common-patterns} ### 长轮询适配器 {#long-poll-adapters} 如果您的适配器使用长轮询(如 Telegram 或微信),请使用轮询循环任务: ```python async def connect(self): self._poll_task = asyncio.create_task(self._poll_loop()) self._mark_connected() async def _poll_loop(self): while self._running: messages = await self._fetch_updates() for msg in messages: await self.handle_message(self._build_event(msg)) ``` ### 回调/Webhook 适配器 {#callbackwebhook-adapters} 如果平台将消息推送到您的端点(如企业微信回调),请运行 HTTP 服务器: ```python async def connect(self): self._app = web.Application() self._app.router.add_post("/callback", self._handle_callback) # ... start aiohttp server self._mark_connected() async def _handle_callback(self, request): event = self._build_event(await request.text()) await self._message_queue.put(event) return web.Response(text="success") # Acknowledge immediately ``` 对于具有严格响应时限的平台(例如企业微信的 5 秒限制),请务必立即确认,并稍后通过 API 主动发送助手的回复。助手会话持续 3–30 分钟——在回调响应窗口内同步返回回复是不可行的。 ### 令牌锁 {#token-locks} 如果适配器持有具有唯一凭证的持久连接,请添加作用域锁以防止两个配置文件使用相同的凭证: ```python from gateway.status import acquire_scoped_lock, release_scoped_lock async def connect(self): if not acquire_scoped_lock("newplat", self._token): logger.error("Token already in use by another profile") return False # ... connect async def disconnect(self): release_scoped_lock("newplat", self._token) ``` ## 参考实现 {#reference-implementations} | 适配器 | 模式 | 复杂度 | 适合参考的场景 | |---------|---------|------------|-------------------| | `bluebubbles.py` | REST + webhook | 中等 | 简单的 REST API 集成 | | `weixin.py` | 长轮询 + CDN | 高 | 媒体处理、加密 | | `wecom_callback.py` | 回调/webhook | 中等 | HTTP 服务器、AES 加密、多应用 | | `telegram.py` | 长轮询 + Bot API | 高 | 支持群组和线程的全功能适配器 | --- ### 添加提供者 - URL: https://hermesagent.org.cn/docs/developer-guide/adding-providers - Path: developer-guide/adding-providers.md - Category: developer-guide - Description: 如何向 Hermes Agent 添加新的推理提供者 —— 认证、运行时解析、CLI 流程、适配器、测试和文档 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/adding-providers.md - Translated At: 2026-04-11T03:22:02.237Z - Headings: 心智模型 | 首先选择实现路径 | 路径 A —— 兼容 OpenAI 的提供者 | 路径 B —— 原生提供者 | 文件清单 | 每个内置提供者必需的文件 | 原生 / 非 OpenAI 提供者所需的额外文件 | 第一步:选择一个唯一的提供者 ID | 第二步:在 hermes cli/auth.py 中添加认证元数据 | 第三步:在 hermes cli/models.py 中添加模型目录和别名 | 第四步:在 hermes cli/runtime provider.py 中解析运行时数据 | 第 5 步:在 hermes cli/main.py 中连接 CLI # 添加提供者 {#adding-providers} Hermes 已经可以通过自定义提供者路径与任何兼容 OpenAI 的端点通信。除非你希望该服务获得一流的用户体验,否则不要添加内置提供者: - 提供商特定的认证或令牌刷新机制 - 经过筛选的模型目录 - 设置 / `hermes model` 菜单项 - `provider:model` 语法的提供者别名 - 需要适配器的非 OpenAI API 形式 如果该提供者仅仅是“另一个兼容 OpenAI 的基础 URL 和 API 密钥”,那么命名的自定义提供者可能就足够了。 ## 心智模型 {#the-mental-model} 一个内置提供者必须在多个层面保持一致: 1. `hermes_cli/auth.py` 决定如何查找凭据。 2. `hermes_cli/runtime_provider.py` 将凭据转换为运行时数据: - `provider` - `api_mode` - `base_url` - `api_key` - `source` 3. `run_agent.py` 使用 `api_mode` 来决定如何构建和发送请求。 4. `hermes_cli/models.py` 和 `hermes_cli/main.py` 使提供者在 CLI 中显示出来。(`hermes_cli/setup.py` 会自动委托给 `main.py` —— 无需在此处做任何更改。) 5. `agent/auxiliary_client.py` 和 `agent/model_metadata.py` 保持辅助任务和令牌预算功能正常运行。 关键抽象是 `api_mode`。 - 大多数提供者使用 `chat_completions`。 - Codex 使用 `codex_responses`。 - Anthropic 使用 `anthropic_messages`。 - 新的非 OpenAI 协议通常意味着添加一个新的适配器和一个新的 `api_mode` 分支。 ## 首先选择实现路径 {#choose-the-implementation-path-first} ### 路径 A —— 兼容 OpenAI 的提供者 {#path-a-—-openai-compatible-provider} 当提供者接受标准的 chat-completions 风格请求时使用此路径。 典型工作内容: - 添加认证元数据 - 添加模型目录 / 别名 - 添加运行时解析 - 添加 CLI 菜单连接 - 添加辅助模型默认值 - 添加测试和用户文档 通常不需要新的适配器或新的 `api_mode`。 ### 路径 B —— 原生提供者 {#path-b-—-native-provider} 当提供者的行为不同于 OpenAI 的 chat completions 时使用此路径。 当前树中示例: - `codex_responses` - `anthropic_messages` 此路径包含路径 A 的所有内容,并额外包括: - `agent/` 中的提供者适配器 - `run_agent.py` 中针对请求构建、分发、使用量提取、中断处理和响应归一化的分支 - 适配器测试 ## 文件清单 {#file-checklist} ### 每个内置提供者必需的文件 {#required-for-every-built-in-provider} 1. `hermes_cli/auth.py` 2. `hermes_cli/models.py` 3. `hermes_cli/runtime_provider.py` 4. `hermes_cli/main.py` 5. `agent/auxiliary_client.py` 6. `agent/model_metadata.py` 7. 测试文件 8. 用户文档,位于 `website/docs/` 下 :::tip `hermes_cli/setup.py` **不需要**修改。设置向导会自动将提供者/模型选择委托给 `main.py` 中的 `select_provider_and_model()` —— 任何添加到该函数中的提供者都会自动在 `hermes setup` 中可用。 ::: ### 原生 / 非 OpenAI 提供者所需的额外文件 {#additional-for-native--non-openai-providers} 10. `agent/_adapter.py` 11. `run_agent.py` 12. 如果需要提供者 SDK,则需修改 `pyproject.toml` ## 第一步:选择一个唯一的提供者 ID {#step-1-pick-one-canonical-provider-id} 选择一个唯一的提供者 ID,并在所有地方使用它。 仓库中的示例: - `openai-codex` - `kimi-coding` - `minimax-cn` 该 ID 应出现在以下位置: - `hermes_cli/auth.py` 中的 `PROVIDER_REGISTRY` - `hermes_cli/models.py` 中的 `_PROVIDER_LABELS` - `hermes_cli/auth.py` 和 `hermes_cli/models.py` 中的 `_PROVIDER_ALIASES` - `hermes_cli/main.py` 中 CLI `--provider` 的选项 - 设置 / 模型选择分支 - 辅助模型默认值 - 测试用例 如果这些文件中的 ID 不一致,该提供者将表现为“半连接”:认证可能有效,但 `/model`、设置或运行时解析可能会静默失败。 ## 第二步:在 `hermes_cli/auth.py` 中添加认证元数据 {#step-2-add-auth-metadata-in-hermes_cliauthpy} 对于基于 API 密钥的提供者,在 `PROVIDER_REGISTRY` 中添加一个 `ProviderConfig` 条目,包含: - `id` - `name` - `auth_type="api_key"` - `inference_base_url` - `api_key_env_vars` - 可选的 `base_url_env_var` 同时在 `_PROVIDER_ALIASES` 中添加别名。 请参考现有提供者作为模板: - 简单的 API 密钥路径:Z.AI、MiniMax - 带端点检测的 API 密钥路径:Kimi、Z.AI - 原生令牌解析:Anthropic - OAuth / 认证存储路径:Nous、OpenAI Codex 在此阶段需要回答的问题: - Hermes 应检查哪些环境变量?优先级顺序是什么? - 提供者是否需要基础 URL 覆盖? - 是否需要端点探测或令牌刷新? - 当凭据缺失时,认证错误信息应如何提示? 如果提供者需要的功能超出“查找 API 密钥”范围,请添加专用的凭据解析器,而不是将逻辑塞入无关的分支中。 ## 第三步:在 `hermes_cli/models.py` 中添加模型目录和别名 {#step-3-add-model-catalog-and-aliases-in-hermes_climodelspy} 更新提供者目录,使提供者能在菜单中使用,并支持 `provider:model` 语法。 典型修改: - `_PROVIDER_MODELS` - `_PROVIDER_LABELS` - `_PROVIDER_ALIASES` - `list_available_providers()` 中提供者的显示顺序 - 如果提供者支持实时 `/models` 获取,则修改 `provider_model_ids()` 如果提供者暴露了实时模型列表,优先使用它,并将 `_PROVIDER_MODELS` 作为静态回退。 该文件也是使以下输入正常工作的关键: ```text anthropic:claude-sonnet-4-6 kimi:model-name ``` 如果此处缺少别名,提供者可能认证成功,但在 `/model` 解析时仍会失败。 ## 第四步:在 `hermes_cli/runtime_provider.py` 中解析运行时数据 {#step-4-resolve-runtime-data-in-hermes_cliruntime_providerpy} `resolve_runtime_provider()` 是 CLI、网关、cron、ACP 和辅助客户端共用的路径。 添加一个分支,返回至少包含以下内容的字典: ```python { "provider": "your-provider", "api_mode": "chat_completions", # 或者你的本机模式 "base_url": "https://...", "api_key": "...", "source": "env|portal|auth-store|explicit", "requested_provider": requested_provider, } ``` 如果该提供者兼容 OpenAI,`api_mode` 通常应保持为 `chat_completions`。 注意 API 密钥的优先级。Hermes 已包含逻辑,防止将 OpenRouter 密钥泄露给无关的端点。新提供者也应明确指出哪个密钥对应哪个基础 URL。 ## 第 5 步:在 `hermes_cli/main.py` 中连接 CLI {#step-5-wire-the-cli-in-hermes_climainpy} 在提供者出现在交互式 `hermes model` 流程之前,它是不可发现的。 请在 `hermes_cli/main.py` 中更新以下内容: - `provider_labels` 字典 - `select_provider_and_model()` 函数中的 `providers` 列表 - 提供者分派逻辑(`if selected_provider == ...`) - `--provider` 参数的可选值 - 如果该提供者支持登录/登出流程,更新相应的选项 - 添加一个 `_model_flow_()` 函数,或复用 `_model_flow_api_key_provider()`(如果适用) :::tip `hermes_cli/setup.py` 无需修改——它从 `main.py` 调用 `select_provider_and_model()`,因此你的新提供者会自动出现在 `hermes model` 和 `hermes setup` 中。 ::: ## 第 6 步:确保辅助调用正常工作 {#step-6-keep-auxiliary-calls-working} 此处有两个文件需要关注: ### `agent/auxiliary_client.py` {#agentauxiliary_clientpy} 如果这是一个直接的 API 密钥提供者,请向 `_API_KEY_PROVIDER_AUX_MODELS` 添加一个轻量级/快速的默认辅助模型。 辅助任务包括: - 视觉摘要 - 网页提取摘要 - 上下文压缩摘要 - 会话搜索摘要 - 记忆清理 如果该提供者没有合适的默认辅助模型,辅助任务可能会表现不佳,或意外使用昂贵的主模型。 ### `agent/model_metadata.py` {#agentmodel_metadatapy} 为该提供者的模型添加上下文长度,以确保令牌预算、压缩阈值和限制保持合理。 ## 第 7 步:如果提供者是原生的,添加适配器和 `run_agent.py` 支持 {#step-7-if-the-provider-is-native-add-an-adapter-and-run_agentpy-support} 如果提供者不是标准的聊天补全接口,请将提供者特定的逻辑隔离到 `agent/_adapter.py` 中。 保持 `run_agent.py` 专注于编排。它应调用适配器辅助函数,而不是在文件中各处直接构建提供者请求负载。 原生提供者通常需要在以下位置进行修改: ### 新的适配器文件 {#new-adapter-file} 典型职责包括: - 构建 SDK / HTTP 客户端 - 解析令牌数 - 将 OpenAI 风格的对话消息转换为提供者的请求格式 - 如有必要,转换工具模式 - 将提供者响应规范化为 `run_agent.py` 所期望的格式 - 提取使用情况和结束原因数据 ### `run_agent.py` {#run_agentpy} 搜索 `api_mode` 并审计每个分支点。至少需验证: - `__init__` 选择了新的 `api_mode` - 客户端构建对提供者有效 - `_build_api_kwargs()` 知道如何格式化请求 - `_api_call_with_interrupt()` 能正确分派到对应的客户端调用 - 中断 / 客户端重建路径正常工作 - 响应验证能接受提供者的响应结构 - 结束原因提取正确 - 令牌使用量提取正确 - 回退模型激活能平滑切换到新提供者 - 摘要生成和记忆清理路径仍能正常工作 同时在 `run_agent.py` 中搜索 `self.client.`。任何假设标准 OpenAI 客户端存在的代码路径,在原生提供者使用不同客户端对象或 `self.client = None` 时都可能出错。 ### 提示缓存和提供者特定请求字段 {#prompt-caching-and-provider-specific-request-fields} 提示缓存和提供者特定的选项很容易出现回归。 树中已有的示例: - Anthropic 有原生提示缓存路径 - OpenRouter 接收提供者路由字段 - 并非每个提供者都应接收每个请求端选项 添加原生提供者时,请再次确认 Hermes 仅发送提供者实际理解的字段。 ## 第 8 步:测试 {#step-8-tests} 至少覆盖保护提供者连接的测试。 常见位置: - `tests/test_runtime_provider_resolution.py` - `tests/test_cli_provider_resolution.py` - `tests/test_cli_model_command.py` - `tests/test_setup_model_selection.py` - `tests/test_provider_parity.py` - `tests/test_run_agent.py` - 对于原生提供者,添加 `tests/test__adapter.py` 对于仅文档示例,具体文件集可能不同。重点是覆盖: - 认证解析 - CLI 菜单 / 提供者选择 - 运行时提供者解析 - Agent 执行路径 - 提供者:模型解析 - 任何适配器特定的消息转换 使用 xdist 禁用运行测试: ```bash source venv/bin/activate python -m pytest tests/test_runtime_provider_resolution.py tests/test_cli_provider_resolution.py tests/test_cli_model_command.py tests/test_setup_model_selection.py -n0 -q ``` 对于更深层次的更改,在推送前运行完整测试套件: ```bash source venv/bin/activate python -m pytest tests/ -n0 -q ``` ## 第 9 步:实时验证 {#step-9-live-verification} 测试通过后,运行一次真实的烟雾测试。 ```bash source venv/bin/activate python -m hermes_cli.main chat -q "Say hello" --provider your-provider --model your-model ``` 如果修改了菜单,请测试交互式流程: ```bash source venv/bin/activate python -m hermes_cli.main model python -m hermes_cli.main setup ``` 对于原生提供者,还需验证至少一次工具调用,而不仅仅是纯文本响应。 ## 第 10 步:更新面向用户的文档 {#step-10-update-user-facing-docs} 如果该提供者旨在作为一级选项发布,请同时更新用户文档: - `website/docs/getting-started/quickstart.md` - `website/docs/user-guide/configuration.md` - `website/docs/reference/environment-variables.md` 开发者可能完美配置了提供者,但仍可能导致用户无法发现所需的环境变量或设置流程。 ## OpenAI 兼容提供者检查清单 {#openai-compatible-provider-checklist} 如果提供者符合标准聊天补全接口,请使用此清单。 - [ ] 在 `hermes_cli/auth.py` 中添加 `ProviderConfig` - [ ] 在 `hermes_cli/auth.py` 和 `hermes_cli/models.py` 中添加别名 - [ ] 在 `hermes_cli/models.py` 中添加模型目录 - [ ] 在 `hermes_cli/runtime_provider.py` 中添加运行时分支 - [ ] 在 `hermes_cli/main.py` 中添加 CLI 配线(setup.py 会自动继承) - [ ] 在 `agent/auxiliary_client.py` 中添加辅助模型 - [ ] 在 `agent/model_metadata.py` 中添加上下文长度 - [ ] 更新运行时 / CLI 测试 - [ ] 更新用户文档 ## 原生提供者检查清单 {#native-provider-checklist} 当提供者需要新的协议路径时,请使用此清单。 - [ ] 完成 OpenAI 兼容提供者检查清单中的所有项目 - [ ] 在 `agent/_adapter.py` 中添加适配器 - [ ] 在 `run_agent.py` 中支持新的 `api_mode` - [ ] 中断 / 重建路径正常工作 - [ ] 使用量和结束原因提取正常工作 - [ ] 回退路径正常工作 - [ ] 添加适配器测试 - [ ] 通过实时烟雾测试 ## 常见陷阱 {#common-pitfalls} ### 1. 将提供者添加到认证但未添加到模型解析 {#1-adding-the-provider-to-auth-but-not-to-model-parsing} 这会导致凭据解析正确,但 `/model` 和 `provider:model` 输入会失败。 ### 2. 忘记 `config["model"]` 可以是字符串或字典 {#2-forgetting-that-configmodel-can-be-a-string-or-a-dict} 许多提供者选择代码必须同时处理这两种形式。 ### 3. 认为必须使用内置提供者 {#3-assuming-a-built-in-provider-is-required} 如果服务仅是 OpenAI 兼容的,自定义提供者可能已用更少的维护成本解决用户问题。 ### 4. 忘记辅助路径 {#4-forgetting-auxiliary-paths} 主聊天路径可能正常工作,但摘要、记忆清除或视觉辅助功能失败,因为辅助路由从未更新。 ### 5. 原生提供者分支隐藏在 `run_agent.py` 中 {#5-native-provider-branches-hiding-in-run_agentpy} 搜索 `api_mode` 和 `self.client.`。不要假设显而易见的请求路径是唯一的路径。 ### 6. 向其他提供者发送 OpenRouter 专用参数 {#6-sending-openrouter-only-knobs-to-other-providers} 如提供者路由等字段仅适用于支持它们的提供者。 ### 7. 更新 `hermes model` 但未更新 `hermes setup` {#7-updating-hermes-model-but-not-hermes-setup} 两个流程都需要知道该提供者。 ## 实现过程中良好的搜索目标 {#good-search-targets-while-implementing} 若正在查找提供者影响的所有位置,请搜索以下符号: - `PROVIDER_REGISTRY` - `_PROVIDER_ALIASES` - `_PROVIDER_MODELS` - `resolve_runtime_provider` - `_model_flow_` - `select_provider_and_model` - `api_mode` - `_API_KEY_PROVIDER_AUX_MODELS` - `self.client.` ## 相关文档 {#related-docs} - [提供者运行时解析](provider-runtime) - [架构](architecture) - [贡献指南](contributing) --- ### 添加工具 - URL: https://hermesagent.org.cn/docs/developer-guide/adding-tools - Path: developer-guide/adding-tools.md - Category: developer-guide - Description: 如何向 Hermes Agent 添加新工具 —— 模式、处理器、注册和工具集 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/adding-tools.md - Translated At: 2026-04-11T03:21:38.109Z - Headings: 概述 | 第一步:创建工具文件 | 关键规则 | 第二步:添加到工具集 | 第三步:添加发现导入 | 异步处理函数 | 需要 task id 的处理函数 | 被 Agent 循环拦截的工具 | 可选:设置向导集成 | 检查清单 # 添加工具 {#adding-tools} 在编写工具之前,请问自己:**这应该是一个 [技能](creating-skills) 吗?** 当某个功能可以表示为指令 + shell 命令 + 现有工具(如 arXiv 搜索、git 工作流、Docker 管理、PDF 处理)时,请将其作为 **技能**。 当需要与 API 密钥进行端到端集成、自定义处理逻辑、二进制数据处理或流式处理(如浏览器自动化、TTS、视觉分析)时,请将其作为 **工具**。 ## 概述 {#overview} 添加一个工具需要修改 **3 个文件**: 1. **`tools/your_tool.py`** — 处理函数、模式、检查函数、`registry.register()` 调用 2. **`toolsets.py`** — 将工具名称添加到 `_HERMES_CORE_TOOLS`(或特定工具集) 3. **`model_tools.py`** — 将 `"tools.your_tool"` 添加到 `_discover_tools()` 列表中 ## 第一步:创建工具文件 {#step-1-create-the-tool-file} 每个工具文件都遵循相同的结构: ```python # tools/weather_tool.py """Weather Tool -- 查找某个位置的当前天气。""" import json import os import logging logger = logging.getLogger(__name__) # --- 可用性检查 --- def check_weather_requirements() -> bool: """Return True if the tool's dependencies are available.""" return bool(os.getenv("WEATHER_API_KEY")) # --- 处理程序 --- 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: # ...调用天气 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"] } } # --- 注册 --- from tools.registry import registry registry.register( name="weather", toolset="weather", schema=WEATHER_SCHEMA, handler=lambda args, **kw: weather_tool( location=args.get("location", ""), units=args.get("units", "metric")), check_fn=check_weather_requirements, requires_env=["WEATHER_API_KEY"], ) ``` ### 关键规则 {#key-rules} :::danger 重要 - 处理函数 **必须** 返回 JSON 字符串(通过 `json.dumps()`),不能返回原始字典 - 错误 **必须** 以 `{"error": "message"}` 形式返回,不能抛出异常 - `check_fn` 在构建工具定义时被调用 —— 如果返回 `False`,该工具将被静默排除 - `handler` 接收 `(args: dict, **kwargs)`,其中 `args` 是 LLM 工具调用的参数 ::: ## 第二步:添加到工具集 {#step-2-add-to-a-toolset} 在 `toolsets.py` 中添加工具名称: ```python # 如果它应该在所有平台上可用(CLI + 消息平台): _HERMES_CORE_TOOLS = [ ... "weather", # <-- 在此添加 ] # 或者创建一个新的独立 Toolset: "weather": { "description": "Weather lookup tools", "tools": ["weather"], "includes": [] }, ``` ## 第三步:添加发现导入 {#step-3-add-discovery-import} 在 `model_tools.py` 中将模块添加到 `_discover_tools()` 列表中: ```python def _discover_tools(): _modules = [ ... "tools.weather_tool", # <-- 在此添加 ] ``` 此导入会触发工具文件末尾的 `registry.register()` 调用。 ## 异步处理函数 {#async-handlers} 如果处理函数需要异步代码,请使用 `is_async=True` 标记: ```python async def weather_tool_async(location: str) -> str: async with aiohttp.ClientSession() as session: ... return json.dumps(result) registry.register( name="weather", toolset="weather", schema=WEATHER_SCHEMA, handler=lambda args, **kw: weather_tool_async(args.get("location", "")), check_fn=check_weather_requirements, is_async=True, # 注册表自动调用 _run_async() ) ``` 注册表会透明地处理异步桥接 —— 你无需自行调用 `asyncio.run()`。 ## 需要 task_id 的处理函数 {#handlers-that-need-task_id} 管理会话级状态的工具会通过 `**kwargs` 接收 `task_id`: ```python def _handle_weather(args, **kw): task_id = kw.get("task_id") return weather_tool(args.get("location", ""), task_id=task_id) registry.register( name="weather", ... handler=_handle_weather, ) ``` ## 被 Agent 循环拦截的工具 {#agent-loop-intercepted-tools} 某些工具(如 `todo`、`memory`、`session_search`、`delegate_task`)需要访问会话级 Agent 状态。这些工具在到达注册表之前会被 `run_agent.py` 拦截。注册表仍然保存它们的模式,但如果拦截被绕过,`dispatch()` 将返回一个回退错误。 ## 可选:设置向导集成 {#optional-setup-wizard-integration} 如果工具需要 API 密钥,请将其添加到 `hermes_cli/config.py`: ```python OPTIONAL_ENV_VARS = { ... "WEATHER_API_KEY": { "description": "Weather API key for weather lookup", "prompt": "Weather API key", "url": "https://weatherapi.com/", "tools": ["weather"], "password": True, }, } ``` ## 检查清单 {#checklist} - [ ] 已创建工具文件,包含处理函数、模式、检查函数和注册调用 - [ ] 已在 `toolsets.py` 中添加到适当的工具集中 - [ ] 已在 `model_tools.py` 中添加发现导入 - [ ] 处理函数返回 JSON 字符串,错误以 `{"error": "..."}` 形式返回 - [ ] 可选:已将 API 密钥添加到 `hermes_cli/config.py` 中的 `OPTIONAL_ENV_VARS` - [ ] 可选:已添加到 `toolset_distributions.py` 以支持批量处理 - [ ] 已使用 `hermes chat -q "Use the weather tool for London"` 测试 --- ### Agent Loop 内部机制 - URL: https://hermesagent.org.cn/docs/developer-guide/agent-loop - Path: developer-guide/agent-loop.md - Category: developer-guide - Description: AIAgent 执行、API 模式、工具、回调和回退行为的详细指南 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/agent-loop.md - Translated At: 2026-04-11T03:22:17.037Z - Headings: 核心职责 | 两个入口点 | API 模式 | 轮次生命周期 | 消息格式 | 消息交替规则 | 可中断的 API 调用 | 工具执行 | 串行与并发 | 执行流程 | Agent 级工具 | 回调接口 # Agent Loop 内部机制 {#agent-loop-internals} 核心编排引擎是 `run_agent.py` 中的 `AIAgent` 类 —— 约 9,200 行代码,负责从提示词组装到工具分发,再到提供方故障转移的全部流程。 ## 核心职责 {#core-responsibilities} `AIAgent` 负责以下事项: - 通过 `prompt_builder.py` 组装有效系统提示词和工具模式 - 选择正确的提供方/API 模式(`chat_completions`、`codex_responses`、`anthropic_messages`) - 支持中断的模型调用,具备取消支持 - 执行工具调用(通过线程池实现串行或并发执行) - 以 OpenAI 消息格式维护对话历史 - 处理压缩、重试以及备用模型切换 - 跟踪父 Agent 和子 Agent 之间的迭代预算 - 在上下文丢失前刷新持久记忆 ## 两个入口点 {#two-entry-points} ```python # 简洁接口——返回最终响应字符串 response = agent.chat("Fix the bug in main.py") # 完整接口——返回包含消息、元数据和用量统计的字典 result = agent.run_conversation( user_message="Fix the bug in main.py", system_message=None, # 如果省略则自动构建 conversation_history=None, # 如果省略则从 session 自动加载 task_id="task_abc123" ) ``` `chat()` 是 `run_conversation()` 的轻量封装,从结果字典中提取 `final_response` 字段。 ## API 模式 {#api-modes} Hermes 支持三种 API 执行模式,由提供方选择、显式参数和基础 URL 推断共同决定: | API 模式 | 用途 | 客户端类型 | |----------|------|------------| | `chat_completions` | OpenAI 兼容端点(OpenRouter、自定义、大多数提供方) | `openai.OpenAI` | | `codex_responses` | OpenAI Codex / Responses API | `openai.OpenAI`(使用 Responses 格式) | | `anthropic_messages` | 原生 Anthropic Messages API | `anthropic.Anthropic` 通过适配器 | 模式决定了消息格式、工具调用结构、响应解析方式以及缓存/流式处理机制。三种模式在 API 调用前后均统一为相同的内部消息格式(OpenAI 风格的 `role`/`content`/`tool_calls` 字典)。 **模式解析顺序:** 1. 显式 `api_mode` 构造函数参数(优先级最高) 2. 提供方特定检测(例如 `anthropic` 提供方 → `anthropic_messages`) 3. 基础 URL 推断(例如 `api.anthropic.com` → `anthropic_messages`) 4. 默认值:`chat_completions` ## 轮次生命周期 {#turn-lifecycle} Agent 循环的每次迭代遵循以下流程: ```text run_conversation() 1. Generate task_id if not provided 2. Append user message to conversation history 3. Build or reuse cached system prompt (prompt_builder.py) 4. Check if preflight compression is needed (>50% context) 5. Build API messages from conversation history - chat_completions: OpenAI format as-is - codex_responses: convert to Responses API input items - anthropic_messages: convert via anthropic_adapter.py 6. Inject ephemeral prompt layers (budget warnings, context pressure) 7. Apply prompt caching markers if on Anthropic 8. Make interruptible API call (_api_call_with_interrupt) 9. Parse response: - If tool_calls: execute them, append results, loop back to step 5 - If text response: persist session, flush memory if needed, return ``` ### 消息格式 {#message-format} 所有消息在内部均使用 OpenAI 兼容格式: ```python {"role": "system", "content": "..."} {"role": "user", "content": "..."} {"role": "assistant", "content": "...", "tool_calls": [...]} {"role": "tool", "tool_call_id": "...", "content": "..."} ``` 支持扩展思考的模型生成的推理内容存储在 `assistant_msg["reasoning"]` 中,并可通过 `reasoning_callback` 可选显示。 ### 消息交替规则 {#message-alternation-rules} Agent 循环强制执行严格的消息角色交替: - 系统消息之后:`User → Assistant → User → Assistant → ...` - 工具调用期间:`Assistant(带 tool_calls)→ Tool → Tool → ... → Assistant` - **绝不允许**连续两个助理消息 - **绝不允许**连续两个用户消息 - **仅允许** `tool` 角色拥有连续条目(并行工具结果) 提供方会验证这些序列,拒绝格式错误的历史记录。 ## 可中断的 API 调用 {#interruptible-api-calls} API 请求被封装在 `_api_call_with_interrupt()` 中,该函数在后台线程中运行实际的 HTTP 调用,同时监控中断事件: ```text ┌──────────────────────┐ ┌──────────────┐ │ Main thread │ │ API thread │ │ wait on: │────▶│ HTTP POST │ │ - response ready │ │ to provider │ │ - interrupt event │ └──────────────┘ │ - timeout │ └──────────────────────┘ ``` 当发生中断时(用户发送新消息、执行 `/stop` 命令或接收信号): - API 线程被放弃(响应被丢弃) - Agent 可处理新输入或干净关闭 - 不会将部分响应注入对话历史 ## 工具执行 {#tool-execution} ### 串行与并发 {#sequential-vs-concurrent} 当模型返回工具调用时: - **单个工具调用** → 在主线程中直接执行 - **多个工具调用** → 通过 `ThreadPoolExecutor` 并发执行 - 特例:标记为交互式(如 `clarify`)的工具强制串行执行 - 无论完成顺序如何,结果均按原始工具调用顺序重新插入 ### 执行流程 {#execution-flow} ```text for each tool_call in response.tool_calls: 1. Resolve handler from tools/registry.py 2. Fire pre_tool_call plugin hook 3. Check if dangerous command (tools/approval.py) - If dangerous: invoke approval_callback, wait for user 4. Execute handler with args + task_id 5. Fire post_tool_call plugin hook 6. Append {"role": "tool", "content": result} to history ``` ### Agent 级工具 {#agent-level-tools} 某些工具在到达 `handle_function_call()` 之前由 `run_agent.py` 拦截: | 工具 | 拦截原因 | |------|----------| | `todo` | 读取/写入 Agent 本地任务状态 | | `memory` | 向持久记忆文件写入,带字符限制 | | `session_search` | 通过 Agent 的会话数据库查询会话历史 | | `delegate_task` | 启动子 Agent(s),拥有隔离上下文 | 这些工具直接修改 Agent 状态,并返回合成的工具结果,不经过注册表。 ## 回调接口 {#callback-surfaces} `AIAgent` 支持平台特定的回调,以在 CLI、网关和 ACP 集成中实现实时进度反馈: | 回调函数 | 触发时机 | 使用方 | |----------|-----------|---------| | `tool_progress_callback` | 每个工具执行前后 | CLI 进度条,网关进度消息 | | `thinking_callback` | 模型开始/停止思考时 | CLI “thinking...” 指示器 | | `reasoning_callback` | 模型返回推理内容时 | CLI 推理显示,网关推理块 | | `clarify_callback` | 调用 `clarify` 工具时 | CLI 输入提示,网关交互消息 | | `step_callback` | 每次完整的 Agent 回合结束后 | 网关步骤追踪,ACP 进度 | | `stream_delta_callback` | 每次流式传输的 token(启用时) | CLI 流式显示 | | `tool_gen_callback` | 从流中解析出工具调用时 | CLI 进度条中的工具预览 | | `status_callback` | 状态变化时(思考、执行等) | ACP 状态更新 | ## 预算与回退行为 {#budget-and-fallback-behavior} ### 迭代预算 {#iteration-budget} Agent 通过 `IterationBudget` 跟踪迭代次数: - 默认值:90 次迭代(可通过 `agent.max_turns` 配置) - 父 Agent 与子 Agent 共享预算 —— 子 Agent 会消耗父 Agent 的预算 - 两级预算压力机制通过 `_get_budget_warning()` 实现: - 达到 70% 以上使用率(警告级别):在最后一个工具结果中追加 `[BUDGET: 迭代 X/Y。剩余 N 次迭代。开始整合你的工作。]` - 达到 90% 以上使用率(严重警告级别):在最后一个工具结果中追加 `[BUDGET WARNING: 迭代 X/Y。仅剩 N 次迭代。立即提供最终响应。]` - 达到 100% 时,Agent 停止并返回已完成工作的摘要 ### 回退模型 {#fallback-model} 当主模型失败时(429 速率限制、5xx 服务器错误、401/403 认证错误): 1. 检查配置中的 `fallback_providers` 列表 2. 按顺序尝试每个回退提供方 3. 成功后,使用新提供方继续对话 4. 对于 401/403 错误,在切换前尝试刷新凭证 回退系统也独立覆盖辅助任务 —— 视觉、压缩、网页提取和会话搜索各自拥有可配置的独立回退链,通过 `auxiliary.*` 配置节进行设置。 ## 压缩与持久化 {#compression-and-persistence} ### 压缩触发时机 {#when-compression-triggers} - **预检**(API 调用前):当对话超过模型上下文窗口的 50% - **网关自动压缩**:当对话超过 85%(更激进,运行于回合之间) ### 压缩期间发生的情况 {#what-happens-during-compression} 1. 首先将记忆刷新到磁盘(防止数据丢失) 2. 将中间对话回合总结为紧凑摘要 3. 保留最后 N 条消息完整(`compression.protect_last_n`,默认值:20) 4. 工具调用/结果消息对保持完整(从不拆分) 5. 生成新的会话谱系 ID(压缩创建了一个“子”会话) ### 会话持久化 {#session-persistence} 每次回合结束后: - 消息保存到会话存储(通过 `hermes_state.py` 使用 SQLite) - 记忆更改刷新到 `MEMORY.md` / `USER.md` - 可通过 `/resume` 或 `hermes chat --resume` 重新启动会话 ## 关键源文件 {#key-source-files} | 文件 | 用途 | |------|---------| | `run_agent.py` | AIAgent 类 —— 完整的 Agent 循环(约 9,200 行) | | `agent/prompt_builder.py` | 从记忆、技能、上下文文件、个性等组装系统提示 | | `agent/context_engine.py` | ContextEngine ABC —— 可插拔的上下文管理 | | `agent/context_compressor.py` | 默认引擎 —— 有损摘要算法 | | `agent/prompt_caching.py` | Anthropic 提示缓存标记与缓存指标 | | `agent/auxiliary_client.py` | 辅助 LLM 客户端,用于辅助任务(视觉、摘要) | | `model_tools.py` | 工具模式集合,`handle_function_call()` 分发逻辑 | ## 相关文档 {#related-docs} - [提供方运行时解析](provider-runtime) - [提示组装](prompt-assembly) - [上下文压缩与提示缓存](context-compression-and-caching) - [工具运行时](tools-runtime) - [架构概览](architecture) --- ### 架构 - URL: https://hermesagent.org.cn/docs/developer-guide/architecture - Path: developer-guide/architecture.md - Category: developer-guide - Description: Hermes Agent 内部结构 — 主要子系统、执行路径、数据流,以及下一步阅读建议 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/architecture.md - Translated At: 2026-04-11T03:22:19.510Z - Headings: 系统概览 | 目录结构 | 数据流 | CLI 会话 | 网关消息 | 定时任务 | 推荐阅读顺序 | 主要子系统 | Agent 循环 | 提示词系统 | 提供者解析 | 工具系统 # 架构 {#architecture} 本页是 Hermes Agent 内部结构的顶层概览。请使用它来了解代码库的整体布局,然后深入各个子系统文档以获取实现细节。 ## 系统概览 {#system-overview} ```text ┌─────────────────────────────────────────────────────────────────────┐ │ Entry Points │ │ │ │ CLI (cli.py) Gateway (gateway/run.py) ACP (acp_adapter/) │ │ Batch Runner API Server Python Library │ └──────────┬──────────────┬───────────────────────┬────────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ AIAgent (run_agent.py) │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Prompt │ │ Provider │ │ Tool │ │ │ │ Builder │ │ Resolution │ │ Dispatch │ │ │ │ (prompt_ │ │ (runtime_ │ │ (model_ │ │ │ │ builder.py) │ │ provider.py)│ │ tools.py) │ │ │ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │ │ │ │ │ │ │ ┌──────┴───────┐ ┌──────┴───────┐ ┌──────┴───────┐ │ │ │ Compression │ │ 3 API Modes │ │ Tool Registry│ │ │ │ & Caching │ │ chat_compl. │ │ (registry.py)│ │ │ │ │ │ codex_resp. │ │ 48 tools │ │ │ │ │ │ anthropic │ │ 40 toolsets │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ └─────────────────────────────────────────────────────────────────────┘ │ │ ▼ ▼ ┌───────────────────┐ ┌──────────────────────┐ │ Session Storage │ │ Tool Backends │ │ (SQLite + FTS5) │ │ Terminal (6 backends) │ │ hermes_state.py │ │ Browser (5 backends) │ │ gateway/session.py│ │ Web (4 backends) │ └───────────────────┘ │ MCP (dynamic) │ │ File, Vision, etc. │ └──────────────────────┘ ``` ## 目录结构 {#directory-structure} ```text hermes-agent/ ├── run_agent.py # AIAgent —— 核心对话循环(约 9,200 行) ├── cli.py # HermesCLI —— 交互式终端界面(约 8,500 行) ├── model_tools.py # Tool 发现、Schema 收集与分发 ├── toolsets.py # Tool 分组与平台预设 ├── hermes_state.py # SQLite 会话 / 状态数据库与 FTS5 ├── hermes_constants.py # HERMES_HOME 与 profile 感知路径 ├── batch_runner.py # 批量轨迹生成 │ ├── agent/ # Agent 内部结构 │ ├── prompt_builder.py # System Prompt 组装 │ ├── context_engine.py # ContextEngine ABC(可插拔) │ ├── context_compressor.py # 默认引擎——有损摘要 │ ├── prompt_caching.py # Anthropic Prompt 缓存 │ ├── auxiliary_client.py # 用于辅助任务的辅助 LLM(Vision、总结) │ ├── model_metadata.py # Model Context 长度与 Token 估算 │ ├── models_dev.py # models.dev 注册表集成 │ ├── anthropic_adapter.py # Anthropic 消息 API 格式转换 │ ├── display.py # KawaiiSpinner、Tool 预览格式 │ ├── skill_commands.py # Skill 斜杠命令 │ ├── memory_manager.py # Memory 管理器编排 │ ├── memory_provider.py # Memory Provider ABC │ └── trajectory.py # 轨迹保存助手 │ ├── hermes_cli/ # CLI 子命令和设置 │ ├── main.py # 入口点 —— 所有 `hermes` 子命令 │ ├── config.py # DEFAULT_CONFIG、OPTIONAL_ENV_VARS、迁移 │ ├── commands.py # COMMAND_REGISTRY — 中央斜线命令定义 │ ├── auth.py # PROVIDER_REGISTRY,凭证解析 │ ├── runtime_provider.py # Provider → `api_mode` + 凭证 │ ├── models.py # Model 目录、Provider 模型列表 │ ├── model_switch.py # /model 命令逻辑(CLI + gateway 共享) │ ├── setup.py # 交互式设置向导(约 3,100 行) │ ├── skin_engine.py # CLI 主题引擎 │ ├── skills_config.py # `hermes skills` —— 按平台启用 / 禁用 │ ├── skills_hub.py # `/skills` 斜杠命令 │ ├── tools_config.py # `hermes tools` —— 按平台启用 / 禁用 │ ├── plugins.py # PluginManager —— 发现、加载与挂钩 │ ├── callbacks.py # 终端回调(澄清、sudo、批准) │ └── gateway.py # `hermes gateway` 启动 / 停止 │ ├── tools/ # Tool 实现(每个 Tool 一个文件) │ ├── registry.py # 中央 tool 注册表 │ ├── approval.py # 危险命令检测 │ ├── terminal_tool.py # 终端编排 │ ├── process_registry.py # 后台进程管理 │ ├── file_tools.py # 读文件、写文件、补丁、搜索文件 │ ├── web_tools.py # 网络搜索、网络提取 │ ├── browser_tool.py # 11 个浏览器自动化 Tool │ ├── code_execution_tool.py # `execute_code` 沙箱 │ ├── delegate_tool.py # Subagent 委派 │ ├── mcp_tool.py # MCP 客户端(约 2,200 行) │ ├── credential_files.py # 基于文件的凭证传递 │ ├── env_passthrough.py # 沙箱的环境变量直通 │ ├── ansi_strip.py # ANSI 逃逸剥离 │ └── environments/ # 终端后端(本地、Docker、SSH、Modal、Daytona、Singularity) │ ├── gateway/ # 消息平台 Gateway │ ├── run.py # GatewayRunner —— 消息分发(约 7,500 行) │ ├── session.py # SessionStore — 会话持久化 │ ├── delivery.py # 出站消息传递 │ ├── pairing.py # DM配对授权 │ ├── hooks.py # 钩子发现和生命周期事件 │ ├── mirror.py # 跨session消息镜像 │ ├── status.py # Token 锁,profile 范围内的进程跟踪 │ ├── builtin_hooks/ # 始终注册的钩子 │ └── platforms/ # 15 个适配器:telegram、discord、slack、whatsapp、 │ # signal、matrix、mattermost、电子邮件、短信、 │ # dingtalk、feishu、wecom、weixin、bluebubbles、家庭助理、webhook │ ├── acp_adapter/ # ACP 服务器(VS 代码 / Zed / JetBrains) ├── cron/ # 调度程序(jobs.py、scheduler.py) ├── plugins/memory/ # Memory provider 插件 ├── plugins/context_engine/ # Context 引擎插件 ├── environments/ # 强化学习训练环境 (Atropos) ├── skills/ # 捆绑 skills(始终可用) ├── optional-skills/ # 官方可选skills(显式安装) ├── website/ # Docusaurus 文档网站 └── tests/ # Pytest 套件(“0”,000+ 测试) ``` ## 数据流 {#data-flow} ### CLI 会话 {#cli-session} ```text User input → HermesCLI.process_input() → AIAgent.run_conversation() → prompt_builder.build_system_prompt() → runtime_provider.resolve_runtime_provider() → API call (chat_completions / codex_responses / anthropic_messages) → tool_calls? → model_tools.handle_function_call() → loop → final response → display → save to SessionDB ``` ### 网关消息 {#gateway-message} ```text Platform event → Adapter.on_message() → MessageEvent → GatewayRunner._handle_message() → authorize user → resolve session key → create AIAgent with session history → AIAgent.run_conversation() → deliver response back through adapter ``` ### 定时任务 {#cron-job} ```text Scheduler tick → load due jobs from jobs.json → create fresh AIAgent (no history) → inject attached skills as context → run job prompt → deliver response to target platform → update job state and next_run ``` ## 推荐阅读顺序 {#recommended-reading-order} 如果你是代码库的新手: 1. **本页** —— 了解整体架构 2. **[Agent 循环内部机制](agent-loop)** —— AIAgent 的工作原理 3. **[提示词组装](prompt-assembly)** —— 系统提示词的构建 4. **[提供者运行时解析](provider-runtime)** —— 提供者的选择机制 5. **[添加提供者](adding-providers)** —— 添加新提供者的实践指南 6. **[工具运行时](tools-runtime)** —— 工具注册表、分发与运行环境 7. **[会话存储](session-storage)** —— SQLite 模式、FTS5、会话传承关系 8. **[网关内部机制](gateway-internals)** —— 消息平台网关 9. **[上下文压缩与提示词缓存](context-compression-and-caching)** —— 上下文压缩与缓存机制 10. **[ACP 内部机制](acp-internals)** —— IDE 集成 11. **[环境、基准测试与数据生成](/docs/reference/toolsets-reference)** —— 强化学习训练 ## 主要子系统 {#major-subsystems} ### Agent 循环 {#agent-loop} 同步编排引擎(`run_agent.py` 中的 `AIAgent`)。负责提供者选择、提示词构建、工具执行、重试、降级、回调、压缩和持久化。支持三种 API 模式,以适配不同的提供者后端。 → [Agent 循环内部机制](agent-loop) ### 提示词系统 {#prompt-system} 在整个对话生命周期中进行提示词的构建与维护: - **`prompt_builder.py`** —— 从以下来源组装系统提示词:个性设定(SOUL.md)、记忆(MEMORY.md、USER.md)、技能、上下文文件(AGENTS.md、.hermes.md)、工具使用指导,以及模型特定指令 - **`prompt_caching.py`** —— 为前缀缓存应用 Anthropic 的缓存断点 - **`context_compressor.py`** —— 当上下文超过阈值时,对中间对话轮次进行摘要压缩 → [提示词组装](prompt-assembly),[上下文压缩与提示词缓存](context-compression-and-caching) ### 提供者解析 {#provider-resolution} CLI、网关、定时任务、ACP 和辅助调用共用的运行时解析器。将 `(provider, model)` 元组映射为 `(api_mode, api_key, base_url)`。支持 18+ 个提供者,处理 OAuth 流程、凭证池和别名解析。 → [提供者运行时解析](provider-runtime) ### 工具系统 {#tool-system} 中央工具注册表(`tools/registry.py`),包含 20 个工具集中的 47 个已注册工具。每个工具文件在导入时自动注册。注册表负责模式收集、分发、可用性检查和错误包装。终端工具支持 6 种后端(本地、Docker、SSH、Daytona、Modal、Singularity)。 → [工具运行时](tools-runtime) ### 会话持久化 {#session-persistence} 基于 SQLite 的会话存储,支持 FTS5 全文搜索。会话具备传承追踪(压缩过程中的父子关系)、跨平台隔离,以及带竞争处理的原子写入。 → [会话存储](session-storage) ### 消息网关 {#messaging-gateway} 长期运行的进程,包含 14 个平台适配器,统一会话路由、用户授权(白名单 + 私信配对)、斜杠命令分发、钩子系统、定时任务触发和后台维护。 → [网关内部机制](gateway-internals) ### 插件系统 {#plugin-system} 三种发现来源:`~/.hermes/plugins/`(用户级)、`.hermes/plugins/`(项目级)和 pip 入口点。插件通过上下文 API 注册工具、钩子和 CLI 命令。存在两种专用插件类型:记忆提供者(`plugins/memory/`)和上下文引擎(`plugins/context_engine/`)。两者均为单选 —— 每次只能激活一个,通过 `hermes plugins` 或 `config.yaml` 配置。 → [插件指南](/docs/guides/build-a-hermes-plugin),[记忆提供者插件](memory-provider-plugin) ### 定时任务 {#cron} 原生的 Agent 任务(非 shell 任务)。任务以 JSON 格式存储,支持多种调度格式,可附加技能和脚本,并可发送至任意平台。 → [定时任务内部机制](cron-internals) ### ACP 集成 {#acp-integration} 通过 stdio/JSON-RPC 将 Hermes 作为编辑器原生 Agent 暴露给 VS Code、Zed 和 JetBrains。 → [ACP 内部机制](acp-internals) ### 强化学习 / 环境 / 轨迹 {#rl--environments--trajectories} 完整的环境框架,用于评估与强化学习训练。与 Atropos 集成,支持多种工具调用解析器,并生成 ShareGPT 格式的轨迹。 → [环境、基准测试与数据生成](/docs/reference/toolsets-reference),[轨迹与训练格式](trajectory-format) ## 设计原则 {#design-principles} | 原则 | 实际含义 | |-----------|--------------------------| | **提示稳定性** | 系统提示在对话过程中不会改变。除用户显式操作(如 `/model`)外,不会出现破坏缓存的变更。 | | **可观察的执行** | 每个工具调用都会通过回调对用户可见。CLI 中显示进度(旋转图标),网关中显示聊天消息。 | | **可中断性** | 用户输入或信号可随时取消正在进行的 API 调用和工具执行。 | | **平台无关的核心** | 一个 AIAgent 类同时支持 CLI、网关、ACP、批处理和 API 服务器。平台差异仅存在于入口点,而非 Agent 本身。 | | **松耦合** | 可选子系统(MCP、插件、记忆提供者、强化学习环境)使用注册表模式和 check_fn 门控机制,而非硬依赖。 | | **配置文件隔离** | 每个配置文件(`hermes -p `)拥有独立的 HERMES_HOME、配置、记忆、会话和网关 PID。多个配置文件可并发运行。 | ## 文件依赖链 {#file-dependency-chain} ```text tools/registry.py (no deps — imported by all tool files) ↑ tools/*.py (each calls registry.register() at import time) ↑ model_tools.py (imports tools/registry + triggers tool discovery) ↑ run_agent.py, cli.py, batch_runner.py, environments/ ``` 该依赖链意味着工具注册在导入时完成,早于任何 Agent 实例的创建。添加新工具需要在 `model_tools.py` 的 `_discover_tools()` 列表中添加导入。 --- ### 浏览器 CDP 监控器 — 设计 { browser cdp supervisor — design} - URL: https://hermesagent.org.cn/docs/developer-guide/browser-supervisor - Path: developer-guide/browser-supervisor.md - Category: developer-guide - Description: 状态: 已发布 (PR 14540) 最后更新: 2026 04 23 作者: @teknium1 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/browser-supervisor.md - Translated At: 2026-05-03T17:15:55.355Z - Headings: 问题 | 后端能力矩阵(于 2026 04 23 实时验证) | 架构 | CDPSupervisor | 生命周期 | 对话框策略 | Agent 表面 (PR 1) | 一个新工具 | browser snapshot 扩展 | 可用性门控 | 跨源 iframe 交互 | Camofox(后续) # 浏览器 CDP 监控器 — 设计 {#browser-cdp-supervisor-—-design} **状态:** 已发布 (PR 14540) **最后更新:** 2026-04-23 **作者:** @teknium1 ## 问题 {#problem} 原生 JS 对话框(`alert`/`confirm`/`prompt`/`beforeunload`)和 iframe 是我们浏览器工具链中最大的两个空白: 1. **对话框阻塞 JS 线程。** 页面上的任何操作都会停滞,直到对话框被处理。在此工作之前,Agent 无法得知对话框已打开——后续的工具调用会挂起或抛出不透明的错误。 2. **Iframe 不可见。** Agent 可以在 DOM 快照中看到 iframe 节点,但无法在其中点击、输入或执行 eval——尤其是生活在独立 Chromium 进程中的跨源 (OOPIF) iframe。 [PR #12550](https://github.com/NousResearch/hermes-agent/pull/12550) 提议了一个无状态的 `browser_dialog` 包装器。这并没有解决检测问题——它只是一个更干净的 CDP 调用,适用于 Agent 已经通过症状知道对话框已打开的情况。因被取代而关闭。 ## 后端能力矩阵(于 2026-04-23 实时验证) {#backend-capability-matrix-verified-live-2026-04-23} 使用一次性探测脚本针对一个数据 URL 页面进行测试,该页面在主框架和同源 srcdoc iframe 中触发 alert,以及一个跨源 `https://example.com` iframe: | 后端 | 对话框检测 | 对话框响应 | 帧树 | 通过 `browser_cdp(frame_id=...)` 进行 OOPIF `Runtime.evaluate` | |---|---|---|---|---| | 本地 Chrome (`--remote-debugging-port`) / `/browser connect` | ✓ | ✓ 完整工作流 | ✓ | ✓ | | Browserbase | ✓ (通过桥接) | ✓ 完整工作流 (通过桥接) | ✓ | ✓ (`document.title = "Example Domain"` 在真实跨源 iframe 上已验证) | | Camofox | ✗ 无 CDP (仅 REST) | ✗ | 部分通过 DOM 快照 | ✗ | **Browserbase 响应的工作原理。** Browserbase 的 CDP 代理内部使用 Playwright,并在约 10ms 内自动关闭原生对话框,因此 `Page.handleJavaScriptDialog` 无法跟上。为了解决这个问题,监控器通过 `Page.addScriptToEvaluateOnNewDocument` 注入一个桥接脚本,该脚本用同步 XHR 覆盖 `window.alert`/`confirm`/`prompt`,指向一个魔术主机 (`hermes-dialog-bridge.invalid`)。`Fetch.enable` 在这些 XHR 接触网络之前拦截它们——对话框变为监控器捕获的 `Fetch.requestPaused` 事件,而 `respond_to_dialog` 通过 `Fetch.fulfillRequest` 完成请求,载荷为注入脚本解码的 JSON 主体。 最终结果:从页面的角度来看,`prompt()` 仍然返回 Agent 提供的字符串。从 Agent 的角度来看,无论如何都是相同的 `browser_dialog(action=...)` API。针对真实的 Browserbase 会话进行的端到端测试——4/4(alert/prompt/confirm-accept/confirm-dismiss)全部通过,包括值往返传回页面 JS。 Camofox 在此 PR 中仍不受支持;计划在 `jo-inc/camofox-browser` 上游提出问题,请求添加对话框轮询端点。 ## 架构 {#architecture} ### CDPSupervisor {#cdpsupervisor} 每个 Hermes `task_id` 在后台守护线程中运行一个 `asyncio.Task`。持有到后端 CDP 端点的持久 WebSocket 连接。维护: - **对话框队列** — `List[PendingDialog]`,包含 `{id, type, message, default_prompt, session_id, opened_at}` - **帧树** — `Dict[frame_id, FrameInfo]`,包含父子关系、URL、源、是否为跨源子会话 - **会话映射** — `Dict[session_id, SessionInfo]`,以便交互工具可以将 OOPIF 操作路由到正确的附加会话 - **最近的控制台错误** — 最后 50 条的环形缓冲区(用于 PR 2 诊断) 附加时订阅: - `Page.enable` — `javascriptDialogOpening`, `frameAttached`, `frameNavigated`, `frameDetached` - `Runtime.enable` — `executionContextCreated`, `consoleAPICalled`, `exceptionThrown` - `Target.setAutoAttach {autoAttach: true, flatten: true}` — 暴露子 OOPIF 目标;监控器在每个目标上启用 `Page`+`Runtime` 通过快照锁实现线程安全的状态访问;工具处理程序(同步)读取冻结的快照而无需等待。 ### 生命周期 {#lifecycle} - **启动:** `SupervisorRegistry.get_or_start(task_id, cdp_url)` — 由 `browser_navigate`、Browserbase 会话创建、`/browser connect` 调用。幂等。 - **停止:** 会话 teardown 或 `/browser disconnect`。取消 asyncio 任务,关闭 WebSocket,丢弃状态。 - **重新绑定:** 如果 CDP URL 更改(用户重新连接到新的 Chrome),停止旧监控器并重新启动——切勿在不同端点间重用状态。 ### 对话框策略 {#dialog-policy} 可通过 `config.yaml` 中的 `browser.dialog_policy` 进行配置: - **`must_respond`**(默认)— 捕获,在 `browser_snapshot` 中显示,等待显式的 `browser_dialog(action=...)` 调用。如果在 300 秒安全超时后没有响应,则自动关闭并记录日志。防止有缺陷的 Agent 永远停滞。 - `auto_dismiss` — 记录并立即关闭;Agent 随后通过 `browser_snapshot` 内的 `browser_state` 看到它。 - `auto_accept` — 记录并接受(对于 `beforeunload` 很有用,用户希望干净地导航离开)。 策略是按任务设置的;v1 中没有每个对话框的覆盖设置。 ## Agent 表面 (PR 1) {#agent-surface-pr-1} ### 一个新工具 {#one-new-tool} ``` browser_dialog(action, prompt_text=None, dialog_id=None) ``` - `action="accept"` / `"dismiss"` → 响应指定的或唯一的待处理对话框(必需) - `prompt_text=...` → 提供给 `prompt()` 对话框的文本 - `dialog_id=...` → 当有多个对话框排队时用于消除歧义(罕见情况) 该工具仅用于响应。Agent 在调用之前从 `browser_snapshot` 输出中读取待处理对话框。 ### `browser_snapshot` 扩展 {#browser_snapshot-extension} 当附加了 supervisor 时,向现有的快照输出添加三个可选字段: ```json { "pending_dialogs": [ {"id": "d-1", "type": "alert", "message": "Hello", "opened_at": 1650000000.0} ], "recent_dialogs": [ {"id": "d-1", "type": "alert", "message": "...", "opened_at": 1650000000.0, "closed_at": 1650000000.1, "closed_by": "remote"} ], "frame_tree": { "top": {"frame_id": "FRAME_A", "url": "https://example.com/", "origin": "https://example.com"}, "children": [ {"frame_id": "FRAME_B", "url": "about:srcdoc", "is_oopif": false}, {"frame_id": "FRAME_C", "url": "https://ads.example.net/", "is_oopif": true, "session_id": "SID_C"} ], "truncated": false } } ``` - **`pending_dialogs`**:当前阻塞页面 JS 线程的对话框。Agent 必须调用 `browser_dialog(action=...)` 进行响应。在 Browserbase 上为空,因为他们的 CDP 代理会在约 10 毫秒内自动关闭对话框。 - **`recent_dialogs`**:最多包含 20 个最近关闭对话框的环形缓冲区,带有 `closed_by` 标签 — `"agent"`(我们已响应)、`"auto_policy"`(本地 auto_dismiss/auto_accept)、`"watchdog"`(触及 must_respond 超时)或 `"remote"`(浏览器/后端为我们关闭了它,例如 Browserbase)。这是 Browserbase 上的 Agent 仍能了解发生情况的方式。 - **`frame_tree`**:包括跨源 (OOPIF) 子项的帧结构。上限为 30 个条目 + OOPIF 深度 2,以限制广告密集页面上的快照大小。当触及限制时,`truncated: true` 会显现;需要完整树的 Agent 可以使用带有 `Page.getFrameTree` 的 `browser_cdp`。 这些都没有新的工具 schema 表面 — Agent 读取其已经请求的快照。 ### 可用性门控 {#availability-gating} 两个表面都基于 `_browser_cdp_check` 进行门控(supervisor 仅在 CDP 端点可达时才能运行)。在 Camofox / 无后端会话中,对话框工具被隐藏,且快照省略新字段 — 不会导致 schema 膨胀。 ## 跨源 iframe 交互 {#cross-origin-iframe-interaction} 扩展对话框检测工作,`browser_cdp(frame_id=...)` 通过 supervisor 已连接的 WebSocket 路由 CDP 调用(特别是 `Runtime.evaluate`),使用 OOPIF 的子 `sessionId`。Agent 从 `browser_snapshot.frame_tree.children[]` 中挑选 `is_oopif=true` 的 frame_ids,并将其传递给 `browser_cdp`。对于同源 iframe(没有专用的 CDP 会话),Agent 改用来自顶层 `Runtime.evaluate` 的 `contentWindow`/`contentDocument` — 当 `frame_id` 属于非 OOPIF 时,supervisor 会显示指向该回退方案的错误。 在 Browserbase 上,这是 iframe 交互的唯一可靠路径 — 无状态 CDP 连接(每次 `browser_cdp` 调用时打开)会遇到签名 URL 过期问题,而 supervisor 的长寿命连接保持有效的会话。 ## Camofox(后续) {#camofox-follow-up} 计划在 `jo-inc/camofox-browser` 上解决的问题,添加: - 每个会话的 Playwright `page.on('dialog', handler)` - `GET /tabs/:tabId/dialogs` 轮询端点 - `POST /tabs/:tabId/dialogs/:id` 用于接受/关闭 - 帧树内省端点 ## 涉及的文件(PR 1) {#files-touched-pr-1} ### 新增 {#new} - `tools/browser_supervisor.py` — `CDPSupervisor`, `SupervisorRegistry`, `PendingDialog`, `FrameInfo` - `tools/browser_dialog_tool.py` — `browser_dialog` 工具处理程序 - `tests/tools/test_browser_supervisor.py` — 模拟 CDP WebSocket 服务器 + 生命周期/状态测试 - `website/docs/developer-guide/browser-supervisor.md` — 本文件 ### 修改 {#modified} - `toolsets.py` — 在 `browser`, `hermes-acp`, `hermes-api-server`, core toolsets 中注册 `browser_dialog`(受 CDP 可达性门控) - `tools/browser_tool.py` - `browser_navigate` 启动钩子:如果 CDP URL 可解析,则执行 `SupervisorRegistry.get_or_start(task_id, cdp_url)` - `browser_snapshot`(约第 1536 行):将 supervisor 状态合并到返回 payload 中 - `/browser connect` 处理程序:使用新端点重启 supervisor - `_cleanup_browser_session` 中的会话清理钩子 - `hermes_cli/config.py` — 向 `DEFAULT_CONFIG` 添加 `browser.dialog_policy` 和 `browser.dialog_timeout_s` - 文档:`website/docs/user-guide/features/browser.md`, `website/docs/reference/tools-reference.md`, `website/docs/reference/toolsets-reference.md` ## 非目标 {#non-goals} - Camofox 的检测/交互(上游缺口;单独跟踪) - 将对话框/帧事件实时流式传输给用户(需要网关钩子) - 跨会话持久化对话框历史(仅限内存) - 每个 iframe 的对话框策略(Agent 可以通过 `dialog_id` 表达这一点) - 替换 `browser_cdp` — 它仍然作为长尾情况(cookie、视口、网络节流)的应急出口 ## 测试 {#testing} 单元测试使用一个 asyncio 模拟 CDP 服务器,该服务器足以执行协议来演练所有状态转换:附加、启用、导航、触发对话框、关闭对话框、帧附加/分离、子目标附加、会话清理。真实后端 E2E(Browserbase + 本地 Chrome)是手动的;来自 2026-04-23 调查的探测脚本保留在仓库中的 `scripts/browser_supervisor_e2e.py` 下,以便任何人都可以在新后端版本上重新验证。 --- ### 上下文压缩与缓存 { context compression and caching} - URL: https://hermesagent.org.cn/docs/developer-guide/context-compression-and-caching - Path: developer-guide/context-compression-and-caching.md - Category: developer-guide - Description: Hermes Agent 使用双层压缩系统和 Anthropic 提示词缓存机制,以在长时间对话中高效管理上下文窗口的使用。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/context-compression-and-caching.md - Translated At: 2026-04-11T03:22:37.022Z - Headings: 可插拔的上下文引擎 | 双层压缩系统 | 1. 网关会话清理(85% 阈值) | 2. Agent ContextCompressor(50% 阈值,可配置) | 配置 | 参数详情 | 计算值(以 200K 上下文模型为例,使用默认值) | 压缩算法 | 阶段 1:清除旧工具结果(低成本,无需 LLM 调用) | 阶段 2:确定边界 | 阶段 3:生成结构化摘要 | 目标 # 上下文压缩与缓存 {#context-compression-and-caching} Hermes Agent 使用双层压缩系统和 Anthropic 提示词缓存机制,以在长时间对话中高效管理上下文窗口的使用。 源文件:`agent/context_engine.py`(ABC 接口),`agent/context_compressor.py`(默认引擎),`agent/prompt_caching.py`,`gateway/run.py`(会话清理),`run_agent.py`(搜索 `_compress_context`) ## 可插拔的上下文引擎 {#pluggable-context-engine} 上下文管理基于 `ContextEngine` ABC 接口(`agent/context_engine.py`)。内置的 `ContextCompressor` 是默认实现,但插件可以替换为其他引擎(例如:无损上下文管理)。 ```yaml context: engine: "compressor" # 默认值 - 内置有损摘要 engine: "lcm" # 示例 - 提供无损 context 的插件 ``` 该引擎负责: - 决定是否应触发压缩(`should_compress()`) - 执行压缩操作(`compress()`) - 可选地暴露 Agent 可调用的工具(例如:`lcm_grep`) - 跟踪来自 API 响应的 token 使用情况 选择由配置驱动,通过 `config.yaml` 中的 `context.engine` 进行配置。解析顺序如下: 1. 检查 `plugins/context_engine//` 目录 2. 检查通用插件系统(`register_context_engine()`) 3. 回退到内置的 `ContextCompressor` 插件引擎**不会自动激活**——用户必须显式将 `context.engine` 设置为插件名称。默认值 `"compressor"` 始终使用内置引擎。 可通过 `hermes plugins` → 提供商插件 → 上下文引擎 进行配置,或直接编辑 `config.yaml`。 有关开发上下文引擎插件,请参阅 [上下文引擎插件](/docs/developer-guide/context-engine-plugin)。 ## 双层压缩系统 {#dual-compression-system} Hermes 具有两个独立运行的压缩层: ``` ┌──────────────────────────┐ Incoming message │ Gateway Session Hygiene │ Fires at 85% of context ─────────────────► │ (pre-agent, rough est.) │ Safety net for large sessions └─────────────┬────────────┘ │ ▼ ┌──────────────────────────┐ │ Agent ContextCompressor │ Fires at 50% of context (default) │ (in-loop, real tokens) │ Normal context management └──────────────────────────┘ ``` ### 1. 网关会话清理(85% 阈值) {#1-gateway-session-hygiene-85-threshold} 位于 `gateway/run.py`(搜索 `_maybe_compress_session`)。这是一个**安全网**,在 Agent 处理消息前运行。当会话在轮次之间增长过快时(例如 Telegram/Discord 中夜间累积),防止 API 失败。 - **阈值**:固定为模型上下文长度的 85% - **token 来源**:优先使用上一轮 API 报告的实际 token 数;若不可用,则回退到粗略的字符估算(`estimate_messages_tokens_rough`) - **触发条件**:仅当 `len(history) >= 4` 且压缩功能已启用时 - **目的**:捕获逃逸出 Agent 自身压缩器的会话 网关清理阈值有意高于 Agent 压缩器的阈值。若设置为 50%(与 Agent 相同),在长会话中会导致每轮都提前压缩。 ### 2. Agent ContextCompressor(50% 阈值,可配置) {#2-agent-contextcompressor-50-threshold-configurable} 位于 `agent/context_compressor.py`。这是**主要压缩系统**,在 Agent 的工具循环内部运行,并可访问准确的、由 API 报告的 token 数。 ## 配置 {#configuration} 所有压缩设置均从 `config.yaml` 中 `compression` 键下读取: ```yaml compression: enabled: true # 启用/disable compression(默认值:true) threshold: 0.50 # context window 的分数(默认值:0.50 = 50%) target_ratio: 0.20 # 保留多少阈值作为尾部(默认值:0.20) protect_last_n: 20 # 最小受保护尾部消息(默认值:20) summary_model: null # 覆盖 model 进行摘要(默认:使用辅助) ``` ### 参数详情 {#parameter-details} | 参数 | 默认值 | 范围 | 描述 | |------|--------|------|------| | `threshold` | `0.50` | 0.0–1.0 | 当提示词 token 数 ≥ `threshold × context_length` 时触发压缩 | | `target_ratio` | `0.20` | 0.10–0.80 | 控制尾部保护 token 预算:`threshold_tokens × target_ratio` | | `protect_last_n` | `20` | ≥1 | 始终保留的最近消息最小数量 | | `protect_first_n` | `3` | (硬编码) | 系统提示 + 第一次交互始终保留 | ### 计算值(以 200K 上下文模型为例,使用默认值) {#computed-values-for-a-200k-context-model-at-defaults} ``` context_length = 200,000 threshold_tokens = 200,000 × 0.50 = 100,000 tail_token_budget = 100,000 × 0.20 = 20,000 max_summary_tokens = min(200,000 × 0.05, 12,000) = 10,000 ``` ## 压缩算法 {#compression-algorithm} `ContextCompressor.compress()` 方法遵循四阶段算法: ### 阶段 1:清除旧工具结果(低成本,无需 LLM 调用) {#phase-1-prune-old-tool-results-cheap-no-llm-call} 将超出保护尾部的旧工具结果(>200 字符)替换为: ``` [Old tool output cleared to save context space] ``` 这是一个低成本的预处理步骤,可显著节省来自冗长工具输出(文件内容、终端输出、搜索结果)的 token。 ### 阶段 2:确定边界 {#phase-2-determine-boundaries} ``` ┌─────────────────────────────────────────────────────────────┐ │ Message list │ │ │ │ [0..2] ← protect_first_n (system + first exchange) │ │ [3..N] ← middle turns → SUMMARIZED │ │ [N..end] ← tail (by token budget OR protect_last_n) │ │ │ └─────────────────────────────────────────────────────────────┘ ``` 尾部保护基于**token 预算**:从末尾向后遍历,累计 token 直到预算耗尽。若预算保护的消息数少于 `protect_last_n`,则回退到固定数量。 边界对齐以避免拆分 `tool_call`/`tool_result` 组。`_align_boundary_backward()` 方法会跳过连续的工具结果,找到父级助手消息,确保组完整。 ### 阶段 3:生成结构化摘要 {#phase-3-generate-structured-summary} 中间轮次使用辅助 LLM 和结构化模板进行摘要: ``` ## 目标 [What the user is trying to accomplish] ## 约束与偏好 [User preferences, coding style, constraints, important decisions] ## 进度 ### 已完成 [Completed work — specific file paths, commands run, results] ### 进行中 [Work currently underway] ### 阻塞项 [Any blockers or issues encountered] ## 关键决策 [Important technical decisions and why] ## 相关文件 [Files read, modified, or created — with brief note on each] ## 下一步 [What needs to happen next] ## 关键上下文 [Specific values, error messages, configuration details] ``` 摘要预算随压缩内容量动态调整: - 公式:`content_tokens × 0.20`(`_SUMMARY_RATIO` 常量) - 最小值:2,000 token - 最大值:`min(context_length × 0.05, 12,000)` token ### 阶段 4:组装压缩后的消息 {#phase-4-assemble-compressed-messages} 压缩后的消息列表包含: 1. 头部消息(首次压缩时在系统提示后附加说明) 2. 摘要消息(角色选择避免连续同角色违规) 3. 尾部消息(保持不变) 未关联的 `tool_call`/`tool_result` 对由 `_sanitize_tool_pairs()` 进行清理: - 引用已删除调用的工具结果 → 被移除 - 其结果已被移除的工具调用 → 注入占位结果 ### 迭代式重压缩 {#iterative-re-compression} 在后续的压缩过程中,上一次的摘要会被传递给 LLM,并附带指令以**更新**该摘要,而非从头开始重新总结。这能够保留多次压缩之间的信息——项目从“进行中”变为“已完成”,新增进展被加入,过时信息被移除。 压缩器实例上的 `_previous_summary` 字段用于存储上一次的摘要文本,以实现此目的。 ## 压缩前后示例 {#beforeafter-example} ### 压缩前(45 条消息,约 95K 标记) {#before-compression-45-messages-95k-tokens} ``` [0] system: "You are a helpful assistant..." (system prompt) [1] user: "Help me set up a FastAPI project" [2] assistant: terminal: mkdir project [3] tool: "directory created" [4] assistant: write_file: main.py [5] tool: "file written (2.3KB)" ... 30 more turns of file editing, testing, debugging ... [38] assistant: terminal: pytest [39] tool: "8 passed, 2 failed\n..." (5KB output) [40] user: "Fix the failing tests" [41] assistant: read_file: tests/test_api.py [42] tool: "import pytest\n..." (3KB) [43] assistant: "I see the issue with the test fixtures..." [44] user: "Great, also add error handling" ``` ### 压缩后(25 条消息,约 45K 标记) {#after-compression-25-messages-45k-tokens} ``` [0] system: "You are a helpful assistant... [Note: Some earlier conversation turns have been compacted...]" [1] user: "Help me set up a FastAPI project" [2] assistant: "[CONTEXT COMPACTION] Earlier turns were compacted... ## 目标 Set up a FastAPI project with tests and error handling ## 进度 ### 已完成 - Created project structure: main.py, tests/, requirements.txt - Implemented 5 API endpoints in main.py - Wrote 10 test cases in tests/test_api.py - 8/10 tests passing ### 进行中 - Fixing 2 failing tests (test_create_user, test_delete_user) ## 相关文件 - main.py — FastAPI app with 5 endpoints - tests/test_api.py — 10 test cases - requirements.txt — fastapi, pytest, httpx ## 下一步 - Fix failing test fixtures - Add error handling" [3] user: "Fix the failing tests" [4] assistant: read_file: tests/test_api.py [5] tool: "import pytest\n..." [6] assistant: "I see the issue with the test fixtures..." [7] user: "Great, also add error handling" ``` ## 提示词缓存(Anthropic) {#prompt-caching-anthropic} 来源:`agent/prompt_caching.py` 通过缓存对话前缀,将多轮对话的输入标记成本降低约 75%。使用 Anthropic 的 `cache_control` 断点机制。 ### 策略:system_and_3 {#strategy-system_and_3} Anthropic 每个请求最多允许 4 个 `cache_control` 断点。Hermes 使用“system_and_3”策略: ``` Breakpoint 1: System prompt (stable across all turns) Breakpoint 2: 3rd-to-last non-system message ─┐ Breakpoint 3: 2nd-to-last non-system message ├─ Rolling window Breakpoint 4: Last non-system message ─┘ ``` ### 工作原理 {#how-it-works} `apply_anthropic_cache_control()` 对消息进行深度复制,并注入 `cache_control` 标记: ```python # 缓存标记格式 marker = {"type": "ephemeral"} # 或者 1 小时 TTL: marker = {"type": "ephemeral", "ttl": "1h"} ``` 标记的插入位置根据内容类型有所不同: | 内容类型 | 标记插入位置 | |---------|-------------| | 字符串内容 | 转换为 `[{"type": "text", "text": ..., "cache_control": ...}]` | | 列表内容 | 添加到最后一个元素的字典中 | | None/空值 | 作为 `msg["cache_control"]` 添加 | | 工具消息 | 作为 `msg["cache_control"]` 添加(仅限原生 Anthropic) | ### 缓存感知设计模式 {#cache-aware-design-patterns} 1. **稳定的系统提示**:系统提示为断点 1,跨所有轮次缓存。避免在对话过程中修改它(压缩仅在首次压缩时追加一条备注)。 2. **消息顺序至关重要**:缓存命中要求前缀匹配。在中间插入或删除消息会使得之后所有内容的缓存失效。 3. **压缩与缓存的交互**:压缩后,压缩区域的缓存被失效,但系统提示缓存得以保留。滚动的 3 条消息窗口可在 1-2 轮内重新建立缓存。 4. **TTL 选择**:默认为 `5m`(5 分钟)。对于用户在轮次间有长时间停顿的长会话,建议使用 `1h`。 ### 启用提示词缓存 {#enabling-prompt-caching} 当满足以下条件时,提示词缓存会自动启用: - 模型为 Anthropic Claude 模型(通过模型名称检测) - 提供商支持 `cache_control`(原生 Anthropic API 或 OpenRouter) ```yaml # config.yaml — TTL 可配置 model: cache_ttl: "5m" # “0”或“1” ``` CLI 在启动时显示缓存状态: ``` 💾 Prompt caching: ENABLED (Claude via OpenRouter, 5m TTL) ``` ## 上下文压力警告 {#context-pressure-warnings} 当使用量达到压缩阈值的 85% 时(不是上下文总量的 85%,而是阈值本身的 85%,而该阈值本身为上下文总量的 50%),Agent 会发出上下文压力警告: ``` ⚠️ Context is 85% to compaction threshold (42,500/50,000 tokens) ``` 压缩后,若使用量降至阈值的 85% 以下,则警告状态被清除。如果压缩未能将使用量降至警告水平以下(对话过于密集),警告将持续存在,但压缩不会再次触发,直到使用量再次超过阈值。 --- ### 上下文引擎插件 - URL: https://hermesagent.org.cn/docs/developer-guide/context-engine-plugin - Path: developer-guide/context-engine-plugin.md - Category: developer-guide - Description: 如何构建一个替换内置 ContextCompressor 的上下文引擎插件 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/context-engine-plugin.md - Translated At: 2026-04-11T03:22:34.246Z - Headings: 工作原理 | 目录结构 | ContextEngine 抽象基类 | 引擎必须维护的类属性 | 可选方法 | 引擎工具 | 注册 | 通过目录(推荐方式) | 通过通用插件系统 | 生命周期 | 配置 | 测试 # 构建上下文引擎插件 {#building-a-context-engine-plugin} 上下文引擎插件会替换内置的 `ContextCompressor`,采用替代策略来管理对话上下文。例如,一种无损上下文管理(LCM)引擎,它构建知识有向无环图(DAG)而非有损摘要。 ## 工作原理 {#how-it-works} Agent 的上下文管理基于 `ContextEngine` 抽象基类(`agent/context_engine.py`)。内置的 `ContextCompressor` 是默认实现。插件引擎必须实现相同的接口。 同一时间**只能激活一个**上下文引擎。选择由配置驱动: ```yaml # config.yaml context: engine: "compressor" # 默认内置 engine: "lcm" # 激活名为“0”的插件引擎 ``` 插件引擎**不会自动激活**——用户必须显式将 `context.engine` 设置为插件名称。 ## 目录结构 {#directory-structure} 每个上下文引擎位于 `plugins/context_engine//` 目录下: ``` plugins/context_engine/lcm/ ├── __init__.py # 导出 ContextEngine 子类 ├── plugin.yaml # 元数据(名称、描述、版本) └── ... # 您的引擎需要的任何其他模块 ``` ## ContextEngine 抽象基类 {#the-contextengine-abc} 您的引擎必须实现以下**必需**方法: ```python from agent.context_engine import ContextEngine class LCMEngine(ContextEngine): @property def name(self) -> str: """Short identifier, e.g. 'lcm'. Must match config.yaml value.""" return "lcm" def update_from_response(self, usage: dict) -> None: """Called after every LLM call with the usage dict. Update self.last_prompt_tokens, self.last_completion_tokens, self.last_total_tokens from the response. """ def should_compress(self, prompt_tokens: int = None) -> bool: """Return True if compaction should fire this turn.""" def compress(self, messages: list, current_tokens: int = None) -> list: """Compact the message list and return a new (possibly shorter) list. The returned list must be a valid OpenAI-format message sequence. """ ``` ### 引擎必须维护的类属性 {#class-attributes-your-engine-must-maintain} Agent 会直接读取这些属性用于显示和日志记录: ```python last_prompt_tokens: int = 0 last_completion_tokens: int = 0 last_total_tokens: int = 0 threshold_tokens: int = 0 # 当compression触发时 context_length: int = 0 # model 的完整 context window compression_count: int = 0 # compress() 运行了多少次 ``` ### 可选方法 {#optional-methods} 这些方法在 ABC 中已有合理默认实现。按需重写: | 方法 | 默认行为 | 重写场景 | |------|----------|----------| | `on_session_start(session_id, **kwargs)` | 空操作 | 需要加载持久化状态(DAG、数据库) | | `on_session_end(session_id, messages)` | 空操作 | 需要刷新状态、关闭连接 | | `on_session_reset()` | 重置 token 计数器 | 有需要清除的会话级状态 | | `update_model(model, context_length, ...)` | 更新 context_length + threshold | 模型切换时需要重新计算预算 | | `get_tool_schemas()` | 返回 `[]` | 引擎提供 Agent 可调用的工具(如 `lcm_grep`) | | `handle_tool_call(name, args, **kwargs)` | 返回错误 JSON | 实现工具处理器 | | `should_compress_preflight(messages)` | 返回 `False` | 可在 API 调用前进行低成本预估 | | `get_status()` | 返回标准的 token/threshold 字典 | 有自定义指标需要暴露 | ## 引擎工具 {#engine-tools} 上下文引擎可以向 Agent 暴露直接调用的工具。通过 `get_tool_schemas()` 返回工具 schema,并在 `handle_tool_call()` 中处理调用: ```python def get_tool_schemas(self): return [{ "name": "lcm_grep", "description": "Search the context knowledge graph", "parameters": { "type": "object", "properties": { "query": {"type": "string", "description": "Search query"} }, "required": ["query"], }, }] def handle_tool_call(self, name, args, **kwargs): if name == "lcm_grep": results = self._search_dag(args["query"]) return json.dumps({"results": results}) return json.dumps({"error": f"Unknown tool: {name}"}) ``` 引擎工具会在 Agent 启动时自动注入到工具列表中并被自动分发——无需注册到注册表。 ## 注册 {#registration} ### 通过目录(推荐方式) {#via-directory-recommended} 将您的引擎放置于 `plugins/context_engine//` 目录下。`__init__.py` 必须导出一个 `ContextEngine` 子类。发现系统会自动查找并实例化它。 ### 通过通用插件系统 {#via-general-plugin-system} 通用插件也可以注册一个上下文引擎: ```python def register(ctx): engine = LCMEngine(context_length=200000) ctx.register_context_engine(engine) ``` 只能注册一个引擎。第二个尝试注册的插件将被拒绝,并发出警告。 ## 生命周期 {#lifecycle} ``` 1. Engine instantiated (plugin load or directory discovery) 2. on_session_start() — conversation begins 3. update_from_response() — after each API call 4. should_compress() — checked each turn 5. compress() — called when should_compress() returns True 6. on_session_end() — session boundary (CLI exit, /reset, gateway expiry) ``` `on_session_reset()` 在 `/new` 或 `/reset` 时被调用,用于清除会话级状态,而无需完全关闭。 ## 配置 {#configuration} 用户通过 `hermes plugins` → Provider Plugins → Context Engine 选择您的引擎,或通过编辑 `config.yaml` 进行配置: ```yaml context: engine: "lcm" # 必须与您的引擎的名称属性匹配 ``` `compression` 配置块(如 `compression.threshold`、`compression.protect_last_n` 等)专属于内置的 `ContextCompressor`。如果您的引擎需要自定义配置格式,应在初始化时从 `config.yaml` 读取。 ## 测试 {#testing} ```python from agent.context_engine import ContextEngine def test_engine_satisfies_abc(): engine = YourEngine(context_length=200000) assert isinstance(engine, ContextEngine) assert engine.name == "your-name" def test_compress_returns_valid_messages(): engine = YourEngine(context_length=200000) msgs = [{"role": "user", "content": "hello"}] result = engine.compress(msgs) assert isinstance(result, list) assert all("role" in m for m in result) ``` 请参阅 `tests/agent/test_context_engine.py` 以获取完整的 ABC 合约测试套件。 ## 参见 {#see-also} - [上下文压缩与缓存](/docs/developer-guide/context-compression-and-caching) — 内置压缩器的工作原理 - [记忆提供者插件](/docs/developer-guide/memory-provider-plugin) — 与上下文引擎类似的单选插件系统 - [插件](/docs/user-guide/features/plugins) — 通用插件系统概览 --- ### 贡献 - URL: https://hermesagent.org.cn/docs/developer-guide/contributing - Path: developer-guide/contributing.md - Category: developer-guide - Description: 如何为 Hermes Agent 贡献 —— 开发环境设置、代码风格、Pull Request 流程 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/contributing.md - Translated At: 2026-04-11T03:22:57.770Z - Headings: 贡献优先级 | 常见贡献路径 | 开发环境设置 | 前提条件 | 克隆与安装 | 开发配置 | 运行 | 运行测试 | 代码风格 | 跨平台兼容性 | 1. termios 和 fcntl 仅限 Unix | 2. 文件编码 # 贡献指南 {#contributing} 感谢您为 Hermes Agent 做出贡献!本指南涵盖设置开发环境、理解代码库以及提交您的 PR 并成功合并的流程。 ## 贡献优先级 {#contribution-priorities} 我们按以下顺序重视贡献: 1. **缺陷修复** —— 崩溃、错误行为、数据丢失 2. **跨平台兼容性** —— macOS、不同 Linux 发行版、WSL2、原生 Windows 3. **安全加固** —— shell 注入、提示注入、路径遍历 4. **性能与健壮性** —— 重试逻辑、错误处理、优雅降级 5. **新技能** —— 广泛有用的技能(参见 [创建技能](creating-skills)) 6. **新工具** —— 较少需要;大多数功能应通过技能实现 7. **文档** —— 修复、澄清、新增示例 ## 常见贡献路径 {#common-contribution-paths} - 要构建新工具?请从 [添加工具](adding-tools) 开始 - 要构建新技能?请从 [创建技能](creating-skills) 开始 - 要构建新推理提供者?请从 [添加提供者](adding-providers) 开始 ## 开发环境设置 {#development-setup} ### 前提条件 {#prerequisites} | 要求 | 说明 | |------|------| | **Git** | 需支持 `--recurse-submodules` | | **Python 3.11+** | 若缺失,uv 会自动安装 | | **uv** | 快速的 Python 包管理器 ([安装指南](https://docs.astral.sh/uv/)) | | **Node.js 18+** | 可选 —— 用于浏览器工具和 WhatsApp 桥接 | ### 克隆与安装 {#clone-and-install} ```bash git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git cd hermes-agent # 使用 Python 3.11 创建虚拟环境 uv venv venv --python 3.11 export VIRTUAL_ENV="$(pwd)/venv" # 安装所有附加功能(消息、cron、CLI 菜单、开发 tools) uv pip install -e ".[all,dev]" uv pip install -e "./tinker-atropos" # 可选:浏览器tools npm install ``` ### 开发配置 {#configure-for-development} ```bash mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills} cp cli-config.yaml.example ~/.hermes/config.yaml touch ~/.hermes/.env # 至少添加一个 LLM provider 密钥: echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env ``` ### 运行 {#run} ```bash # 用于全局访问的符号链接 mkdir -p ~/.local/bin ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes # 验证 hermes doctor hermes chat -q "Hello" ``` ### 运行测试 {#run-tests} ```bash pytest tests/ -v ``` ## 代码风格 {#code-style} - **PEP 8**,允许实际例外(不强制行长度限制) - **注释**:仅在解释非显而易见的意图、权衡或 API 特性时使用 - **错误处理**:捕获具体异常。对于意外错误,使用 `logger.warning()` / `logger.error()` 并传入 `exc_info=True` - **跨平台**:永远不要假设为 Unix 系统(见下文) - **安全路径**:永远不要硬编码 `~/.hermes` —— 代码路径请使用 `hermes_constants` 中的 `get_hermes_home()`,用户提示信息请使用 `display_hermes_home()`。完整规则参见 [AGENTS.md](https://github.com/NousResearch/hermes-agent/blob/main/AGENTS#profiles-multi-instance-support) ## 跨平台兼容性 {#cross-platform-compatibility} Hermes 官方支持 Linux、macOS、WSL2 和原生 Windows。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以原生安装;代码库仍需要保留防御性跨平台编码模式,避免在 Windows 边缘情况下发生硬崩溃。关键规则如下: ### 1. `termios` 和 `fcntl` 仅限 Unix {#1-termios-and-fcntl-are-unix-only} 始终捕获 `ImportError` 和 `NotImplementedError`: ```python try: from simple_term_menu import TerminalMenu menu = TerminalMenu(options) idx = menu.show() except (ImportError, NotImplementedError): # 后备:编号菜单 for i, opt in enumerate(options): print(f" {i+1}. {opt}") idx = int(input("Choice: ")) - 1 ``` ### 2. 文件编码 {#2-file-encoding} 某些环境可能以非 UTF-8 编码保存 `.env` 文件: ```python try: load_dotenv(env_path) except UnicodeDecodeError: load_dotenv(env_path, encoding="latin-1") ``` ### 3. 进程管理 {#3-process-management} `os.setsid()`、`os.killpg()` 和信号处理在不同平台间存在差异: ```python import platform if platform.system() != "Windows": kwargs["preexec_fn"] = os.setsid ``` ### 4. 路径分隔符 {#4-path-separators} 请使用 `pathlib.Path`,而非字符串拼接使用 `/`。 ## 安全注意事项 {#security-considerations} Hermes 拥有终端访问权限,安全至关重要。 ### 现有防护措施 {#existing-protections} | 层级 | 实现方式 | |------|----------| | **sudo 密码管道** | 使用 `shlex.quote()` 防止 shell 注入 | | **危险命令检测** | `tools/approval.py` 中的正则模式,配合用户确认流程 | | **Cron 提示注入** | 扫描器阻止指令覆盖模式 | | **写入拒绝列表** | 受保护路径通过 `os.path.realpath()` 解析,防止符号链接绕过 | | **技能防护** | 用于 hub 安装技能的安全扫描器 | | **代码执行沙箱** | 子进程运行时剥离 API 密钥 | | **容器加固** | Docker:所有能力被移除,无权限提升,PID 限制 | ### 贡献安全敏感代码 {#contributing-security-sensitive-code} - 在将用户输入插入 shell 命令时,始终使用 `shlex.quote()` - 在访问控制检查前,使用 `os.path.realpath()` 解析符号链接 - 不要记录密钥 - 在工具执行周围捕获宽泛异常 - 若您的更改涉及文件路径或进程,请在所有平台上进行测试 ## 拉取请求流程 {#pull-request-process} ### 分支命名 {#branch-naming} ``` fix/description # 错误修复 feat/description # 新功能 docs/description # 文档 test/description # 测试 refactor/description # 代码重构 ``` ### 提交前检查 {#before-submitting} 1. **运行测试**:`pytest tests/ -v` 2. **手动测试**:运行 `hermes` 并测试您修改的代码路径 3. **检查跨平台影响**:考虑 macOS 和不同 Linux 发行版 4. **保持 PR 聚焦**:每个 PR 仅包含一个逻辑变更 ### PR 描述 {#pr-description} 请包含: - **变更内容** 及 **原因** - **如何测试** 该变更 - **测试过的平台** - 引用任何相关问题 ### 提交信息 {#commit-messages} 我们使用 [Conventional Commits](https://www.conventionalcommits.org/): ``` (): ``` | 类型 | 用途 | |------|------| | `fix` | 修复缺陷 | | `feat` | 新功能 | | `docs` | 文档 | | `test` | 测试 | | `refactor` | 代码重构 | | `chore` | 构建、CI、依赖更新 | 作用域:`cli`、`gateway`、`tools`、`skills`、`agent`、`install`、`whatsapp`、`security` 示例: ``` fix(cli): prevent crash in save_config_value when model is a string feat(gateway): add WhatsApp multi-user session isolation fix(security): prevent shell injection in sudo password piping ``` ## 报告问题 {#reporting-issues} - 使用 [GitHub Issues](https://github.com/NousResearch/hermes-agent/issues) - 请包含:操作系统、Python 版本、Hermes 版本(`hermes version` 命令输出),以及完整的错误堆栈追踪 - 请提供复现步骤 - 创建新问题前,请先检查是否存在重复问题 - 如发现安全漏洞,请私密报告 ## 社区 {#community} - **Discord**: [discord.gg/NousResearch](https://discord.gg/NousResearch) - **GitHub Discussions**:用于设计提案和架构讨论 - **Skills Hub**:上传专业技能并与其他社区成员共享 ## 许可证 {#license} 通过贡献,您同意您的贡献将遵循 [MIT 许可证](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE)。 --- ### 创建技能 - URL: https://hermesagent.org.cn/docs/developer-guide/creating-skills - Path: developer-guide/creating-skills.md - Category: developer-guide - Description: 如何为 Hermes Agent 创建技能 —— SKILL.md 格式、指南与发布 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/creating-skills.md - Translated At: 2026-04-11T03:23:05.059Z - Headings: 应该创建技能还是工具? | 技能目录结构 | SKILL.md 格式 | 何时使用 | 快速参考 | 操作步骤 | 常见陷阱 | 验证方式 | 平台特定技能 | 条件性技能激活 | 环境变量需求 | 加载时的安全设置 # 创建技能 {#creating-skills} 技能是向 Hermes Agent 添加新功能的首选方式。相比工具,技能更易于创建,无需修改 Agent 代码,并且可以与社区共享。 ## 应该创建技能还是工具? {#should-it-be-a-skill-or-a-tool} 当满足以下条件时,请创建一个 **技能**: - 功能可以通过指令 + shell 命令 + 现有工具来表达 - 包装了一个外部 CLI 或 API,Agent 可通过 `terminal` 或 `web_extract` 调用 - 不需要在 Agent 中内嵌自定义的 Python 集成或 API 密钥管理 - 示例:arXiv 搜索、git 工作流、Docker 管理、PDF 处理、通过 CLI 工具发送邮件 当满足以下条件时,请创建一个 **工具**: - 需要与 API 密钥、认证流程或多组件配置进行端到端集成 - 需要自定义处理逻辑,且必须每次精确执行 - 处理二进制数据、流式传输或实时事件 - 示例:浏览器自动化、TTS、视觉分析 ## 技能目录结构 {#skill-directory-structure} 内置技能位于 `skills/` 目录中,按类别组织。官方可选技能使用相同的结构存放于 `optional-skills/` 中: ```text skills/ ├── research/ │ └── arxiv/ │ ├── SKILL.md # 必填:主要说明 │ └── scripts/ # 可选:帮助脚本 │ └── search_arxiv.py ├── productivity/ │ └── ocr-and-documents/ │ ├── SKILL.md │ ├── scripts/ │ └── references/ └── ... ``` ## SKILL.md 格式 {#skillmd-format} ```markdown --- name: my-skill description: Brief description (shown in skill search results) version: 1.0.0 author: Your Name license: MIT platforms: [macos, linux] # 可选 — 仅限于特定操作系统平台 # 有效:macos、linux、Windows # 省略在所有平台上加载(默认) metadata: hermes: tags: [Category, Subcategory, Keywords] related_skills: [other-skill-name] requires_toolsets: [web] # 可选 — 仅当这些 toolsets 处于活动状态时显示 requires_tools: [web_search] # 可选 — 仅当这些 tools 可用时显示 fallback_for_toolsets: [browser] # 可选 — 当这些 toolsets 处于活动状态时隐藏 fallback_for_tools: [browser_navigate] # 可选 — 当这些 tools 存在时隐藏 config: # 可选 — config.yaml skill 需要的设置 - key: my.setting description: "What this setting controls" default: "sensible-default" prompt: "Display prompt for setup" required_environment_variables: # 可选 — skill 需要的环境变量 - name: MY_API_KEY prompt: "Enter your API key" help: "Get one at https://example.com" required_for: "API access" --- # Skill 标题 Brief intro. ## 何时使用 Trigger conditions — when should the agent load this skill? ## 快速参考 Table of common commands or API calls. ## 操作步骤 Step-by-step instructions the agent follows. ## 常见陷阱 Known failure modes and how to handle them. ## 验证方式 How the agent confirms it worked. ``` ### 平台特定技能 {#platform-specific-skills} 技能可以通过 `platforms` 字段限制其适用的操作系统: ```yaml platforms: [macos] # 仅限 macOS(例如 iMessage、Apple 提醒) platforms: [macos, linux] # macOS 和 Linux platforms: [windows] # 仅限 Windows ``` 设置后,该技能将自动从系统提示、`skills_list()` 和斜杠命令中隐藏,以避免在不兼容的平台上显示。若省略或为空,则该技能在所有平台上加载(向后兼容)。 ### 条件性技能激活 {#conditional-skill-activation} 技能可以声明对特定工具或工具集的依赖关系,从而控制该技能在特定会话的系统提示中是否出现。 ```yaml metadata: hermes: requires_toolsets: [web] # 如果网络 toolset 处于 NOT 活动状态则隐藏 requires_tools: [web_search] # 如果 `web_search` Tool 不可用则隐藏 fallback_for_toolsets: [browser] # 如果浏览器 toolset 处于活动状态则隐藏 fallback_for_tools: [browser_navigate] # 如果 `browser_navigate` 可用则隐藏 ``` | 字段 | 行为 | |------|------| | `requires_toolsets` | 当任意列出的工具集 **不可用** 时,该技能被 **隐藏** | | `requires_tools` | 当任意列出的工具 **不可用** 时,该技能被 **隐藏** | | `fallback_for_toolsets` | 当任意列出的工具集 **可用** 时,该技能被 **隐藏** | | `fallback_for_tools` | 当任意列出的工具 **可用** 时,该技能被 **隐藏** | **`fallback_for_*` 的使用场景:** 创建一个备用技能,用于主工具不可用时的替代方案。例如,一个 `duckduckgo-search` 技能设置 `fallback_for_tools: [web_search]`,仅在未配置 Web 搜索工具(需要 API 密钥)时显示。 **`requires_*` 的使用场景:** 创建一个仅在某些工具存在时才有意义的技能。例如,一个网页抓取工作流技能设置 `requires_toolsets: [web]`,当 Web 工具被禁用时不会污染提示。 ### 环境变量需求 {#environment-variable-requirements} 技能可以声明其所需的环境变量。当通过 `skill_view` 加载技能时,其所需变量会自动注册并传入沙箱执行环境(terminal、execute_code)。 ```yaml required_environment_variables: - name: TENOR_API_KEY prompt: "Tenor API key" # 提示用户时显示 help: "Get your key at https://tenor.com" # 帮助文本或 URL required_for: "GIF search functionality" # 什么需要这个变量 ``` 每项条目支持: - `name`(必需)—— 环境变量名称 - `prompt`(可选)—— 向用户询问值时的提示文本 - `help`(可选)—— 获取该值的帮助文本或 URL - `required_for`(可选)—— 描述该变量所服务的功能 用户也可以在 `config.yaml` 中手动配置传入变量: ```yaml terminal: env_passthrough: - MY_CUSTOM_VAR - ANOTHER_VAR ``` 请参阅 `skills/apple/` 以获取 macOS 专用技能的示例。 ## 加载时的安全设置 {#secure-setup-on-load} 当技能需要 API 密钥或令牌时,请使用 `required_environment_variables`。缺少值 **不会** 将技能从发现中隐藏。相反,Hermes 在本地 CLI 中加载技能时会安全地提示用户输入。 ```yaml required_environment_variables: - name: TENOR_API_KEY prompt: Tenor API key help: Get a key from https://developers.google.com/tenor required_for: full functionality ``` 用户可以选择跳过设置并继续加载技能。Hermes 永远不会将原始密钥值暴露给模型。网关和消息会话将显示本地设置指引,而不是在带外收集密钥。 :::tip 沙箱传入 当你的技能被加载时,任何已设置的 `required_environment_variables` 都会 **自动传入** `execute_code` 和 `terminal` 沙箱——包括远程后端如 Docker 和 Modal。你的技能脚本可以直接访问 `$TENOR_API_KEY`(或 Python 中的 `os.environ["TENOR_API_KEY"]`),无需用户额外配置。详情请参见 [环境变量传入](/docs/user-guide/security#environment-variable-passthrough)。 ::: 旧版的 `prerequisites.env_vars` 仍作为向后兼容的别名被支持。 ### 配置设置(config.yaml) {#config-settings-configyaml} 技能可以声明非敏感的配置项,这些设置将存储在 `config.yaml` 的 `skills.config` 命名空间下。与存储在 `.env` 中的环境变量(密钥)不同,配置项用于路径、偏好设置等非敏感值。 ```yaml metadata: hermes: config: - key: wiki.path description: Path to the LLM Wiki knowledge base directory default: "~/wiki" prompt: Wiki directory path - key: wiki.domain description: Domain the wiki covers default: "" prompt: Wiki domain (e.g., AI/ML research) ``` 每项条目支持: - `key`(必需)—— 设置的点路径(例如 `wiki.path`) - `description`(必需)—— 说明该设置控制的内容 - `default`(可选)—— 用户未配置时的默认值 - `prompt`(可选)—— 在执行 `hermes config migrate` 时显示的提示文本;若未提供则回退到 `description` **工作原理:** 1. **存储**:值将写入 `config.yaml` 中的 `skills.config.` 下: ```yaml skills: config: wiki: path: ~/my-research ``` 2. **发现**:`hermes config migrate` 会扫描所有已启用的技能,查找未配置的设置,并提示用户进行配置。这些设置也会在 `hermes config show` 中的“技能设置”部分显示。 3. **运行时注入**:当一个技能加载时,其配置值会被解析并附加到技能消息中: ``` [Skill config (from ~/.hermes/config.yaml): wiki.path = /home/user/my-research ] ``` Agent 在无需自行读取 `config.yaml` 的情况下即可看到已配置的值。 4. **手动设置**:用户也可以直接设置值: ```bash hermes config set skills.config.wiki.path ~/my-wiki ``` :::tip 何时使用哪种方式 使用 `required_environment_variables` 来处理 API 密钥、令牌等**敏感信息**(存储在 `~/.hermes/.env` 中,不会显示给模型)。使用 `config` 来处理**路径、偏好设置和非敏感配置**(存储在 `config.yaml` 中,可在 `config show` 中查看)。 ::: ### 凭据文件要求(OAuth 令牌等) {#credential-file-requirements-oauth-tokens-etc} 使用 OAuth 或基于文件的凭据的技能可以声明需要挂载到远程沙箱中的文件。这适用于以**文件形式存储**的凭据(而非环境变量)——通常是设置脚本生成的 OAuth 令牌文件。 ```yaml required_credential_files: - path: google_token.json description: Google OAuth2 token (created by setup script) - path: google_client_secret.json description: Google OAuth2 client credentials ``` 每个条目支持: - `path`(必需)——相对于 `~/.hermes/` 的文件路径 - `description`(可选)——说明文件用途以及如何创建 加载时,Hermes 会检查这些文件是否存在。若文件缺失,则触发 `setup_needed`。已存在的文件将自动: - **挂载到 Docker 容器**中作为只读绑定挂载 - **同步到 Modal 沙箱**(在创建时以及每次命令执行前同步,因此支持会话期间的 OAuth) - 在**本地后端**上直接可用,无需特殊处理 :::tip 何时使用哪种方式 使用 `required_environment_variables` 来处理简单的 API 密钥和令牌(字符串存储在 `~/.hermes/.env` 中)。使用 `required_credential_files` 来处理 OAuth 令牌文件、客户端密钥、服务账户 JSON、证书,或任何以磁盘文件形式存在的凭据。 ::: 请参阅 `skills/productivity/google-workspace/SKILL.md` 以获取同时使用两者的完整示例。 ## 技能编写指南 {#skill-guidelines} ### 无外部依赖 {#no-external-dependencies} 优先使用标准库 Python、curl 和现有的 Hermes 工具(如 `web_extract`、`terminal`、`read_file`)。如果必须引入依赖,请在技能文档中说明安装步骤。 ### 渐进式披露 {#progressive-disclosure} 将最常见的工作流放在最前面。边缘情况和高级用法置于底部。这有助于降低常见任务的 token 使用量。 ### 包含辅助脚本 {#include-helper-scripts} 对于 XML/JSON 解析或复杂逻辑,应在 `scripts/` 目录中包含辅助脚本——不要期望 LLM 每次都内联编写解析器。 ### 进行测试 {#test-it} 运行该技能并验证 Agent 是否正确遵循了指令: ```bash hermes chat --toolsets skills -q "Use the X skill to do Y" ``` ## 技能应放置在何处? {#where-should-the-skill-live} 捆绑技能(位于 `skills/` 中)随每个 Hermes 安装一起提供。它们应具有**对大多数用户都广泛有用**的特性: - 文档处理、网络研究、常见开发工作流、系统管理 - 被广泛人群频繁使用 如果你的技能是官方的且有用,但并非普遍需要(例如付费服务集成、重型依赖),请将其放入 **`optional-skills/`** —— 它会随仓库一起发布,可通过 `hermes skills browse` 发现(标记为“官方”),并以内置信任方式安装。 如果你的技能是专业化的、社区贡献的或小众的,更适合发布到 **技能中心(Skills Hub)** —— 上传至注册表,并通过 `hermes skills install` 共享。 ## 发布技能 {#publishing-skills} ### 发布到技能中心 {#to-the-skills-hub} ```bash hermes skills publish skills/my-skill --to github --repo owner/repo ``` ### 发布到自定义仓库 {#to-a-custom-repository} 将你的仓库添加为一个 tap: ```bash hermes skills tap add owner/repo ``` 用户随后即可从你的仓库中搜索并安装技能。 ## 安全扫描 {#security-scanning} 所有通过技能中心安装的技能都会经过安全扫描,检查以下内容: - 数据外泄模式 - 提示注入尝试 - 破坏性命令 - Shell 注入 信任等级: - `builtin` —— 随 Hermes 一起发布(始终受信任) - `official` —— 来自仓库中的 `optional-skills/`(内置信任,无第三方警告) - `trusted` —— 来自 openai/skills、anthropics/skills - `community` —— 非危险发现可使用 `--force` 覆盖;危险判定仍被阻止 Hermes 现在可从多个外部发现模型中消费第三方技能: - 直接使用 GitHub 标识符(例如 `openai/skills/k8s`) - 使用 `skills.sh` 标识符(例如 `skills-sh/vercel-labs/json-render/json-render-react`) - 从 `/.well-known/skills/index.json` 提供的知名端点 如果你希望你的技能在无需 GitHub 特定安装器的情况下也能被发现,建议除了在仓库或市场中发布外,还提供一个知名端点。 --- ### Cron 内部机制 - URL: https://hermesagent.org.cn/docs/developer-guide/cron-internals - Path: developer-guide/cron-internals.md - Category: developer-guide - Description: Hermes 如何存储、调度、编辑、暂停、加载技能以及分发 cron 任务 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/cron-internals.md - Translated At: 2026-04-11T03:23:26.198Z - Headings: 核心文件 | 调度模型 | 任务存储 | 任务生命周期状态 | 向后兼容性 | 调度器运行时 | 时钟周期 | 网关集成 | 新会话隔离 | 技能驱动的任务 | 脚本驱动的任务 | 提供商恢复机制 # Cron 内部机制 {#cron-internals} cron 子系统提供定时任务执行功能——从简单的单次延迟任务,到支持技能注入和跨平台交付的周期性 cron 表达式任务。 ## 核心文件 {#key-files} | 文件 | 用途 | |------|------| | `cron/jobs.py` | 任务模型、存储,对 `jobs.json` 的原子读写操作 | | `cron/scheduler.py` | 调度器循环——检测到期任务、执行任务、跟踪重复任务 | | `tools/cronjob_tools.py` | 面向模型的 `cronjob` 工具注册与处理器 | | `gateway/run.py` | 网关集成——在长期运行的循环中触发 cron 时钟 | | `hermes_cli/cron.py` | CLI 命令 `hermes cron` 的子命令 | ## 调度模型 {#scheduling-model} 支持四种调度格式: | 格式 | 示例 | 行为 | |------|------|------| | **相对延迟** | `30m`, `2h`, `1d` | 单次执行,指定时长后触发 | | **间隔** | `every 2h`, `every 30m` | 周期性执行,按固定间隔触发 | | **Cron 表达式** | `0 9 * * *` | 标准 5 字段 cron 语法(分钟、小时、日、月、星期几) | | **ISO 时间戳** | `2025-01-15T09:00:00` | 单次执行,精确在指定时间触发 | 面向模型的接口是一个单一的 `cronjob` 工具,采用操作风格的命令:`create`、`list`、`update`、`pause`、`resume`、`run`、`remove`。 ## 任务存储 {#job-storage} 任务存储在 `~/.hermes/cron/jobs.json` 中,并采用原子写入语义(先写入临时文件,再重命名)。每个任务记录包含: ```json { "id": "job_abc123", "name": "Daily briefing", "prompt": "Summarize today's AI news and funding rounds", "schedule": "0 9 * * *", "skills": ["ai-funding-daily-report"], "deliver": "telegram:-1001234567890", "repeat": null, "state": "scheduled", "next_run": "2025-01-16T09:00:00Z", "run_count": 42, "created_at": "2025-01-01T00:00:00Z", "model": null, "provider": null, "script": null } ``` ### 任务生命周期状态 {#job-lifecycle-states} | 状态 | 含义 | |------|------| | `scheduled` | 激活状态,将在下次预定时间触发 | | `paused` | 暂停状态——直到恢复前不会触发 | | `completed` | 重复次数耗尽或单次任务已执行完毕 | | `running` | 正在执行中(瞬态状态) | ### 向后兼容性 {#backward-compatibility} 旧版任务可能仅包含一个 `skill` 字段,而非 `skills` 数组。调度器在加载时会进行标准化处理——单个 `skill` 会被提升为 `skills: [skill]`。 ## 调度器运行时 {#scheduler-runtime} ### 时钟周期 {#tick-cycle} 调度器以周期性时钟运行(默认:每 60 秒一次): ```text tick() 1. Acquire scheduler lock (prevents overlapping ticks) 2. Load all jobs from jobs.json 3. Filter to due jobs (next_run <= now AND state == "scheduled") 4. For each due job: a. Set state to "running" b. Create fresh AIAgent session (no conversation history) c. Load attached skills in order (injected as user messages) d. Run the job prompt through the agent e. Deliver the response to the configured target f. Update run_count, compute next_run g. If repeat count exhausted → state = "completed" h. Otherwise → state = "scheduled" 5. Write updated jobs back to jobs.json 6. Release scheduler lock ``` ### 网关集成 {#gateway-integration} 在网关模式下,调度器时钟被集成到网关的主事件循环中。网关在其定期维护周期中调用 `scheduler.tick()`,与消息处理并行运行。 在 CLI 模式下,cron 任务仅在运行 `hermes cron` 命令或处于活跃 CLI 会话期间触发。 ### 新会话隔离 {#fresh-session-isolation} 每个 cron 任务都在一个完全独立的 Agent 会话中运行: - 无前次运行的对话历史 - 无对之前 cron 执行的记忆(除非显式持久化到内存或文件) - 提示必须自包含——cron 任务无法提出澄清性问题 - `cronjob` 工具集被禁用(防止递归) ## 技能驱动的任务 {#skill-backed-jobs} cron 任务可通过 `skills` 字段附加一个或多个技能。在执行时: 1. 技能按指定顺序加载 2. 每个技能的 SKILL.md 内容作为上下文注入 3. 任务的提示作为任务指令追加 4. Agent 处理合并后的技能上下文 + 提示 这使得可重用、可测试的工作流成为可能,而无需将完整指令粘贴到 cron 提示中。例如: ``` Create a daily funding report → attach "ai-funding-daily-report" skill ``` ### 脚本驱动的任务 {#script-backed-jobs} 任务也可通过 `script` 字段附加一个 Python 脚本。该脚本在每次 Agent 执行前运行,其标准输出作为上下文注入到提示中。这支持数据采集和变更检测模式: ```python # ~/.hermes/scripts/check_competitors.py import requests, json # 获取竞争对手的发行说明,与上次运行的差异 # 将摘要打印到标准输出 — agent 分析和报告 ``` 脚本超时默认为 120 秒。`_get_script_timeout()` 通过三层链式机制解析限制: 1. **模块级覆盖** — `_SCRIPT_TIMEOUT`(用于测试/猴子补丁)。仅当其不同于默认值时使用。 2. **环境变量** — `HERMES_CRON_SCRIPT_TIMEOUT` 3. **配置** — `cron.script_timeout_seconds` 在 `config.yaml` 中(通过 `load_config()` 读取) 4. **默认值** — 120 秒 ### 提供商恢复机制 {#provider-recovery} `run_job()` 将用户配置的备用提供方和凭证池传递给 `AIAgent` 实例: - **备用提供方** — 从 `config.yaml` 读取 `fallback_providers`(列表)或 `fallback_model`(旧版字典),匹配网关的 `_load_fallback_model()` 模式。作为 `fallback_model=` 传入 `AIAgent.__init__`,该方法将两种格式统一为备用链。 - **凭证池** — 通过 `load_pool(provider)` 从 `agent.credential_pool` 加载,使用解析后的运行时提供方名称。仅当池中存在凭证(`pool.has_credentials()`)时才传递。支持同一提供方在 429/速率限制错误时的密钥轮换。 这与网关行为保持一致——否则 cron Agent 在遭遇速率限制时将无法尝试恢复。 ## 交付模型 {#delivery-model} cron 任务的结果可交付至任何支持的平台: | 目标 | 语法 | 示例 | |------|------|------| | 原始聊天 | `origin` | 发送到任务创建时的聊天 | | 本地文件 | `local` | 保存到 `~/.hermes/cron/output/` | | Telegram | `telegram` 或 `telegram:` | `telegram:-1001234567890` | | Discord | `discord` 或 `discord:#channel` | `discord:#engineering` | | Slack | `slack` | 发送到 Slack 主频道 | | WhatsApp | `whatsapp` | 发送到 WhatsApp 主聊天 | | Signal | `signal` | 发送到 Signal | | Matrix | `matrix` | 发送到 Matrix 主房间 | | Mattermost | `mattermost` | 发送到 Mattermost 主频道 | | 邮件 | `email` | 通过邮件发送 | | 短信 | `sms` | 通过短信发送 | | Home Assistant | `homeassistant` | 发送到 HA 对话 | | 钉钉 | `dingtalk` | 发送到钉钉 | | 飞书 | `feishu` | 发送到飞书 | | 企业微信 | `wecom` | 发送到企业微信 | | 微信 | `weixin` | 发送到微信(WeChat) | | BlueBubbles | `bluebubbles` | 通过 BlueBubbles 发送到 iMessage | 对于 Telegram 的主题,使用格式 `telegram::`(例如 `telegram:-1001234567890:17585`)。 ### 响应包装 {#response-wrapping} 默认情况下(`cron.wrap_response: true`),cron 交付内容会被包装为: - 一个标题,标识 cron 任务名称和任务本身 - 一个页脚,注明 Agent 无法在对话中看到已发送的消息 在 cron 响应中使用 `[SILENT]` 前缀将完全抑制交付——适用于仅需写入文件或执行副作用的任务。 ### 会话隔离 {#session-isolation} Cron 交付不会被镜像到网关会话的历史记录中。它们仅存在于 cron 任务自身的会话中。这可防止目标聊天对话中出现消息交替违规。 ## 递归保护 {#recursion-guard} Cron 运行的会话禁用了 `cronjob` 工具集。这可防止: - 定时任务创建新的 cron 任务 - 递归调度导致令牌使用量爆炸 - 在任务内部意外修改任务调度 ## 锁定机制 {#locking} 调度器使用基于文件的锁定机制,防止多个重叠的 tick 同时执行同一组待处理任务。这在网关模式下尤为重要,因为如果前一个 tick 执行时间超过 tick 间隔,可能会导致多个维护周期重叠。 ## CLI 界面 {#cli-interface} `hermes cron` CLI 提供了直接的任务管理功能: ```bash hermes cron list # 显示所有职位 hermes cron create # 交互式创造就业机会(别名:添加) hermes cron edit # 编辑作业配置 hermes cron pause # 暂停正在运行的作业 hermes cron resume # 恢复暂停的作业 hermes cron run # 触发立即执行 hermes cron remove # 删除职位 ``` ## 相关文档 {#related-docs} - [Cron 功能指南](/docs/user-guide/features/cron) - [网关内部原理](gateway-internals) - [Agent 循环内部原理](agent-loop) --- ### 扩展 CLI - URL: https://hermesagent.org.cn/docs/developer-guide/extending-the-cli - Path: developer-guide/extending-the-cli.md - Category: developer-guide - Description: 构建扩展 Hermes TUI 的自定义小部件、键盘绑定和布局更改的封装 CLI 工具 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/extending-the-cli.md - Translated At: 2026-04-11T03:23:38.961Z - Headings: 扩展点 | 快速入门:封装 CLI | 钩子参考 | get extra tui widgets() | register extra tui keybindings(kb, , input area) | build tui layout children( widgets) | 布局图示 # 扩展 CLI {#extending-the-cli} Hermes 在 `HermesCLI` 上暴露了受保护的扩展钩子,使得封装 CLI 可以在不覆盖 1000 多行的 `run()` 方法的情况下,添加小部件、快捷键和布局自定义功能。这使得你的扩展与内部实现变化保持解耦。 ## 扩展点 {#extension-points} 共有五个可用的扩展钩子: | 钩子 | 用途 | 何时重写 | |------|------|----------| | `_get_extra_tui_widgets()` | 将小部件注入布局 | 你需要一个持久的 UI 元素(面板、状态栏、迷你播放器) | | `_register_extra_tui_keybindings(kb, *, input_area)` | 添加键盘快捷键 | 你需要热键(切换面板、传输控制、模态快捷键) | | `_build_tui_layout_children(**widgets)` | 完全控制小部件顺序 | 你需要重新排序或包装现有小部件(较少见) | | `process_command()` | 添加自定义斜杠命令 | 你需要处理 `/mycommand`(已有钩子) | | `_build_tui_style_dict()` | 自定义 prompt_toolkit 样式 | 你需要自定义颜色或样式(已有钩子) | 前三个是新的受保护钩子,后两个已存在。 ## 快速入门:封装 CLI {#quick-start-a-wrapper-cli} ```python #!/usr/bin/env python3 """my_cli.py — Example wrapper CLI that extends Hermes.""" from cli import HermesCLI from prompt_toolkit.layout import FormattedTextControl, Window from prompt_toolkit.filters import Condition class MyCLI(HermesCLI): def __init__(self, **kwargs): super().__init__(**kwargs) self._panel_visible = False def _get_extra_tui_widgets(self): """Add a toggleable info panel above the status bar.""" cli_ref = self return [ Window( FormattedTextControl(lambda: "📊 My custom panel content"), height=1, filter=Condition(lambda: cli_ref._panel_visible), ), ] def _register_extra_tui_keybindings(self, kb, *, input_area): """F2 toggles the custom panel.""" cli_ref = self @kb.add("f2") def _toggle_panel(event): cli_ref._panel_visible = not cli_ref._panel_visible def process_command(self, cmd: str) -> bool: """Add a /panel slash command.""" if cmd.strip().lower() == "/panel": self._panel_visible = not self._panel_visible state = "visible" if self._panel_visible else "hidden" print(f"Panel is now {state}") return True return super().process_command(cmd) if __name__ == "__main__": cli = MyCLI() cli.run() ``` 运行它: ```bash cd ~/.hermes/hermes-agent source .venv/bin/activate python my_cli.py ``` ## 钩子参考 {#hook-reference} ### `_get_extra_tui_widgets()` {#_get_extra_tui_widgets} 返回一个要插入 TUI 布局的小部件列表。这些小部件将出现在 **分隔符和状态栏之间** —— 位于输入区域之上,主输出区域之下。 ```python def _get_extra_tui_widgets(self) -> list: return [] # 默认:没有额外的小部件 ``` 每个小部件都应是一个 prompt_toolkit 容器(例如 `Window`、`ConditionalContainer`、`HSplit`)。使用 `ConditionalContainer` 或 `filter=Condition(...)` 可使小部件可切换。 ```python from prompt_toolkit.layout import ConditionalContainer, Window, FormattedTextControl from prompt_toolkit.filters import Condition def _get_extra_tui_widgets(self): return [ ConditionalContainer( Window(FormattedTextControl("Status: connected"), height=1), filter=Condition(lambda: self._show_status), ), ] ``` ### `_register_extra_tui_keybindings(kb, *, input_area)` {#_register_extra_tui_keybindingskb--input_area} 在 Hermes 注册其自身快捷键之后、布局构建之前被调用。将你的快捷键添加到 `kb` 中。 ```python def _register_extra_tui_keybindings(self, kb, *, input_area): pass # 默认值:没有额外的键绑定 ``` 参数: - **`kb`** — prompt_toolkit 应用程序的 `KeyBindings` 实例 - **`input_area`** — 主 `TextArea` 小部件,如果你需要读取或操作用户输入 ```python def _register_extra_tui_keybindings(self, kb, *, input_area): cli_ref = self @kb.add("f3") def _clear_input(event): input_area.text = "" @kb.add("f4") def _insert_template(event): input_area.text = "/search " ``` **避免与内置快捷键冲突**:`Enter`(提交)、`Escape Enter`(换行)、`Ctrl-C`(中断)、`Ctrl-D`(退出)、`Tab`(自动补全接受)。F2 及以上功能键和 Ctrl 组合键通常安全。 ### `_build_tui_layout_children(**widgets)` {#_build_tui_layout_childrenwidgets} 仅当你需要完全控制小部件顺序时才重写此方法。大多数扩展应使用 `_get_extra_tui_widgets()`。 ```python def _build_tui_layout_children(self, *, sudo_widget, secret_widget, approval_widget, clarify_widget, spinner_widget, spacer, status_bar, input_rule_top, image_bar, input_area, input_rule_bot, voice_status_bar, completions_menu) -> list: ``` 默认实现返回: ```python [ Window(height=0), # 锚 sudo_widget, # sudo 密码 prompt (有条件) secret_widget, # 秘密输入prompt(有条件) approval_widget, # 危险指挥批准(有条件) clarify_widget, # 澄清问题 UI(有条件) spinner_widget, # 思维旋转器(有条件) spacer, # 填充剩余的垂直空间 *self._get_extra_tui_widgets(), # YOUR WIDGETS 去 HERE status_bar, # 型号/token/context 状态线 input_rule_top, # ── 输入上方的边框 image_bar, # 附加图像指示器 input_area, # 用户文本输入 input_rule_bot, # ── 输入框下方的边框 voice_status_bar, # 语音模式状态(有条件) completions_menu, # 自动完成下拉菜单 ] ``` ## 布局图示 {#layout-diagram} 从上到下的默认布局: 1. **输出区域** —— 可滚动的对话历史 2. **分隔符** 3. **额外小部件** —— 来自 `_get_extra_tui_widgets()` 4. **状态栏** —— 模型、上下文百分比、已用时间 5. **图像栏** —— 附加图像数量 6. **输入区域** —— 用户提示 7. **语音状态** —— 录音指示器 8. **补全菜单** —— 自动补全建议 --- ### 网关内部结构 - URL: https://hermesagent.org.cn/docs/developer-guide/gateway-internals - Path: developer-guide/gateway-internals.md - Category: developer-guide - Description: 消息网关的启动、用户授权、会话路由及消息传递过程 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/gateway-internals.md - Translated At: 2026-04-11T03:24:09.319Z - Headings: 核心文件 | 架构概览 | 消息流转流程 | 会话密钥格式 | 两级消息保护机制 | 授权机制 | 私信配对流程 | 斜杠命令分发 | 运行中 Agent 保护机制 | 配置来源 | 平台适配器 | Token 锁机制 # 网关内部机制 {#gateway-internals} 消息网关是一个长期运行的进程,通过统一的架构连接 Hermes 与 14+ 个外部消息平台。 ## 核心文件 {#key-files} | 文件 | 用途 | |------|------| | `gateway/run.py` | `GatewayRunner` — 主循环、斜杠命令处理、消息分发(约 7,500 行) | | `gateway/session.py` | `SessionStore` — 会话持久化与会话密钥构造 | | `gateway/delivery.py` | 向目标平台/渠道发送出站消息 | | `gateway/pairing.py` | 用户授权的私信配对流程 | | `gateway/channel_directory.py` | 将聊天 ID 映射为可读名称,用于定时发送 | | `gateway/hooks.py` | 钩子发现、加载与生命周期事件分发 | | `gateway/mirror.py` | `send_message` 的跨会话消息镜像 | | `gateway/status.py` | 针对配置文件作用域的网关实例的令牌锁管理 | | `gateway/builtin_hooks/` | 始终注册的钩子(例如 BOOT.md 系统提示钩子) | | `gateway/platforms/` | 平台适配器(每个消息平台一个) | ## 架构概览 {#architecture-overview} ```text ┌─────────────────────────────────────────────────┐ │ GatewayRunner │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Telegram │ │ Discord │ │ Slack │ ... │ │ │ Adapter │ │ Adapter │ │ Adapter │ │ │ └─────┬─────┘ └─────┬────┘ └─────┬────┘ │ │ │ │ │ │ │ └──────────────┼──────────────┘ │ │ ▼ │ │ _handle_message() │ │ │ │ │ ┌────────────┼────────────┐ │ │ ▼ ▼ ▼ │ │ Slash command AIAgent Queue/BG │ │ dispatch creation sessions │ │ │ │ │ ▼ │ │ SessionStore │ │ (SQLite persistence) │ └─────────────────────────────────────────────────┘ ``` ## 消息流转流程 {#message-flow} 当来自任意平台的消息到达时: 1. **平台适配器** 接收原始事件,将其标准化为 `MessageEvent` 2. **基础适配器** 检查活跃会话保护: - 如果该会话的 Agent 正在运行 → 将消息入队,并设置中断事件 - 如果是 `/approve`、`/deny`、`/stop` → 跳过保护(直接分发) 3. **GatewayRunner._handle_message()** 接收事件: - 通过 `_session_key_for_source()` 解析会话密钥(格式:`agent:main:{platform}:{chat_type}:{chat_id}`) - 检查授权(参见授权部分) - 检查是否为斜杠命令 → 转发至命令处理器 - 检查 Agent 是否已运行 → 拦截如 `/stop`、`/status` 等命令 - 否则 → 创建 `AIAgent` 实例并启动对话 4. **响应** 通过平台适配器返回 ### 会话密钥格式 {#session-key-format} 会话密钥编码了完整的路由上下文: ``` agent:main:{platform}:{chat_type}:{chat_id} ``` 例如:`agent:main:telegram:private:123456789` 支持线程感知的平台(如 Telegram 论坛主题、Discord 线程、Slack 线程)可能在 `chat_id` 部分包含线程 ID。**切勿手动构造会话密钥** —— 始终使用 `gateway/session.py` 中的 `build_session_key()`。 ### 两级消息保护机制 {#two-level-message-guard} 当 Agent 正在运行时,传入的消息会经过两级顺序保护: 1. **一级 —— 基础适配器**(`gateway/platforms/base.py`):检查 `_active_sessions`。如果会话处于活跃状态,则将消息入队至 `_pending_messages` 并设置中断事件。这会在消息到达网关运行器之前就捕获它们。 2. **二级 —— 网关运行器**(`gateway/run.py`):检查 `_running_agents`。拦截特定命令(`/stop`、`/new`、`/queue`、`/status`、`/approve`、`/deny`),并按需路由。其余所有消息将触发 `running_agent.interrupt()`。 必须在 Agent 被阻塞时仍能到达运行器的命令(如 `/approve`)通过 `await self._message_handler(event)` **内联分发** —— 它们绕过后台任务系统,以避免竞态条件。 ## 授权机制 {#authorization} 网关使用多层授权检查,按顺序评估: 1. **平台级全允许标志**(如 `TELEGRAM_ALLOW_ALL_USERS`)—— 若启用,则该平台所有用户均被授权 2. **平台允许列表**(如 `TELEGRAM_ALLOWED_USERS`)—— 逗号分隔的用户 ID 列表 3. **私信配对** —— 经认证的用户可通过配对码为新用户配对 4. **全局全允许**(`GATEWAY_ALLOW_ALL_USERS`)—— 若启用,则所有平台的所有用户均被授权 5. **默认:拒绝** —— 未授权用户将被拒绝 ### 私信配对流程 {#dm-pairing-flow} ```text Admin: /pair Gateway: "Pairing code: ABC123. Share with the user." New user: ABC123 Gateway: "Paired! You're now authorized." ``` 配对状态由 `gateway/pairing.py` 持久化,重启后仍有效。 ## 斜杠命令分发 {#slash-command-dispatch} 网关流程中的所有斜杠命令均通过相同的解析管道: 1. `hermes_cli/commands.py` 中的 `resolve_command()` 将输入映射为规范名称(处理别名、前缀匹配) 2. 将规范名称与 `GATEWAY_KNOWN_COMMANDS` 进行比对 3. `_handle_message()` 中的处理器根据规范名称进行分发 4. 部分命令受配置限制(`CommandDef` 上的 `gateway_config_gate`) ### 运行中 Agent 保护机制 {#running-agent-guard} 必须在 Agent 处理期间**不执行**的命令会提前被拒绝: ```python if _quick_key in self._running_agents: if canonical == "model": return "⏳ Agent is running — wait for it to finish or /stop first." ``` 绕过命令(`/stop`、`/new`、`/approve`、`/deny`、`/queue`、`/status`)具有特殊处理逻辑。 ## 配置来源 {#config-sources} 网关从多个来源读取配置: | 来源 | 提供内容 | |------|--------| | `~/.hermes/.env` | API 密钥、机器人令牌、平台凭证 | | `~/.hermes/config.yaml` | 模型设置、工具配置、显示选项 | | 环境变量 | 覆盖上述任意配置 | 与 CLI(使用 `load_cli_config()` 并带有硬编码默认值)不同,网关通过 YAML 加载器直接读取 `config.yaml`。这意味着在 CLI 默认字典中存在但用户配置文件中不存在的配置键,在 CLI 与网关中的行为可能不同。 ## 平台适配器 {#platform-adapters} 每个消息平台在 `gateway/platforms/` 中都有一个适配器: ```text gateway/platforms/ ├── base.py # BaseAdapter — 所有平台的共享逻辑 ├── telegram.py # Telegram 机器人 API(长轮询或 webhook) ├── discord.py # 通过 discord.py 提供 Discord ├── slack.py # Slack Socket Mode ├── whatsapp.py # WhatsApp 商业云 API ├── signal.py # Signal 通过 signal-cli REST API ├── matrix.py # Matrix 通过 matrix-nio(可选 E2EE) ├── mattermost.py # Mattermost WebSocket API ├── email.py # 通过 IMAP/SMTP 发送电子邮件 ├── sms.py # SMS 通过 Twilio ├── dingtalk.py # 钉钉WebSocket ├── feishu.py # 飞书/Lark WebSocket 或 webhook ├── wecom.py # WeCom(工作微信)回调 ├── weixin.py # Weixin(个人微信)通过iLink Bot API ├── bluebubbles.py # 通过 BlueBubbles macOS 服务器的 Apple iMessage ├── webhook.py # 入站/outbound webhook 适配器 ├── api_server.py # REST API 服务器适配器 └── homeassistant.py # 家庭助理对话集成 ``` 适配器实现一个通用接口: - `connect()` / `disconnect()` — 生命周期管理 - `send_message()` — 出站消息发送 - `on_message()` — 入站消息标准化 → `MessageEvent` ### Token 锁机制 {#token-locks} 使用唯一凭据连接的适配器会在 `connect()` 中调用 `acquire_scoped_lock()`,并在 `disconnect()` 中调用 `release_scoped_lock()`。这可防止两个配置文件同时使用同一个机器人令牌。 ## 消息投递路径 {#delivery-path} 出站投递(`gateway/delivery.py`)处理以下情况: - **直接回复** — 将响应发送回原始聊天 - **主频道投递** — 将定时任务输出和后台结果路由到配置的主频道 - **显式目标投递** — 使用 `send_message` 工具指定 `telegram:-1001234567890` - **跨平台投递** — 将消息投递到与原始消息不同的平台 定时任务的投递**不会**被镜像到网关会话历史中 — 它们仅存在于独立的定时任务会话中。这是有意的设计选择,以避免消息交替违规。 ## 钩子(Hooks) {#hooks} 网关钩子是响应生命周期事件的 Python 模块。 ### 网关钩子事件 {#gateway-hook-events} | 事件 | 触发时机 | |------|--------| | `gateway:startup` | 网关进程启动时 | | `session:start` | 新的对话会话开始时 | | `session:end` | 会话完成或超时 | | `session:reset` | 用户通过 `/new` 重置会话 | | `agent:start` | Agent 开始处理消息 | | `agent:step` | Agent 完成一次工具调用迭代 | | `agent:end` | Agent 完成并返回响应 | | `command:*` | 任意斜杠命令被执行 | 钩子从 `gateway/builtin_hooks/`(始终启用)和 `~/.hermes/hooks/`(用户安装)中发现。每个钩子是一个包含 `HOOK.yaml` 清单和 `handler.py` 的目录。 ## 记忆提供者集成 {#memory-provider-integration} 当启用记忆提供者插件(例如 Honcho)时: 1. 网关为每条消息创建一个带会话 ID 的 `AIAgent` 2. `MemoryManager` 使用会话上下文初始化提供者 3. 提供者工具(例如 `honcho_profile`、`viking_search`)通过以下方式路由: ```text AIAgent._invoke_tool() → self._memory_manager.handle_tool_call(name, args) → provider.handle_tool_call(name, args) ``` 4. 会话结束/重置时,触发 `on_session_end()` 以进行清理和最终数据刷新 ### 记忆刷新生命周期 {#memory-flush-lifecycle} 当会话被重置、恢复或过期时: 1. 内置记忆被刷新到磁盘 2. 记忆提供者的 `on_session_end()` 钩子被触发 3. 临时 `AIAgent` 执行一次仅记忆的对话轮次 4. 然后上下文被丢弃或归档 ## 后台维护 {#background-maintenance} 网关在处理消息的同时运行周期性维护任务: - **定时任务触发** — 检查任务调度并触发到期任务 - **会话超时清理** — 在超时后清理废弃会话 - **记忆主动刷新** — 在会话过期前主动刷新记忆 - **缓存刷新** — 刷新模型列表和提供者状态 ## 进程管理 {#process-management} 网关以长期运行的进程形式运行,通过以下方式管理: - `hermes gateway start` / `hermes gateway stop` — 手动控制 - `systemctl`(Linux)或 `launchctl`(macOS) — 服务管理 - PID 文件位于 `~/.hermes/gateway.pid` — 配置文件范围的进程跟踪 **配置文件范围 vs 全局**:`start_gateway()` 使用配置文件范围的 PID 文件。`hermes gateway stop` 仅停止当前配置文件的网关。`hermes gateway stop --all` 使用全局 `ps aux` 扫描来终止所有网关进程(用于更新时)。 ## 相关文档 {#related-docs} - [会话存储](session-storage) - [定时任务内部机制](cron-internals) - [ACP 内部机制](acp-internals) - [Agent 循环内部机制](agent-loop) - [消息网关(用户指南)](/docs/user-guide/messaging) --- ### 图像生成提供商插件 - URL: https://hermesagent.org.cn/docs/developer-guide/image-gen-provider-plugin - Path: developer-guide/image-gen-provider-plugin.md - Category: developer-guide - Description: 如何为 Hermes Agent 构建图像生成后端插件 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/image-gen-provider-plugin.md - Translated At: 2026-06-16T00:42:52.437Z - Headings: 发现机制工作原理 | 目录结构 | ImageGenProvider 抽象基类 (ABC) | plugin.yaml | ABC 参考 | 响应格式 | 处理 base64 与 URL 输出 | 用户覆盖 | 测试 | 参考实现 | 通过 pip 分发 | 相关页面 # 构建图像生成提供者插件 {#building-an-image-generation-provider-plugin} 图像生成(image-gen)提供者插件注册一个后端,用于服务每一次 `image_generate` 工具调用——无论是 DALL·E、gpt-image、Grok、Flux、Imagen、Stable Diffusion、fal、Replicate、本地 ComfyUI 环境,还是其他任何后端。内置提供者(OpenAI、OpenAI-Codex、xAI)均作为插件提供。你可以通过在 `plugins/image_gen//` 中放置一个目录来添加新的提供者,或覆盖已有的捆绑提供者。 :::tip 图像生成是 Hermes 支持的几种**后端插件**之一。其他插件(具有更专用的抽象基类 ABC)包括 [记忆提供者插件](/docs/developer-guide/memory-provider-plugin)、[上下文引擎插件](/docs/developer-guide/context-engine-plugin) 和 [模型提供者插件](/docs/developer-guide/model-provider-plugin)。通用的工具/钩子/CLI 插件请参阅 [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin)。 ::: ## 发现机制工作原理 {#how-discovery-works} Hermes 会在以下三个位置扫描图像生成后端: 1. **捆绑(Bundled)** — `/plugins/image_gen//`(随 `kind: backend` 自动加载,始终可用) 2. **用户(User)** — `~/.hermes/plugins/image_gen//`(通过 `plugins.enabled` 选择启用) 3. **Pip** — 声明了 `hermes_agent.plugins` 入口点的包 每个插件的 `register(ctx)` 函数都会调用 `ctx.register_image_gen_provider(...)`——这将其放入 `agent/image_gen_registry.py` 中的注册表。活跃提供者由 `config.yaml` 中的 `image_gen.provider` 选定;`hermes tools` 会引导用户进行选择。 `image_generate` 工具包装器向注册表请求活跃提供者并分派到该提供者。如果没有注册任何提供者,该工具会显示一条有用的错误信息,指向 `hermes tools`。 ## 目录结构 {#directory-structure} ``` plugins/image_gen/my-backend/ ├── __init__.py # ImageGenProvider subclass + register() └── plugin.yaml # Manifest with kind: backend ``` 此时,捆绑插件已完整。位于 `~/.hermes/plugins/image_gen//` 的用户插件需要添加到 `config.yaml` 中的 `plugins.enabled` 列表中(或者运行 `hermes plugins enable `)。 ## ImageGenProvider 抽象基类 (ABC) {#the-imagegenprovider-abc} 继承 `agent.image_gen_provider.ImageGenProvider`。唯一必需的成员是 `name` 属性和 `generate()` 方法——其他所有成员都有合理的默认值: ```python # plugins/image_gen/my-backend/__init__.py from typing import Any, Dict, List, Optional import os from agent.image_gen_provider import ( DEFAULT_ASPECT_RATIO, ImageGenProvider, error_response, resolve_aspect_ratio, save_b64_image, success_response, ) class MyBackendImageGenProvider(ImageGenProvider): @property def name(self) -> str: # Stable id used in image_gen.provider config. Lowercase, no spaces. return "my-backend" @property def display_name(self) -> str: # Human label shown in `hermes tools`. Defaults to name.title() if omitted. return "My Backend" def is_available(self) -> bool: # Return False if credentials or deps are missing. # The tool's availability gate calls this before dispatch. if not os.environ.get("MY_BACKEND_API_KEY"): return False try: import my_backend_sdk # noqa: F401 except ImportError: return False return True def list_models(self) -> List[Dict[str, Any]]: # Catalog shown in `hermes tools` model picker. return [ { "id": "my-model-fast", "display": "My Model (Fast)", "speed": "~5s", "strengths": "Quick iteration", "price": "$0.01/image", }, { "id": "my-model-hq", "display": "My Model (HQ)", "speed": "~30s", "strengths": "Highest fidelity", "price": "$0.04/image", }, ] def default_model(self) -> Optional[str]: return "my-model-fast" def get_setup_schema(self) -> Dict[str, Any]: # Metadata for the `hermes tools` picker — keys to prompt for at setup. return { "name": "My Backend", "badge": "paid", # optional; shown as a short tag in the picker "tag": "One-line description shown under the name", "env_vars": [ { "key": "MY_BACKEND_API_KEY", "prompt": "My Backend API key", "url": "https://my-backend.example.com/api-keys", }, ], } def generate( self, prompt: str, aspect_ratio: str = DEFAULT_ASPECT_RATIO, **kwargs: Any, ) -> Dict[str, Any]: prompt = (prompt or "").strip() aspect_ratio = resolve_aspect_ratio(aspect_ratio) if not prompt: return error_response( error="Prompt is required", error_type="invalid_input", provider=self.name, prompt="", aspect_ratio=aspect_ratio, ) # Model selection precedence: env var → config → default. The helper # _resolve_model() in the built-in openai plugin is a good reference. model_id = kwargs.get("model") or self.default_model() or "my-model-fast" try: import my_backend_sdk client = my_backend_sdk.Client(api_key=os.environ["MY_BACKEND_API_KEY"]) result = client.generate( prompt=prompt, model=model_id, aspect_ratio=aspect_ratio, ) # Two shapes supported: # - URL string: return it as `image` # - base64 data: save under $HERMES_HOME/cache/images/ via save_b64_image() if result.get("image_b64"): path = save_b64_image( result["image_b64"], prefix=self.name, extension="png", ) image = str(path) else: image = result["image_url"] return success_response( image=image, model=model_id, prompt=prompt, aspect_ratio=aspect_ratio, provider=self.name, ) except Exception as exc: return error_response( error=str(exc), error_type=type(exc).__name__, provider=self.name, model=model_id, prompt=prompt, aspect_ratio=aspect_ratio, ) def register(ctx) -> None: """Plugin entry point — called once at load time.""" ctx.register_image_gen_provider(MyBackendImageGenProvider()) ``` ## plugin.yaml {#pluginyaml} ```yaml name: my-backend version: 1.0.0 description: My image backend — text-to-image via My Backend SDK author: Your Name kind: backend requires_env: - MY_BACKEND_API_KEY ``` `kind: backend` 是将插件路由到图像生成注册路径的关键。`requires_env` 会在执行 `hermes plugins install` 时提示用户配置。 ## ABC 参考 {#abc-reference} 完整契约位于 `agent/image_gen_provider.py`。你通常会被重写的方法如下: | 成员 | 必需 | 默认值 | 用途 | |---|---|---|---| | `name` | ✅ | — | 在 `image_gen.provider` 配置中使用的稳定 ID | | `display_name` | — | `name.title()` | 在 `hermes tools` 中显示的标签 | | `is_available()` | — | `True` | 用于检查缺失凭据/依赖项的门控 | | `list_models()` | — | `[]` | 供 `hermes tools` 模型选择器使用的目录 | | `default_model()` | — | `list_models()` 中的第一个 | 未配置模型时的回退选项 | | `get_setup_schema()` | — | 最小化 | 选择器元数据 + 环境变量提示 | | `generate(prompt, aspect_ratio, **kwargs)` | ✅ | — | 实际调用 | ## 响应格式 {#response-format} `generate()` 必须返回通过 `success_response()` 或 `error_response()` 构建的字典。两者均位于 `agent/image_gen_provider.py` 中。 **成功:** ```python success_response( image=, model=, prompt=, aspect_ratio="landscape" | "square" | "portrait", provider=, extra={...}, # optional backend-specific fields ) ``` **错误:** ```python error_response( error="human-readable message", error_type="provider_error" | "invalid_input" | "", provider=, model=, prompt=, aspect_ratio=, ) ``` 工具包装器将该字典序列化为 JSON 并交给 LLM。错误会作为工具结果呈现;LLM 决定如何向用户解释这些错误。 ## 处理 base64 与 URL 输出 {#handling-base64-vs-url-output} 某些后端返回图像 URL(如 fal、Replicate);其他后端返回 base64 负载(如 OpenAI gpt-image-2)。对于 base64 情况,请使用 `save_b64_image()`——它将文件写入 `$HERMES_HOME/cache/images/__.` 并返回绝对 `Path`。在 `success_response()` 中将该路径(作为 `str`)作为 `image=` 参数传递。网关交付(Telegram 照片气泡、Discord 附件)既能识别 URL 也能识别绝对路径。 ## 用户覆盖 {#user-overrides} 在 `~/.hermes/plugins/image_gen//` 中放置一个用户插件,其 `name` 属性与某个捆绑插件相同,并通过 `hermes plugins enable ` 启用它——注册表采用“最后写入者胜出”原则,因此你的版本将替换内置版本。这对于将 `openai` 插件指向私有代理,或换入自定义模型目录非常有用。 ## 测试 {#testing} ```bash export HERMES_HOME=/tmp/hermes-imggen-test mkdir -p $HERMES_HOME/plugins/image_gen/my-backend # …copy __init__.py + plugin.yaml into that dir… export MY_BACKEND_API_KEY=your-test-key hermes plugins enable my-backend # Pick it as the active provider echo "image_gen:" >> $HERMES_HOME/config.yaml echo " provider: my-backend" >> $HERMES_HOME/config.yaml # Exercise it hermes -z "Generate an image of a corgi in a spacesuit" ``` 或者交互式测试:`hermes tools` → “Image Generation” → 选择 `my-backend` → 如果提示则输入 API 密钥。 ## 参考实现 {#reference-implementations} - **`plugins/image_gen/openai/__init__.py`** — 将 gpt-image-2 分为低/中/高三个层级,作为共享同一 API 模型但具有不同 `quality` 参数的三个虚拟模型 ID。这是在单一后端下分层模型以及 config.yaml 优先级链的良好示例。 - **`plugins/image_gen/xai/__init__.py`** — 通过 xAI 使用 Grok Imagine。形态不同(URL 输出,更简单的目录)。 - **`plugins/image_gen/openai-codex/__init__.py`** — Codex 风格的 Responses API 变体,复用 OpenAI SDK 但使用不同的路由基础 URL。 ## 通过 pip 分发 {#distribute-via-pip} ```toml # pyproject.toml [project.entry-points."hermes_agent.plugins"] my-backend-imggen = "my_backend_imggen_package" ``` `my_backend_imggen_package` 必须暴露一个顶层的 `register` 函数。完整设置请参阅通用插件指南中的 [通过 pip 分发](/docs/guides/build-a-hermes-plugin#distribute-via-pip)。 ## 相关页面 {#related-pages} - [图像生成](/docs/user-guide/features/image-generation) — 面向用户的功能文档 - [插件概览](/docs/user-guide/features/plugins) — 一览所有插件类型 - [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin) — 通用工具/钩子/斜杠命令指南 --- ### 记忆提供者插件 - URL: https://hermesagent.org.cn/docs/developer-guide/memory-provider-plugin - Path: developer-guide/memory-provider-plugin.md - Category: developer-guide - Description: 如何为 Hermes Agent 构建一个记忆提供者插件 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/memory-provider-plugin.md - Translated At: 2026-04-11T03:24:03.564Z - Headings: 目录结构 | MemoryProvider 抽象基类 | 必需方法 | 核心生命周期 | 配置 | 可选钩子 | 配置 Schema | 保存配置 | 插件入口点 | plugin.yaml | 线程约定 | 配置文件隔离 # 构建记忆提供者插件 {#building-a-memory-provider-plugin} 记忆提供者插件为 Hermes Agent 提供持久化、跨会话的知识,超越内置的 MEMORY.md 和 USER.md。本指南将介绍如何构建一个记忆提供者插件。 :::tip 记忆提供者是两种 **提供者插件** 类型之一。另一种是 [上下文引擎插件](/docs/developer-guide/context-engine-plugin),用于替换内置的上下文压缩器。两者遵循相同的模式:单选、配置驱动,并通过 `hermes plugins` 进行管理。 ::: ## 目录结构 {#directory-structure} 每个记忆提供者都位于 `plugins/memory//` 目录下: ``` plugins/memory/my-provider/ ├── __init__.py # MemoryProvider 实现 + register() 入口点 ├── plugin.yaml # 元数据(名称、描述、挂钩) └── README.md # 设置说明、配置参考、tools ``` ## MemoryProvider 抽象基类 {#the-memoryprovider-abc} 你的插件需实现 `agent/memory_provider.py` 中的 `MemoryProvider` 抽象基类: ```python from agent.memory_provider import MemoryProvider class MyMemoryProvider(MemoryProvider): @property def name(self) -> str: return "my-provider" def is_available(self) -> bool: """Check if this provider can activate. NO network calls.""" return bool(os.environ.get("MY_API_KEY")) def initialize(self, session_id: str, **kwargs) -> None: """Called once at agent startup. kwargs always includes: hermes_home (str): Active HERMES_HOME path. Use for storage. """ self._api_key = os.environ.get("MY_API_KEY", "") self._session_id = session_id # ...实现剩余的方法 ``` ## 必需方法 {#required-methods} ### 核心生命周期 {#core-lifecycle} | 方法 | 调用时机 | 是否必须实现? | |--------|-----------|-----------------| | `name` (属性) | 始终调用 | **是** | | `is_available()` | Agent 初始化,激活前 | **是** —— 不得进行网络调用 | | `initialize(session_id, **kwargs)` | Agent 启动时 | **是** | | `get_tool_schemas()` | 初始化后,用于工具注入 | **是** | | `handle_tool_call(name, args)` | Agent 使用你的工具时 | **是**(如果你有工具) | ### 配置 {#config} | 方法 | 用途 | 是否必须实现? | |--------|---------|-----------------| | `get_config_schema()` | 声明 `hermes memory setup` 使用的配置字段 | **是** | | `save_config(values, hermes_home)` | 将非敏感配置写入原生位置 | **是**(除非仅使用环境变量) | ### 可选钩子 {#optional-hooks} | 方法 | 调用时机 | 使用场景 | |--------|-----------|----------| | `system_prompt_block()` | 系统提示词组装时 | 提供静态提供者信息 | | `prefetch(query)` | 每次 API 调用前 | 返回召回的上下文 | | `queue_prefetch(query)` | 每轮对话后 | 为下一轮预热 | | `sync_turn(user, assistant)` | 每轮对话完成后 | 持久化对话内容 | | `on_session_end(messages)` | 会话结束时 | 最终提取/刷新 | | `on_pre_compress(messages)` | 上下文压缩前 | 在丢弃前保存洞察 | | `on_memory_write(action, target, content)` | 内置记忆写入时 | 将变更同步到你的后端 | | `shutdown()` | 进程退出时 | 清理连接 | ## 配置 Schema {#config-schema} `get_config_schema()` 返回一个字段描述列表,由 `hermes memory setup` 使用: ```python def get_config_schema(self): return [ { "key": "api_key", "description": "My Provider API key", "secret": True, # → 写入`.env` "required": True, "env_var": "MY_API_KEY", # 显式环境变量名称 "url": "https://my-provider.com/keys", # 在哪里得到它 }, { "key": "region", "description": "Server region", "default": "us-east", "choices": ["us-east", "eu-west", "ap-south"], }, { "key": "project", "description": "Project identifier", "default": "hermes", }, ] ``` `secret: True` 且带有 `env_var` 的字段将写入 `.env` 文件。非敏感字段将传递给 `save_config()`。 :::tip 最小化与完整 Schema `get_config_schema()` 中的每个字段都会在 `hermes memory setup` 时被提示。具有大量选项的提供者应保持 Schema 尽可能简洁——仅包含用户**必须**配置的字段(如 API 密钥、必需凭证)。可选设置应记录在配置文件参考中(例如 `$HERMES_HOME/myprovider.json`),而不是在设置向导中全部提示。这能保持设置向导快速响应,同时仍支持高级配置。参见 Supermemory 提供者示例——它仅提示 API 密钥;所有其他选项均位于 `supermemory.json` 中。 ::: ## 保存配置 {#save-config} ```python def save_config(self, values: dict, hermes_home: str) -> None: """Write non-secret config to your native location.""" import json from pathlib import Path config_path = Path(hermes_home) / "my-provider.json" config_path.write_text(json.dumps(values, indent=2)) ``` 对于仅使用环境变量的提供者,可保留默认的空操作(no-op)。 ## 插件入口点 {#plugin-entry-point} ```python def register(ctx) -> None: """Called by the memory plugin discovery system.""" ctx.register_memory_provider(MyMemoryProvider()) ``` ## plugin.yaml {#pluginyaml} ```yaml name: my-provider version: 1.0.0 description: "Short description of what this provider does." hooks: - on_session_end # 列出您实现的钩子 ``` ## 线程约定 {#threading-contract} **`sync_turn()` 必须是非阻塞的。** 如果你的后端存在延迟(如 API 调用、LLM 处理),请在守护线程中运行该工作: ```python def sync_turn(self, user_content, assistant_content): def _sync(): try: self._api.ingest(user_content, assistant_content) except Exception as e: logger.warning("Sync failed: %s", e) if self._sync_thread and self._sync_thread.is_alive(): self._sync_thread.join(timeout=5.0) self._sync_thread = threading.Thread(target=_sync, daemon=True) self._sync_thread.start() ``` ## 配置文件隔离 {#profile-isolation} 所有存储路径**必须**使用 `initialize()` 中的 `hermes_home` 参数,不得硬编码 `~/.hermes`: ```python # CORRECT — profile 范围 from hermes_constants import get_hermes_home data_dir = get_hermes_home() / "my-provider" # WRONG — 在所有 profiles 之间共享 data_dir = Path("~/.hermes/my-provider").expanduser() ``` ## 测试 {#testing} 参见 `tests/agent/test_memory_plugin_e2e.py`,其中包含使用真实 SQLite 提供者的完整端到端测试模式。 ```python from agent.memory_manager import MemoryManager mgr = MemoryManager() mgr.add_provider(my_provider) mgr.initialize_all(session_id="test-1", platform="cli") # 测试tool路由 result = mgr.handle_tool_call("my_tool", {"action": "add", "content": "test"}) # 测试生命周期 mgr.sync_all("user msg", "assistant msg") mgr.on_session_end([]) mgr.shutdown_all() ``` ## 添加 CLI 命令 {#adding-cli-commands} 记忆提供者插件可以注册自己的 CLI 子命令树(例如 `hermes my-provider status`、`hermes my-provider config`)。该功能使用基于约定的发现机制——无需修改核心文件。 ### 工作原理 {#how-it-works} 1. 在插件目录中添加一个 `cli.py` 文件 2. 定义一个 `register_cli(subparser)` 函数,用于构建 argparse 树 3. 记忆提供者系统通过 `discover_plugin_cli_commands()` 在启动时发现它 4. 你的命令将出现在 `hermes ` 下 **激活提供者控制:** 只有当你的提供者是配置中的活动 `memory.provider` 时,你的 CLI 命令才会显示。如果用户未配置你的提供者,你的命令将不会出现在 `hermes --help` 中。 ### 示例 {#example} ```python # 插件/memory/my-provider/cli.py def my_command(args): """Handler dispatched by argparse.""" sub = getattr(args, "my_command", None) if sub == "status": print("Provider is active and connected.") elif sub == "config": print("Showing config...") else: print("Usage: hermes my-provider ") def register_cli(subparser) -> None: """Build the hermes my-provider argparse tree. Called by discover_plugin_cli_commands() at argparse setup time. """ subs = subparser.add_subparsers(dest="my_command") subs.add_parser("status", help="Show provider status") subs.add_parser("config", help="Show provider config") subparser.set_defaults(func=my_command) ``` ### 参考实现 {#reference-implementation} 参见 `plugins/memory/honcho/cli.py`,其中包含一个完整示例,包含 13 个子命令、跨配置文件管理(`--target-profile`)以及配置读写功能。 ### 带 CLI 的目录结构 {#directory-structure-with-cli} ``` plugins/memory/my-provider/ ├── __init__.py # MemoryProvider 实现 + register() ├── plugin.yaml # 元数据 ├── cli.py # register_cli(子解析器) — CLI 命令 └── README.md # 设置说明 ``` ## 单提供者规则 {#single-provider-rule} 同一时间只能激活**一个**外部记忆提供者。如果用户尝试注册第二个,MemoryManager 会以警告拒绝。这可防止工具 Schema 膨胀和后端冲突。 --- ### 模型提供商插件 - URL: https://hermesagent.org.cn/docs/developer-guide/model-provider-plugin - Path: developer-guide/model-provider-plugin.md - Category: developer-guide - Description: 如何为 Hermes Agent 构建模型提供商(推理后端)插件 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/model-provider-plugin.md - Translated At: 2026-06-16T00:43:14.168Z - Headings: 发现机制的工作原理 | 目录结构 | 最小示例 — 简单的 API 密钥提供商 | ProviderProfile 字段 | 可覆盖钩子 | 钩子参考示例 | 用户覆盖 — 无需编辑仓库即可替换内置插件 | api mode 选择 | 认证类型 | 发现时机 | 测试你的插件 | 通用 PluginManager 集成 # 构建模型提供商插件 {#building-a-model-provider-plugin} 模型提供商插件声明一个推理后端——一个兼容 OpenAI 的端点、Anthropic Messages 服务器、Codex 风格的 Responses API 或 Bedrock 原生接口——Hermes 可以通过该后端路由 `AIAgent` 调用。每个内置提供商(OpenRouter、Anthropic、GMI、DeepSeek、Nvidia 等)都作为此类插件之一提供。第三方可以通过在 `$HERMES_HOME/plugins/model-providers/` 下放置一个目录来添加自己的插件,无需对仓库进行任何更改。 :::tip 模型提供商插件是第三种**提供商插件**。另外两种是[记忆提供商插件](/docs/developer-guide/memory-provider-plugin)(跨会话知识)和[上下文引擎插件](/docs/developer-guide/context-engine-plugin)(上下文压缩策略)。这三者都遵循相同的“放置目录、声明配置文件、无需编辑仓库”模式。 ::: ## 发现机制的工作原理 {#how-discovery-works} `providers/__init__.py._discover_providers()` 会在首次有代码调用 `get_provider_profile()` 或 `list_providers()` 时惰性运行。发现顺序如下: 1. **捆绑插件** — `/plugins/model-providers//` — 随 Hermes 一起发布 2. **用户插件** — `$HERMES_HOME/plugins/model-providers//` — 放入任意目录;后续会话无需重启即可生效 3. **遗留单文件** — `/providers/.py` — 用于树外可编辑安装的向后兼容 **用户插件会覆盖同名的捆绑插件**,因为 `register_provider()` 采用最后写入者优先策略。只需放置一个 `$HERMES_HOME/plugins/model-providers/gmi/` 目录,即可替换内置的 GMI 配置文件,而无需触碰仓库。 ## 目录结构 {#directory-structure} ``` plugins/model-providers/my-provider/ ├── __init__.py # Calls register_provider(profile) at module-level ├── plugin.yaml # kind: model-provider + metadata (optional but recommended) └── README.md # Setup instructions (optional) ``` 唯一必需的文件是 `__init__.py`。`plugin.yaml` 供 `hermes plugins` 用于内省,并由通用 PluginManager 用于将插件路由到正确的加载器;如果没有它,通用加载器将回退到源文本启发式方法。 ## 最小示例 — 简单的 API 密钥提供商 {#minimal-example-—-a-simple-api-key-provider} ```python # plugins/model-providers/acme-inference/__init__.py from providers import register_provider from providers.base import ProviderProfile acme = ProviderProfile( name="acme-inference", aliases=("acme",), display_name="Acme Inference", description="Acme — OpenAI-compatible direct API", signup_url="https://acme.example.com/keys", env_vars=("ACME_API_KEY", "ACME_BASE_URL"), base_url="https://api.acme.example.com/v1", auth_type="api_key", default_aux_model="acme-small-fast", fallback_models=( "acme-large-v3", "acme-medium-v3", "acme-small-fast", ), ) register_provider(acme) ``` ```yaml # plugins/model-providers/acme-inference/plugin.yaml name: acme-inference kind: model-provider version: 1.0.0 description: Acme Inference — OpenAI-compatible direct API author: Your Name ``` 就是这样。放置这两个文件后,以下功能将**自动连接**,无需其他编辑: | 集成 | 位置 | 获得的功能 | |---|---|---| | 凭证解析 | `hermes_cli/auth.py` | `PROVIDER_REGISTRY["acme-inference"]` 从配置文件中填充 | | `--provider` CLI 标志 | `hermes_cli/main.py` | 接受 `acme-inference` | | `hermes model` 选择器 | `hermes_cli/models.py` | 出现在 `CANONICAL_PROVIDERS` 中,模型列表从 `{base_url}/models` 获取 | | `hermes doctor` | `hermes_cli/doctor.py` | 对 `ACME_API_KEY` + `{base_url}/models` 探测进行健康检查 | | `hermes setup` | `hermes_cli/config.py` | `ACME_API_KEY` 出现在 `OPTIONAL_ENV_VARS` 和设置向导中 | | URL 反向映射 | `agent/model_metadata.py` | 主机名 → 提供商名称,用于自动检测 | | 辅助模型 | `agent/auxiliary_client.py` | 使用 `default_aux_model` 进行压缩/摘要 | | 运行时解析 | `hermes_cli/runtime_provider.py` | 返回正确的 `base_url`、`api_key`、`api_mode` | | 传输层 | `agent/transports/chat_completions.py` | 配置文件路径通过 `prepare_messages` / `build_extra_body` / `build_api_kwargs_extras` 生成 kwargs | ## ProviderProfile 字段 {#providerprofile-fields} 完整定义位于 `providers/base.py`。最常用的字段如下: | 字段 | 类型 | 用途 | |---|---|---| | `name` | str | 规范 ID — 与 `config.yaml` 中的 `model.provider` 和 `--provider` 标志匹配 | | `aliases` | `tuple[str, ...]` | 由 `get_provider_profile()` 解析的替代名称(例如 `grok` → `xai`) | | `api_mode` | str | `chat_completions` \| `codex_responses` \| `anthropic_messages` \| `bedrock_converse` | | `display_name` | str | `hermes model` 选择器中显示的人类可读标签 | | `description` | str | 选择器副标题 | | `signup_url` | str | 在首次运行设置期间显示(“在此获取 API 密钥”) | | `env_vars` | `tuple[str, ...]` | 按优先级排列的 API 密钥环境变量;最后一个 `*_BASE_URL` 条目用作用户基础 URL 覆盖 | | `base_url` | str | 默认推理端点 | | `models_url` | str | 显式目录 URL(回退到 `{base_url}/models`) | | `auth_type` | str | `api_key` \| `oauth_device_code` \| `oauth_external` \| `copilot` \| `aws_sdk` \| `external_process` | | `fallback_models` | `tuple[str, ...]` | 当实时目录获取失败时显示的精选列表 | | `default_headers` | `dict[str, str]` | 在每个请求中发送(例如 Copilot 的 `Editor-Version`) | | `fixed_temperature` | Any | `None` = 使用调用者的值;`OMIT_TEMPERATURE` 哨兵值 = 根本不发送 temperature(Kimi) | | `default_max_tokens` | `int \| None` | 提供商级别的 max_tokens 上限(Nvidia:16384) | | `default_aux_model` | str | 用于辅助任务(压缩、视觉、摘要)的廉价模型 | ## 可覆盖钩子 {#overridable-hooks} 对于非平凡的怪癖,子类化 `ProviderProfile`: ```python from typing import Any from providers.base import ProviderProfile class AcmeProfile(ProviderProfile): def prepare_messages(self, messages: list[dict[str, Any]]) -> list[dict[str, Any]]: """Provider-specific message preprocessing. Runs after codex sanitization, before developer-role swap. Default: pass-through.""" # Example: Qwen normalizes plain-text content to a list-of-parts # array and injects cache_control; Kimi rewrites tool-call JSON return messages def build_extra_body(self, *, session_id=None, **context) -> dict: """Provider-specific extra_body fields merged into the API call. Context includes: session_id, provider_preferences, model, base_url, reasoning_config. Default: empty dict.""" # Example: OpenRouter's provider-preferences block, # Gemini's thinking_config translation. return {} def build_api_kwargs_extras(self, *, reasoning_config=None, **context): """Returns (extra_body_additions, top_level_kwargs). Needed when some fields go top-level (Kimi's reasoning_effort, OpenRouter's verbosity for adaptive Anthropic models) and some go in extra_body (OpenRouter's reasoning dict). Default: ({}, {}).""" return {}, {} def fetch_models(self, *, api_key=None, timeout=8.0) -> list[str] | None: """Live catalog fetch. Default hits {models_url or base_url}/models with Bearer auth. Override for: custom auth (Anthropic), no REST endpoint (Bedrock → None), or public/unauthenticated catalogs (OpenRouter).""" return super().fetch_models(api_key=api_key, timeout=timeout) ``` ## 钩子参考示例 {#hook-reference-examples} 查看这些捆绑插件以了解惯用法: | 插件 | 为何值得关注 | |---|---| | `plugins/model-providers/openrouter/` | 聚合器,支持提供商偏好设置和公开模型目录 | | `plugins/model-providers/gemini/` | `thinking_config` 转换(原生形式 + OpenAI 兼容的嵌套形式) | | `plugins/model-providers/kimi-coding/` | `OMIT_TEMPERATURE`、`extra_body.thinking`、顶层 `reasoning_effort` | | `plugins/model-providers/qwen-oauth/` | 消息规范化、`cache_control` 注入、VL 高分辨率支持 | | `plugins/model-providers/nous/` | 归属标签,“禁用时省略推理” | | `plugins/model-providers/custom/` | Ollama `num_ctx` + `think: false` 的特殊行为 | | `plugins/model-providers/bedrock/` | `api_mode="bedrock_converse"`,`fetch_models` 返回 None(无 REST 端点) | ## 用户覆盖 — 无需编辑仓库即可替换内置插件 {#user-overrides-—-replace-a-built-in-without-editing-the-repo} 假设你想让 `gmi` 指向你的私有暂存端点以进行测试。创建 `~/.hermes/plugins/model-providers/gmi/__init__.py`: ```python from providers import register_provider from providers.base import ProviderProfile register_provider(ProviderProfile( name="gmi", aliases=("gmi-cloud", "gmicloud"), env_vars=("GMI_API_KEY",), base_url="https://gmi-staging.internal.example.com/v1", auth_type="api_key", default_aux_model="google/gemini-3.1-flash-lite-preview", )) ``` 在下一次会话中,`get_provider_profile("gmi").base_url` 将返回暂存 URL。无需修补仓库,也无需重新构建。由于用户插件在捆绑插件之后被发现,因此用户的 `register_provider()` 调用将生效。 ## api_mode 选择 {#api_mode-selection} 识别以下四个值。Hermes 基于以下规则进行选择: 1. 用户显式覆盖(如果设置了 `config.yaml` 中的 `model.api_mode`) 2. OpenCode 的每模型分发(Zen 和 Go 使用 `opencode_model_api_mode`) 3. URL 自动检测 — `/anthropic` 后缀 → `anthropic_messages`,`api.openai.com` → `codex_responses`,`api.x.ai` → `codex_responses`,Kimi 域名上的 `/coding` → `chat_completions` 4. **配置文件 `api_mode`** 作为 URL 检测未找到任何内容时的回退选项 5. 默认值 `chat_completions` 设置 `profile.api_mode` 以匹配你的提供商默认的 API 模式 — 它作为一个提示。用户 URL 覆盖仍然优先。 ## 认证类型 {#auth-types} | `auth_type` | 含义 | 使用者 | |---|---|---| | `api_key` | 单个环境变量携带静态 API 密钥 | 大多数提供商 | | `oauth_device_code` | 设备代码 OAuth 流程 | — | | `oauth_external` | 用户在别处登录,令牌存入 `auth.json` | Anthropic OAuth、MiniMax OAuth、Gemini Cloud Code、Qwen Portal、Nous Portal | | `copilot` | GitHub Copilot 令牌刷新周期 | 仅 `copilot` 插件 | | `aws_sdk` | AWS SDK 凭证链(IAM 角色、配置文件、环境变量) | 仅 `bedrock` 插件 | | `external_process` | 由代理产生的子进程处理认证 | 仅 `copilot-acp` 插件 | `auth_type` 决定了哪些代码路径将你的提供商视为“简单 API 密钥提供商” — 如果它不是 `api_key`,PluginManager 仍然会记录清单,但 Hermes 的 CLI 级自动化(doctor 检查、`--provider` 标志、设置向导委托)可能会跳过它。 ## 发现时机 {#discovery-timing} 提供商发现是**惰性**的 — 由进程中的第一次 `get_provider_profile()` 或 `list_providers()` 调用触发。实际上,这发生在启动早期(`auth.py` 模块加载时会急切地扩展 `PROVIDER_REGISTRY`)。如果你需要验证插件是否已加载,请运行: ```bash hermes doctor ``` — 成功的 `auth_type="api_key"` 配置文件将出现在 Provider Connectivity 部分,并带有 `/models` 探测。 用于程序化检查: ```python from providers import list_providers for p in list_providers(): print(p.name, p.base_url, p.api_mode) ``` ## 测试你的插件 {#testing-your-plugin} 将 `HERMES_HOME` 指向一个临时目录,以免污染你的真实配置: ```bash export HERMES_HOME=/tmp/hermes-plugin-test mkdir -p $HERMES_HOME/plugins/model-providers/my-provider cat > $HERMES_HOME/plugins/model-providers/my-provider/__init__.py <<'EOF' from providers import register_provider from providers.base import ProviderProfile register_provider(ProviderProfile( name="my-provider", env_vars=("MY_API_KEY",), base_url="https://api.my-provider.example.com/v1", auth_type="api_key", )) EOF export MY_API_KEY=your-test-key hermes -z "hello" --provider my-provider -m some-model ``` ## 通用 PluginManager 集成 {#general-pluginmanager-integration} 通用 `PluginManager`(`hermes plugins` 操作的对象)**可以看到**模型提供商插件,但不会导入它们 — `providers/__init__.py` 负责它们的生命周期。管理器记录清单以供内省,并按 `kind: model-provider` 进行分类。当你将一个未标记的用户插件放入 `$HERMES_HOME/plugins/` 且该插件恰好使用 `ProviderProfile` 调用 `register_provider` 时,管理器会通过源文本启发式方法自动将其强制转换为 `kind: model-provider` — 因此即使没有 `plugin.yaml`,插件也能正确路由。 ## 通过 pip 分发 {#distribute-via-pip} 像任何 Hermes 插件一样,模型提供商可以作为 pip 包发布。在你的 `pyproject.toml` 中添加一个入口点: ```toml [project.entry-points."hermes_agent.plugins"] acme-inference = "acme_hermes_plugin:register" ``` …其中 `acme_hermes_plugin:register` 是一个调用 `register_provider(profile)` 的函数。通用 PluginManager 在 `discover_and_load()` 期间拾取入口点插件。对于 `kind: model-provider` 的 pip 插件,你仍然需要在清单中声明种类(或依赖源文本启发式方法)。 请参阅 [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin#distribute-via-pip) 以获取完整的入口点设置。 ## 相关页面 {#related-pages} - [提供商运行时](/docs/developer-guide/provider-runtime) — 解析优先级 + 每一层读取配置文件的位置 - [添加提供商](/docs/developer-guide/adding-providers) — 新推理后端的端到端清单(涵盖快速插件路径和完整的 CLI/认证集成) - [记忆提供商插件](/docs/developer-guide/memory-provider-plugin) - [上下文引擎插件](/docs/developer-guide/context-engine-plugin) - [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin) — 通用插件创作 --- ### 插件 LLM 访问 - URL: https://hermesagent.org.cn/docs/developer-guide/plugin-llm-access - Path: developer-guide/plugin-llm-access.md - Category: developer-guide - Description: 通过 ctx.llm 在插件内部发起任意 LLM 调用——支持聊天或非结构化输出,同步或异步方式。采用宿主拥有的身份验证、故障关闭(fail closed)信任网关,以及可选的 JSON Schema 验证。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/plugin-llm-access.md - Translated At: 2026-06-16T00:43:18.411Z - Headings: 最小可能的调用 | 更完整的聊天示例 | 结构化输出 | 此通道提供的功能 | 快速开始 | 聊天补全 — /tldr | 结构化提取 — /paste to tasks | 何时使用哪种 | API 表面 | complete() | complete structured() | 异步 (Async) # 插件 LLM 访问 {#plugin-llm-access} `ctx.llm` 是插件进行 LLM 调用的支持方式。 聊天补全、结构化提取、同步、异步、带或不带图像——相同的接口表面,相同的信任网关,相同的主机托管凭据。 当插件需要执行涉及模型但不属于代理对话的任务时,会使用此功能。例如:将工具错误重写为非工程师可读内容的钩子;在入队前翻译传入消息的网关适配器;总结长粘贴文本的斜杠命令;对昨日活动进行评分并向状态板写入一行的定时任务;或者决定消息是否值得唤醒代理的预过滤器。 这些是代理不应参与循环的任务。它们只需要一次 LLM 调用、一个类型化的答案,然后完成。 ## 最小可能的调用 {#the-smallest-possible-call} ```python result = ctx.llm.complete(messages=[{"role": "user", "content": "ping"}]) return result.text ``` 这就是整个 API,只需一行代码。无需密钥,无需提供商配置,无需 SDK 初始化。插件针对用户当前使用的任何提供商和模型运行——当用户切换提供商时,插件会自动跟随。 ## 更完整的聊天示例 {#a-more-complete-chat-example} ```python result = ctx.llm.complete( messages=[ {"role": "system", "content": "Rewrite errors as one short sentence a non-engineer can act on."}, {"role": "user", "content": traceback_text}, ], max_tokens=64, purpose="hooks.error-rewrite", ) return result.text ``` `purpose` 是一个自由格式的审计字符串——它会显示在 `agent.log` 和 `result.audit` 中,以便操作员查看哪个插件进行了哪次调用。对于频繁触发的操作,这是可选但推荐的。 ## 结构化输出 {#structured-output} 当插件需要类型化的答案时,切换到结构化通道: ```python result = ctx.llm.complete_structured( instructions="Score this support reply for urgency (0–1) and pick a category.", input=[{"type": "text", "text": message_body}], json_schema=TRIAGE_SCHEMA, purpose="support.triage", temperature=0.0, max_tokens=128, ) if result.parsed["urgency"] > 0.8: await dispatch_to_oncall(result.parsed["category"], message_body) ``` 主机向提供商请求 JSON 输出,作为回退在本地解析,如果安装了 `jsonschema` 则根据你的模式进行验证,并在 `result.parsed` 上返回 Python 对象。如果模型无法生成有效的 JSON,`result.parsed` 为 `None`,而 `result.text` 携带原始响应。 ## 此通道提供的功能 {#what-this-lane-gives-you} * **一次调用,四种形态。** `complete()` 用于聊天,`complete_structured()` 用于类型化 JSON,`acomplete()` 和 `acomplete_structured()` 用于 asyncio。参数相同,结果对象相同。 * **主机托管凭据。** OAuth 令牌、刷新流程、凭据池、每任务辅助覆盖——Hermes 已有的每个凭据概念均适用。插件永远看不到令牌;主机通过 `result.audit` 归因调用。 * **有界。** 单次同步或异步调用。无流式传输,无工具循环,无需管理对话状态。陈述输入,获取结果,返回。 * **故障关闭信任。** 你从未配置过的插件无法选择自己的提供商、模型、代理或存储的凭据。默认姿态是“使用用户正在使用的内容”。操作员在 `config.yaml` 中按插件选择加入特定的覆盖。 ## 快速开始 {#quick-start} 下面有两个完整的插件——一个用于聊天,一个用于结构化。两者都包含在单个 `register(ctx)` 函数中,无需任何外部配置即可针对用户激活的任何模型运行。 ### 聊天补全 — `/tldr` {#chat-completion-—-tldr} ```python def register(ctx): ctx.register_command( name="tldr", handler=lambda raw: _tldr(ctx, raw), description="Summarise the supplied text in one paragraph.", args_hint="", ) def _tldr(ctx, raw_args: str) -> str: text = raw_args.strip() if not text: return "Usage: /tldr " result = ctx.llm.complete( messages=[ {"role": "system", "content": "Summarise the user's text in one tight paragraph. No preamble."}, {"role": "user", "content": text}, ], max_tokens=256, temperature=0.3, purpose="tldr", ) return result.text ``` `result.text` 是模型的响应;`result.usage` 携带令牌计数;`result.provider` 和 `result.model` 携带归因信息。 ### 结构化提取 — `/paste-to-tasks` {#structured-extraction-—-paste-to-tasks} ```python def register(ctx): ctx.register_command( name="paste-to-tasks", handler=lambda raw: _paste_to_tasks(ctx, raw), description="Turn freeform meeting notes into structured tasks.", args_hint="", ) _TASKS_SCHEMA = { "type": "object", "properties": { "tasks": { "type": "array", "items": { "type": "object", "properties": { "owner": {"type": "string"}, "action": {"type": "string"}, "due": {"type": "string", "description": "ISO date or empty"}, }, "required": ["action"], }, }, }, "required": ["tasks"], } def _paste_to_tasks(ctx, raw_args: str) -> str: if not raw_args.strip(): return "Usage: /paste-to-tasks " result = ctx.llm.complete_structured( instructions=( "Extract concrete action items from these meeting notes. " "One task per actionable line. If no owner is named, leave 'owner' blank." ), input=[{"type": "text", "text": raw_args}], json_schema=_TASKS_SCHEMA, schema_name="meeting.tasks", purpose="paste-to-tasks", temperature=0.0, max_tokens=512, ) if result.parsed is None: return f"Couldn't parse a response. Raw output:\n{result.text}" lines = [f"- [{t.get('owner') or '?'}] {t['action']}" for t in result.parsed["tasks"]] return "\n".join(lines) or "(no tasks found)" ``` 第三个实际示例(这次带有图像输入)位于 [`hermes-example-plugins`](https://github.com/NousResearch/hermes-example-plugins/tree/main/plugin-llm-example) 仓库中(参考插件的配套仓库——未与 hermes-agent 本身捆绑)。对于异步接口(带有 `asyncio.gather()` 的 `acomplete()` / `acomplete_structured()`),请参阅同一仓库中的 [`plugin-llm-async-example`](https://github.com/NousResearch/hermes-example-plugins/tree/main/plugin-llm-async-example)。 ## 何时使用哪种 {#when-to-use-which} | 你想要… | 使用 | |---|---| | 自由格式文本响应(翻译、总结、重写、生成) | `complete()` | | 多轮提示(系统 + 少样本示例 + 用户) | `complete()` | | 针对模式验证的类型化字典返回 | `complete_structured()` | | 带有类型化字典返回的图像或文本输入 | `complete_structured()` | | 从异步代码发起相同调用(网关适配器、异步钩子) | `acomplete()` / `acomplete_structured()` | 其他所有内容——提供商选择、模型解析、身份验证、回退、超时、视觉路由——在所有四种情况下都是相同的。 ## API 表面 {#api-surface} `ctx.llm` 是 `agent.plugin_llm.PluginLlm` 的一个实例。 ### `complete()` {#complete} ```python result = ctx.llm.complete( messages=[{"role": "user", "content": "Hi"}], provider=None, # optional, gated — Hermes provider id (e.g. "openrouter") model=None, # optional, gated — whatever string that provider expects temperature=None, max_tokens=None, timeout=None, # seconds agent_id=None, # optional, gated profile=None, # optional, gated — explicit auth-profile name purpose="optional-audit-string", ) # → PluginLlmCompleteResult(text, provider, model, agent_id, usage, audit) ``` 普通聊天补全。`messages` 是标准的 OpenAI 格式——一个包含 `{"role": "...", "content": "..."}` 字典的列表。多轮提示(系统 + 少样本用户/助手对 + 最终用户)的工作方式与使用 OpenAI SDK 完全相同。 `provider=` 和 `model=` 是独立的,并遵循与主机主配置相同的结构(`model.provider` + `model.model`)。仅设置 `model=` 以使用用户的活跃提供商及其上的不同模型。同时设置两者以完全切换提供商。如果没有操作员选择加入,任一参数都会引发 `PluginLlmTrustError`。 ### `complete_structured()` {#complete_structured} ```python result = ctx.llm.complete_structured( instructions="What you want extracted.", input=[ {"type": "text", "text": "..."}, {"type": "image", "data": b"...", "mime_type": "image/png"}, {"type": "image", "url": "https://..."}, ], json_schema={...}, # optional — triggers parsed result + validation json_mode=False, # set True without a schema to ask for JSON anyway schema_name=None, # optional human-readable schema name system_prompt=None, provider=None, # optional, gated model=None, # optional, gated temperature=None, max_tokens=None, timeout=None, agent_id=None, profile=None, purpose=None, ) # → PluginLlmStructuredResult(text, provider, model, agent_id, # usage, parsed, content_type, audit) ``` 输入为类型化的文本或图像块(原始字节会自动进行 base64 编码并作为 `data:` URL 处理)。当提供 `json_schema` 或 `json_mode=True` 时,宿主会通过 `response_format` 请求 JSON 输出,在本地解析作为后备方案,并且如果安装了 `jsonschema`,还会根据你的 schema 进行验证。 * `result.content_type == "json"` — `result.parsed` 是与你的 schema 匹配的 Python 对象。 * `result.content_type == "text"` — 解析或验证失败;检查 `result.text` 以获取原始模型响应。 ### 异步 (Async) {#async} ```python result = await ctx.llm.acomplete(messages=...) result = await ctx.llm.acomplete_structured(instructions=..., input=...) ``` 参数和结果类型与其同步对应项相同。从网关适配器、异步钩子或任何已在 asyncio 循环中运行的插件代码中使用这些方法。 ### 结果属性 (Result attributes) {#result-attributes} ```python @dataclass class PluginLlmCompleteResult: text: str # the assistant's response provider: str # e.g. "openrouter", "anthropic" model: str # whatever the provider returned for this call agent_id: str # whose model/auth was used usage: PluginLlmUsage # tokens + cache + cost estimate audit: Dict[str, Any] # plugin_id, purpose, profile @dataclass class PluginLlmStructuredResult(PluginLlmCompleteResult): parsed: Optional[Any] # JSON object when content_type == "json" content_type: str # "json" or "text" # audit also carries schema_name when supplied ``` 当提供商返回这些字段时,`usage` 包含 `input_tokens`、`output_tokens`、`total_tokens`、`cache_read_tokens`、`cache_write_tokens` 和 `cost_usd`。 ## 信任网关 (Trust gate) {#trust-gate} 默认行为是故障关闭(fail-closed)。如果没有 `plugins.entries` 配置块,插件可以: * 针对用户活动的提供商和模型运行四种方法中的任何一种, * 设置请求整形参数(`temperature`、`max_tokens`、`timeout`、`system_prompt`、`purpose`、`messages`、`instructions`、`input`、`json_schema`), ……仅此而已。`provider=`、`model=`、`agent_id=` 和 `profile=` 参数会抛出 `PluginLlmTrustError`,直到操作员选择启用为止。 **大多数插件永远不需要本节。** 一个仅调用 `ctx.llm.complete(messages=...)` 且无覆盖的插件会针对用户当前活动的配置运行,无需任何配置即可工作。下面的块仅在插件特别希望固定到与用户不同的模型或提供商时才相关。 ```yaml plugins: entries: my-plugin: llm: # Allow this plugin to choose a different Hermes provider # (must be one Hermes already knows about — same names as # `hermes model` and config.yaml model.provider). allow_provider_override: true # Optionally restrict which providers. Use ["*"] for any. allowed_providers: - openrouter - anthropic # Allow this plugin to ask for a specific model. allow_model_override: true # Optionally restrict which models. Use ["*"] for any. # Models are matched literally against whatever string the # plugin sends — Hermes does not look anything up. allowed_models: - openai/gpt-4o-mini - anthropic/claude-3-5-haiku # Allow cross-agent calls (rare). allow_agent_id_override: false # Allow the plugin to request a specific stored auth profile # (e.g. a different OAuth account on the same provider). allow_profile_override: false ``` 插件 ID 是扁平插件的 manifest `name:` 字段,或者是嵌套插件的路径派生键(例如 `image_gen/openai`、`memory/honcho` 等)。 ### 网关强制执行的内容 {#what-the-gate-enforces} | 覆盖项 | 默认值 | 配置键 | | ------------------ | -------- | ---------------------------------- | | `provider=` | 拒绝 | `allow_provider_override: true` | | ↳ 允许列表 | — | `allowed_providers: [...]` | | `model=` | 拒绝 | `allow_model_override: true` | | ↳ 允许列表 | — | `allowed_models: [...]` | | `agent_id=` | 拒绝 | `allow_agent_id_override: true` | | `profile=` | 拒绝 | `allow_profile_override: true` | 每个覆盖项都是独立受控的。授予 `allow_model_override` **不会**同时授予 `allow_provider_override` — 即使插件被信任可以选择模型,除非它也获得了提供商网关权限,否则仍会被限制在用户活动的提供商上。 ### 网关不需要强制执行的内容 {#what-the-gate-does-not-need-to-enforce} * 请求整形参数 — `temperature`、`max_tokens`、`timeout`、`system_prompt`、`purpose`、`messages`、`instructions`、`input`、`json_schema`、`schema_name`、`json_mode` — 始终允许;它们不涉及选择凭据或路由。 * 默认的拒绝姿态意味着未配置的插件仍然可以执行有用的工作 — 它只是针对活动的提供商和模型运行。操作员只需要为想要更精细路由的插件考虑 `plugins.entries`。 ## 宿主拥有的内容 {#what-the-host-owns} 以下是 `ctx.llm` 为插件执行的完整事项列表,因此你无需自行处理: * **提供商解析。** 从用户的配置中读取 `model.provider` + `model.model`(或在受信任时使用显式覆盖)。 * **认证。** 从 `~/.hermes/auth.json` / 环境变量中提取 API 密钥、OAuth 令牌或刷新令牌,包括在配置了凭据池时的情况。插件永远不会看到这些凭据。 * **视觉路由。** 当提供图像输入且用户活动的文本模型仅支持文本时,宿主会自动回退到配置的视觉模型。 * **回退链。** 如果用户的主要提供商返回 5xx 或 429 错误,请求会在向插件返回错误之前经过 Hermes 常规的聚合器感知回退流程。 * **超时。** 遵守你的 `timeout=` 参数,回退到 `auxiliary..timeout` 配置或全局 aux 默认值。 * **JSON 整形。** 当你请求 JSON 时,向提供商发送 `response_format`,如果提供商返回了代码围栏响应,则在本地重新解析。 * **Schema 验证。** 当安装了 `jsonschema` 时,根据你的 `json_schema` 进行验证;否则记录调试行并跳过严格验证。 * **审计日志。** 每次调用都会向 `agent.log` 写入一行 INFO 日志,包含插件 ID、提供商/模型、用途和令牌总数。 ## 插件拥有的内容 {#what-the-plugin-owns} * **请求形状(Request shape)。** 聊天使用 `messages`,结构化使用 `instructions` + `input`。插件构建提示词;宿主执行它。 * **模式(Schema)。** 你希望返回的任何形状。宿主不会为你推断它。 * **错误处理。** 当输入为空或模式验证失败时,`complete_structured()` 会抛出 `ValueError`。当信任网关拒绝覆盖时,会触发 `PluginLlmTrustError`。其他任何情况(提供商 5xx 错误、未配置凭据、超时)都会抛出 `auxiliary_client.call_llm()` 所抛出的任何异常。 * **成本。** 每次调用都针对用户付费的提供商运行。不要在不考虑 token 消耗的情况下,对每个网关消息循环调用 `complete()`。 ## 这在插件表面中的位置 {#where-this-fits-in-the-plugin-surface} 现有的 `ctx.*` 方法扩展了现有的 Hermes 子系统: | `ctx.register_tool` | 添加代理可以调用的工具 | | `ctx.register_platform` | 连接新的网关适配器 | | `ctx.register_image_gen_provider` | 替换图像生成后端 | | `ctx.register_memory_provider` | 替换记忆后端 | | `ctx.register_context_engine` | 替换上下文压缩器 | | `ctx.register_hook` | 观察生命周期事件 | `ctx.llm` 是第一个让插件能够*out of band*(带外)运行与用户交谈的相同模型的表面,而不涉及上述任何内容。这是它唯一的工作。如果你的插件需要注册一个由代理调用的工具,请使用 `register_tool`。如果它需要对生命周期事件做出反应,请使用 `register_hook`。如果它需要进行自己的模型调用——无论出于何种原因,无论是结构化还是非结构化——使用 `ctx.llm`。 ## 参考 {#reference} * 实现:[`agent/plugin_llm.py`](https://github.com/NousResearch/hermes-agent/blob/main/agent/plugin_llm.py) * 测试:[`tests/agent/test_plugin_llm.py`](https://github.com/NousResearch/hermes-agent/blob/main/tests/agent/test_plugin_llm.py) * 参考插件(配套仓库): * [`plugin-llm-example`](https://github.com/NousResearch/hermes-example-plugins/tree/main/plugin-llm-example) — 带有图像输入的同步结构化提取 * [`plugin-llm-async-example`](https://github.com/NousResearch/hermes-example-plugins/tree/main/plugin-llm-async-example) — 使用 `asyncio.gather()` 的异步示例 * 辅助客户端(底层引擎):参见 [Provider Runtime](/docs/developer-guide/provider-runtime)。 --- ### 程序化集成 - URL: https://hermesagent.org.cn/docs/developer-guide/programmatic-integration - Path: developer-guide/programmatic-integration.md - Category: developer-guide - Description: 用于从外部程序驱动 hermes agent 的三种协议:ACP、TUI 网关 JSON RPC 以及兼容 OpenAI 的 HTTP API - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/programmatic-integration.md - Translated At: 2026-06-16T00:42:50.809Z - Headings: ACP(Agent Client Protocol) | TUI 网关 JSON RPC | 方法目录(精选) | 回传的事件流 | Pi 风格 RPC 映射 | 兼容 OpenAI 的 API 服务器 | 我该使用哪一个? | 模型热切换 | 关于 mode rpc 的说明 # 编程式集成 {#programmatic-integration} Hermes 提供了三种协议,用于从外部程序(如 IDE 插件、自定义 UI、CI 流水线、嵌入式子代理)驱动代理。请根据你的传输方式和消费者选择匹配的协议。 | 协议 | 传输方式 | 适用场景 | 定义位置 | |----------|-----------|----------|------------| | **ACP** | 基于 stdio 的 JSON-RPC | 已经支持 [Agent Client Protocol](https://github.com/zed-industries/agent-client-protocol) 的 IDE 客户端(VS Code、Zed、JetBrains) | `acp_adapter/` | | **TUI 网关** | 基于 stdio(或 WebSocket)的 JSON-RPC | 需要对会话、斜杠命令、审批和流式事件进行细粒度控制的自定义宿主 | `tui_gateway/server.py` | | **API 服务器** | HTTP + 服务器发送事件 (SSE) | 兼容 OpenAI 的前端(Open WebUI、LobeChat、LibreChat……)以及语言无关的 Web 客户端 | `gateway/platforms/api_server.py` | 这三种协议驱动的都是同一个 `AIAgent` 核心。它们的区别仅在于线路格式(wire format)以及所暴露的功能集。 --- ## ACP(Agent Client Protocol) {#acp-agent-client-protocol} `hermes acp` 启动一个通过 stdio 通信并遵循 ACP 协议的 JSON-RPC 服务器。它已被 VS Code(Zed Industries 的 ACP 扩展)、Zed 以及任何安装了 ACP 插件的 JetBrains IDE 在生产环境中使用。 暴露的能力包括:会话创建、提示提交、流式代理消息片段、工具调用事件、权限请求、会话分支、取消以及身份验证。工具输出会被渲染为 IDE 可理解的 ACP `Diff`/`ToolCall` 内容块。 完整的生命周期、事件桥接和审批流程详见:[ACP 内部机制](acp-internals)。 ```bash hermes acp # serve ACP on stdio hermes acp --bootstrap # print install snippet for an ACP-capable IDE ``` --- ## TUI 网关 JSON-RPC {#tui-gateway-json-rpc} `tui_gateway/server.py` 是 Ink TUI(`hermes --tui`)和嵌入式仪表板 PTY 桥接所使用的协议。任何外部宿主都可以通过 stdio(或通过 `tui_gateway/ws.py` 使用 WebSocket)使用相同的协议进行通信。 ### 方法目录(精选) {#method-catalog-selected} ``` prompt.submit prompt.background session.steer session.create session.list session.active_list session.activate session.close session.interrupt session.history session.compress session.branch session.title session.usage session.status clarify.respond sudo.respond secret.respond approval.respond config.set / config.get commands.catalog command.resolve command.dispatch cli.exec reload.mcp reload.env process.stop delegation.status subagent.interrupt spawn_tree.save / list / load terminal.resize clipboard.paste image.attach ``` `session.active_list`、`session.activate` 和 `session.close` 是 TUI 会话切换器使用的进程内活跃会话控制方法。请使用 `session.list` / `/resume` 来发现已保存的转录记录;仅对当前在 TUI 网关进程中打开的会话使用活跃会话方法。 ### 回传的事件流 {#events-streamed-back} `message.delta`、`message.complete`、`tool.start`、`tool.progress`、`tool.complete`、`approval.request`、`clarify.request`、`sudo.request`、`secret.request`、`gateway.ready`,以及会话生命周期和错误事件。 ### Pi 风格 RPC 映射 {#pi-style-rpc-mapping} Pi-mono RPC 规范([issue #360](https://github.com/NousResearch/hermes-agent/issues/360))中的每个命令都有对应的 TUI 网关等效命令: | Pi 命令 | Hermes 等效命令 | |------------|-------------------| | `prompt` | `prompt.submit`(或 ACP `session/prompt`) | | `steer` | `session.steer` | | `follow_up` | 在当前轮次后排队的 `prompt.submit` | | `abort` | `session.interrupt` | | `set_model` | 用于 `/model ` 的 `command.dispatch`(会话中途,持久化) | | `compact` | `session.compress` | | `get_state` | `session.status` | | `get_messages` | `session.history` | | `switch_session` | `session.resume` | | `fork` | `session.branch` | | `ui_request` / `ui_response` | `clarify.respond` / `sudo.respond` / `secret.respond` / `approval.respond` | --- ## 兼容 OpenAI 的 API 服务器 {#openai-compatible-api-server} `gateway/platforms/api_server.py` 通过 HTTP 暴露 Hermes,适用于任何已经支持 OpenAI 格式的客户端。当你需要 Web 前端、由 curl 驱动的 CI 运行器或非 Python 消费者时,这非常有用。 端点: ``` POST /v1/chat/completions OpenAI Chat Completions (streaming via SSE) POST /v1/responses OpenAI Responses API (stateful) POST /v1/runs Start a run, returns run_id (202) GET /v1/runs/{id} Run status GET /v1/runs/{id}/events SSE stream of lifecycle events POST /v1/runs/{id}/approval Resolve a pending approval POST /v1/runs/{id}/stop Interrupt the run GET /v1/capabilities Machine-readable feature flags GET /v1/models Lists hermes-agent GET /health, /health/detailed ``` 设置、头部信息(`X-Hermes-Session-Id`、`X-Hermes-Session-Key`)以及前端连接配置详见:[API 服务器](../user-guide/features/api-server)。 --- ## 我该使用哪一个? {#which-one-should-i-use} - **你正在编写 IDE 插件,且该 IDE 已经支持 ACP** → 使用 ACP。IDE 端无需进行额外的协议开发工作。 - **你正在编写自定义桌面/Web/TUI 宿主,并希望使用所有 Hermes 功能**(斜杠命令、审批、澄清、多代理、会话分支)→ 使用 TUI 网关 JSON-RPC。 - **你需要任何兼容 OpenAI 的前端、语言无关的 HTTP 客户端,或由 curl 驱动的自动化** → 使用 API 服务器。 - **你想要无需子进程的 Python 进程内嵌入** → 直接导入 `run_agent.AIAgent`。详见 [代理循环](agent-loop)。 --- ## 模型热切换 {#model-hot-swapping} 会话中途的模型切换在所有界面上均有效——其底层实现是 `/model` 斜杠命令。 - **CLI / TUI:** `/model claude-sonnet-4` 或 `/model openrouter:anthropic/claude-sonnet-4.6` - **TUI 网关 RPC:** 使用 `{"command": "/model claude-sonnet-4"}` 调用 `command.dispatch` - **ACP:** IDE 将斜杠命令作为提示发送;代理对其进行分发 - **API 服务器:** 在请求体中包含 `model` 字段或设置 `X-Hermes-Model` 内置了感知提供商的解析功能(相同的模型名称会根据你所在的提供商自动选择正确的格式)。详见 `hermes_cli/model_switch.py`。 --- ## 关于 `--mode rpc` 的说明 {#a-note-on---mode-rpc} Hermes 没有 `--mode rpc` 标志。上述三种协议已经涵盖了各种用例——ACP 适用于 IDE 协议客户端,TUI 网关适用于 stdio JSON-RPC 宿主,API 服务器适用于 HTTP。如果你发现它们都无法填补的实际空白,请针对你正在构建的具体消费者提交 issue。 --- ### 提示词组装 - URL: https://hermesagent.org.cn/docs/developer-guide/prompt-assembly - Path: developer-guide/prompt-assembly.md - Category: developer-guide - Description: Hermes 如何构建系统提示、保持缓存稳定性以及注入临时层 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/prompt-assembly.md - Translated At: 2026-04-11T03:24:21.619Z - Headings: 缓存的系统提示层 | 具体示例:组装后的系统提示 | 持久 Memory | 用户 Profile | Skills(必填) | AGENTS.md | SOUL.md 在提示词中的呈现方式 | 上下文文件的注入方式 | 上下文文件发现细节 | 仅在 API 调用时生效的层 | 记忆快照 | 上下文文件 # 提示词组装 {#prompt-assembly} Hermes 明确区分了: - **缓存的系统提示状态** - **仅在 API 调用时临时添加的内容** 这是该项目最重要的设计决策之一,因为它影响: - token 使用量 - 提示词缓存效率 - 会话连续性 - 记忆正确性 主要文件: - `run_agent.py` - `agent/prompt_builder.py` - `tools/memory_tool.py` ## 缓存的系统提示层 {#cached-system-prompt-layers} 缓存的系统提示按以下顺序组装: 1. Agent 身份 —— 若 `HERMES_HOME` 下存在 `SOUL.md`,则使用该文件;否则回退至 `prompt_builder.py` 中的 `DEFAULT_AGENT_IDENTITY` 2. 工具感知行为指导 3. Honcho 静态块(当启用时) 4. 可选的系统消息 5. 冻结的 MEMORY 快照 6. 冻结的 USER 配置文件快照 7. 技能索引 8. 上下文文件(`AGENTS.md`、`.cursorrules`、`.cursor/rules/*.mdc`)—— 若第 1 步已加载 `SOUL.md` 作为身份,则此处不再包含 `SOUL.md` 9. 时间戳 / 可选会话 ID 10. 平台提示 当设置 `skip_context_files` 时(例如子 Agent 委派),`SOUL.md` 不会被加载,而是直接使用硬编码的 `DEFAULT_AGENT_IDENTITY`。 ### 具体示例:组装后的系统提示 {#concrete-example-assembled-system-prompt} 以下是所有层均存在时最终系统提示的简化视图(注释标明各部分来源): ``` # 第 1 层:Agent 身份(来自 `~/.hermes/SOUL.md`) You are Hermes, an AI assistant created by Nous Research. You are an expert software engineer and researcher. You value correctness, clarity, and efficiency. ... # 第 2 层:Tool 感知行为指导 You have persistent memory across sessions. Save durable facts using the memory tool: user preferences, environment details, tool quirks, and stable conventions. Memory is injected into every turn, so keep it compact and focused on facts that will still matter later. ... When the user references something from a past conversation or you suspect relevant cross-session context exists, use session_search to recall it before asking them to repeat themselves. # Tool-使用强制执行(仅适用于 GPT/Codex models) You MUST use your tools to take action — do not describe what you would do or plan to do without actually doing it. ... # 第 3 层:Honcho 静态块(激活时) [Honcho personality/context data] # 第 4 层:可选系统消息(来自配置或 API) [User-configured system message override] # 第 5 层:冻结 MEMORY 快照 ## 持久 Memory - User prefers Python 3.12, uses pyproject.toml - Default editor is nvim - Working on project "atlas" in ~/code/atlas - Timezone: US/Pacific # 第 6 层:冻结 USER profile 快照 ## 用户 Profile - Name: Alice - GitHub: alice-dev # 第 7 层:Skills 索引 ## Skills(必填) Before replying, scan the skills below. If one clearly matches your task, load it with skill_view(name) and follow its instructions. ... software-development: - code-review: Structured code review workflow - test-driven-development: TDD methodology research: - arxiv: Search and summarize arXiv papers # 第 8 层:Context 文件(来自项目目录) # 项目上下文 The following project context files have been loaded and should be followed: ## AGENTS.md This is the atlas project. Use pytest for testing. The main entry point is src/atlas/main.py. Always run `make lint` before committing. # 第9层:时间戳+session Current time: 2026-03-30T14:30:00-07:00 Session: abc123 # 第10层:平台提示 You are a CLI AI Agent. Try not to use markdown but simple text renderable inside a terminal. ``` ## `SOUL.md` 在提示词中的呈现方式 {#how-soulmd-appears-in-the-prompt} `SOUL.md` 位于 `~/.hermes/SOUL.md`,作为 Agent 的身份标识 —— 系统提示的最开始部分。`prompt_builder.py` 中的加载逻辑如下: ```python # 来自代理/prompt_builder.py(简体) def load_soul_md() -> Optional[str]: soul_path = get_hermes_home() / "SOUL.md" if not soul_path.exists(): return None content = soul_path.read_text(encoding="utf-8").strip() content = _scan_context_content(content, "SOUL.md") # 安全扫描 content = _truncate_content(content, "SOUL.md") # 上限为 20k 字符 return content ``` 当 `load_soul_md()` 返回内容时,它将替换硬编码的 `DEFAULT_AGENT_IDENTITY`。随后调用 `build_context_files_prompt()` 并传入 `skip_soul=True`,以防止 `SOUL.md` 被重复出现(一次作为身份,一次作为上下文文件)。 若 `SOUL.md` 不存在,则系统回退至: ``` You are Hermes Agent, an intelligent AI assistant created by Nous Research. You are helpful, knowledgeable, and direct. You assist users with a wide range of tasks including answering questions, writing and editing code, analyzing information, creative work, and executing actions via your tools. You communicate clearly, admit uncertainty when appropriate, and prioritize being genuinely useful over being verbose unless otherwise directed below. Be targeted and efficient in your exploration and investigations. ``` ## 上下文文件的注入方式 {#how-context-files-are-injected} `build_context_files_prompt()` 使用 **优先级系统** —— 仅加载一种项目上下文类型(首个匹配项胜出): ```python # 来自代理/prompt_builder.py(简体) def build_context_files_prompt(cwd=None, skip_soul=False): cwd_path = Path(cwd).resolve() # 优先级:第一场比赛获胜 - 仅加载 ONE 项目 context project_context = ( _load_hermes_md(cwd_path) # 1. .hermes.md / HERMES.md(走到 git 根目录) or _load_agents_md(cwd_path) # 2. AGENTS.md(仅限 cwd) or _load_claude_md(cwd_path) # 3. CLAUDE.md(仅限cwd) or _load_cursorrules(cwd_path) # 4. .cursorrules / .cursor/rules/*.mdc ) sections = [] if project_context: sections.append(project_context) # `SOUL.md` 来自 `HERMES_HOME`(独立于项目上下文) if not skip_soul: soul_content = load_soul_md() if soul_content: sections.append(soul_content) if not sections: return "" return ( "# Project Context\n\n" "The following project context files have been loaded " "and should be followed:\n\n" + "\n".join(sections) ) ``` ### 上下文文件发现细节 {#context-file-discovery-details} | 优先级 | 文件 | 搜索范围 | 说明 | |--------|------|----------|------| | 1 | `.hermes.md`、`HERMES.md` | 从当前工作目录向上至 git 仓库根目录 | Hermes 原生项目配置 | | 2 | `AGENTS.md` | 仅当前工作目录 | 常见的 Agent 指令文件 | | 3 | `CLAUDE.md` | 仅当前工作目录 | Claude Code 兼容性 | | 4 | `.cursorrules`、`.cursor/rules/*.mdc` | 仅当前工作目录 | Cursor 兼容性 | 所有上下文文件均经过: - **安全扫描** —— 检查提示注入模式(不可见 Unicode、"忽略先前指令"、凭证外泄尝试) - **截断处理** —— 使用 70/20 头尾比例,上限 20,000 字符,并添加截断标记 - **移除 YAML 前置元数据** —— `.hermes.md` 的前置元数据将被移除(保留用于未来配置覆盖) ## 仅在 API 调用时生效的层 {#api-call-time-only-layers} 这些内容**不会**作为缓存系统提示的一部分持久化: - `ephemeral_system_prompt` - 预填充消息 - 网关派生的会话上下文叠加层 - 后续轮次 Honcho 回忆注入到当前轮次用户消息中 这种分离确保了稳定前缀的稳定性,便于缓存。 ## 记忆快照 {#memory-snapshots} 本地记忆和用户配置文件数据在会话开始时作为冻结快照注入。会话中段的写入会更新磁盘状态,但不会修改已构建的系统提示,直到新会话或强制重建发生。 ## 上下文文件 {#context-files} `agent/prompt_builder.py` 使用 **优先级系统** 扫描并净化项目上下文文件 —— 仅加载一种类型(首个匹配项胜出): 1. `.hermes.md` / `HERMES.md`(从当前目录向上遍历至 git 根目录) 2. `AGENTS.md`(启动时仅在当前工作目录;会话期间通过 `agent/subdirectory_hints.py` 逐步发现子目录) 3. `CLAUDE.md`(仅当前工作目录) 4. `.cursorrules` / `.cursor/rules/*.mdc`(仅当前工作目录) `SOUL.md` 通过 `load_soul_md()` 单独加载,用于身份槽位。若加载成功,则调用 `build_context_files_prompt(skip_soul=True)` 以防止其重复出现。 长文件在注入前会被截断。 ## 技能索引 {#skills-index} 当可用技能工具时,技能系统会向提示词中添加一个紧凑的技能索引。 ## 为何提示词组装采用此方式 {#why-prompt-assembly-is-split-this-way} 该架构有意优化以实现: - 保留提供商端的提示词缓存 - 避免不必要的历史变更 - 保持记忆语义清晰可理解 - 允许网关/ACP/CLI 添加上下文,而不污染持久化提示状态 ## 相关文档 {#related-docs} - [上下文压缩与提示词缓存](context-compression-and-caching) - [会话存储](session-storage) - [网关内部机制](gateway-internals) --- ### 提供者运行时解析 - URL: https://hermesagent.org.cn/docs/developer-guide/provider-runtime - Path: developer-guide/provider-runtime.md - Category: developer-guide - Description: Hermes 如何在运行时解析提供者、凭据、API 模式和辅助模型 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/provider-runtime.md - Translated At: 2026-04-11T03:24:31.223Z - Headings: 解析优先级 | 提供者 | 运行时解析的输出 | 为何如此重要 | AI Gateway | OpenRouter、AI Gateway 与自定义 OpenAI 兼容基础 URL | 原生 Anthropic 路径 | OpenAI Codex 路径 | 辅助模型路由 | 回退模型 | 内部工作原理 | 不支持回退的功能 # 提供者运行时解析 {#provider-runtime-resolution} Hermes 使用一个跨以下组件共享的提供者运行时解析器: - CLI - 网关 - 定时任务 - ACP - 辅助模型调用 主要实现: - `hermes_cli/runtime_provider.py` — 凭据解析,`_resolve_custom_runtime()` - `hermes_cli/auth.py` — 提供者注册表,`resolve_provider()` - `hermes_cli/model_switch.py` — 共享的 `/model` 切换流程(CLI + 网关) - `agent/auxiliary_client.py` — 辅助模型路由 如果你正在尝试添加一个新的第一类推理提供者,请同时阅读本页和 [添加提供者](adding-providers)。 ## 解析优先级 {#resolution-precedence} 从整体上看,提供者解析遵循以下顺序: 1. 显式 CLI/运行时请求 2. `config.yaml` 中的模型/提供者配置 3. 环境变量 4. 提供者特定的默认值或自动解析 这一顺序至关重要,因为 Hermes 将保存的模型/提供者选择视为正常运行的“真理来源”。这可以防止旧的 shell 环境变量导出静默覆盖用户在 `hermes model` 中最后选择的端点。 ## 提供者 {#providers} 当前支持的提供者类别包括: - AI Gateway(Vercel) - OpenRouter - Nous Portal - OpenAI Codex - Copilot / Copilot ACP - Anthropic(原生) - Google / Gemini - 阿里巴巴 / DashScope - DeepSeek - Z.AI - Kimi / Moonshot - MiniMax - MiniMax 中国 - Kilo Code - Hugging Face - OpenCode Zen / OpenCode Go - 自定义(`provider: custom`)—— 用于任何 OpenAI 兼容端点的第一类提供者 - 命名自定义提供者(`config.yaml` 中的 `custom_providers` 列表) ## 运行时解析的输出 {#output-of-runtime-resolution} 运行时解析器返回如下数据: - `provider` - `api_mode` - `base_url` - `api_key` - `source` - 提供者特定的元数据,如过期/刷新信息 ## 为何如此重要 {#why-this-matters} 该解析器是 Hermes 能够在以下场景间共享认证/运行时逻辑的主要原因: - `hermes chat` - 网关消息处理 - 在全新会话中运行的定时任务 - ACP 编辑器会话 - 辅助模型任务 ## AI Gateway {#ai-gateway} 在 `~/.hermes/.env` 中设置 `AI_GATEWAY_API_KEY`,并使用 `--provider ai-gateway` 运行。Hermes 会从网关的 `/models` 端点获取可用模型,并筛选出支持工具使用的语言模型。 ## OpenRouter、AI Gateway 与自定义 OpenAI 兼容基础 URL {#openrouter-ai-gateway-and-custom-openai-compatible-base-urls} Hermes 包含逻辑,以避免在存在多个提供者密钥时(例如 `OPENROUTER_API_KEY`、`AI_GATEWAY_API_KEY` 和 `OPENAI_API_KEY`)将错误的 API 密钥泄露给自定义端点。 每个提供者的 API 密钥都限定于其自身的基础 URL: - `OPENROUTER_API_KEY` 仅发送至 `openrouter.ai` 端点 - `AI_GATEWAY_API_KEY` 仅发送至 `ai-gateway.vercel.sh` 端点 - `OPENAI_API_KEY` 用于自定义端点,并作为回退 Hermes 还区分: - 用户明确选择的真实自定义端点 - 当未配置自定义端点时使用的 OpenRouter 回退路径 这种区分在以下场景中尤为重要: - 本地模型服务器 - 非 OpenRouter / 非 AI Gateway 的 OpenAI 兼容 API - 切换提供者而无需重新运行设置 - 保存在配置中的自定义端点,即使当前 shell 中未导出 `OPENAI_BASE_URL` 也能继续工作 ## 原生 Anthropic 路径 {#native-anthropic-path} Anthropic 已不再仅通过 OpenRouter 实现。 当提供者解析选择 `anthropic` 时,Hermes 使用: - `api_mode = anthropic_messages` - 原生 Anthropic Messages API - `agent/anthropic_adapter.py` 进行转换 原生 Anthropic 的凭据解析现在优先使用可刷新的 Claude Code 凭据,而非复制的环境变量令牌(当两者都存在时)。实际上这意味着: - 当 Claude Code 凭据文件包含可刷新认证时,被视为首选来源 - 手动设置的 `ANTHROPIC_TOKEN` / `CLAUDE_CODE_OAUTH_TOKEN` 值仍可作为显式覆盖 - Hermes 在调用原生 Messages API 前会预先刷新 Anthropic 凭据 - Hermes 在重建 Anthropic 客户端后,若遇到 401 错误仍会重试一次,作为回退路径 ## OpenAI Codex 路径 {#openai-codex-path} Codex 使用独立的 Responses API 路径: - `api_mode = codex_responses` - 专用的凭据解析与认证存储支持 ## 辅助模型路由 {#auxiliary-model-routing} 以下辅助任务可使用其自身的提供者/模型路由,而非主对话模型: - 视觉处理 - 网页提取摘要 - 上下文压缩摘要 - 会话搜索摘要 - 技能中心操作 - MCP 帮助器操作 - 记忆清除 当辅助任务配置大模型提供商为 `main` 时,Hermes 通过与正常聊天相同的共享运行时路径进行解析。实际上这意味着: - 基于环境变量的自定义端点仍可工作 - 通过 `hermes model` / `config.yaml` 保存的自定义端点也可工作 - 辅助路由能够区分真实保存的自定义端点与 OpenRouter 回退路径 ## 回退模型 {#fallback-models} Hermes 支持配置的回退模型/提供者对,允许在主模型遇到错误时进行运行时故障转移。 ### 内部工作原理 {#how-it-works-internally} 1. **存储**:`AIAgent.__init__` 将 `fallback_model` 字典存储,并设置 `_fallback_activated = False`。 2. **触发点**:`_try_activate_fallback()` 在 `run_agent.py` 的主重试循环中被调用三次: - 在无效 API 响应(None choices、缺少内容)达到最大重试次数后 - 在非可重试的客户端错误(HTTP 401、403、404)发生时 - 在瞬态错误(HTTP 429、500、502、503)达到最大重试次数后 3. **激活流程**(`_try_activate_fallback`): - 如果已激活或未配置,立即返回 `False` - 调用 `auxiliary_client.py` 中的 `resolve_provider_client()` 构建带有正确认证的新客户端 - 确定 `api_mode`:`codex_responses` 用于 openai-codex,`anthropic_messages` 用于 anthropic,其余情况为 `chat_completions` - 就地替换:`self.model`、`self.provider`、`self.base_url`、`self.api_mode`、`self.client`、`self._client_kwargs` - 对 anthropic 回退:构建原生 Anthropic 客户端,而非 OpenAI 兼容客户端 - 重新评估提示缓存(在 OpenRouter 上,Claude 模型启用提示缓存) - 设置 `_fallback_activated = True` —— 防止再次触发 - 重置重试计数为 0,并继续循环 4. **配置流程**: - CLI:`cli.py` 读取 `CLI_CONFIG["fallback_model"]` → 传递给 `AIAgent(fallback_model=...)` - 网关:`gateway/run.py._load_fallback_model()` 读取 `config.yaml` → 传递给 `AIAgent` - 验证:`provider` 和 `model` 键都必须非空,否则回退功能被禁用 ### 不支持回退的功能 {#what-does-not-support-fallback} - **子 Agent 委派**(`tools/delegate_tool.py`):子 Agent 继承父 Agent 的提供者,但不继承回退配置 - **定时任务**(`cron/`):使用固定提供者运行,无回退机制 - **辅助任务**:使用其自身独立的提供者自动检测链(参见上方“辅助模型路由”) ### 测试覆盖 {#test-coverage} 详见 `tests/test_fallback_model.py`,涵盖所有支持的提供者、单次调用语义以及边缘情况的全面测试。 ## 相关文档 {#related-docs} - [Agent 循环内部原理](agent-loop) - [ACP 内部原理](acp-internals) - [上下文压缩与提示缓存](context-compression-and-caching) --- ### 会话存储 { session storage} - URL: https://hermesagent.org.cn/docs/developer-guide/session-storage - Path: developer-guide/session-storage.md - Category: developer-guide - Description: Hermes Agent 使用 SQLite 数据库( /.hermes/state.db)来持久化会话元数据、完整消息历史记录以及模型配置,适用于 CLI 和网关会话。这取代了早期的每个会话使用 JSONL 文件的方法。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/session-storage.md - Translated At: 2026-04-11T03:24:34.155Z - Headings: 架构概览 | SQLite 模式 | Sessions 表 | Messages 表 | FTS5 全文搜索 | 模式版本与迁移 | 写入竞争处理 | 常见操作 | 初始化 | 创建和管理会话 | 存储消息 | 检索消息 # 会话存储 {#session-storage} Hermes Agent 使用 SQLite 数据库(`~/.hermes/state.db`)来持久化会话元数据、完整消息历史记录以及模型配置,适用于 CLI 和网关会话。这取代了早期的每个会话使用 JSONL 文件的方法。 源文件:`hermes_state.py` ## 架构概览 {#architecture-overview} ``` ~/.hermes/state.db (SQLite, WAL mode) ├── sessions — Session metadata, token counts, billing ├── messages — Full message history per session ├── messages_fts — FTS5 virtual table for full-text search └── schema_version — Single-row table tracking migration state ``` 关键设计决策: - **WAL 模式**:支持并发读取 + 单个写入者(网关多平台) - **FTS5 虚拟表**:在所有会话消息中实现快速文本搜索 - **会话血缘关系**:通过 `parent_session_id` 链(由上下文压缩触发的拆分) - **来源标签**(`cli`、`telegram`、`discord` 等):用于平台过滤 - 批处理运行器和强化学习轨迹 **不存储于此**(由独立系统管理) ## SQLite 模式 {#sqlite-schema} ### Sessions 表 {#sessions-table} ```sql CREATE TABLE IF NOT EXISTS sessions ( id TEXT PRIMARY KEY, source TEXT NOT NULL, user_id TEXT, model TEXT, model_config TEXT, system_prompt TEXT, parent_session_id TEXT, started_at REAL NOT NULL, ended_at REAL, end_reason TEXT, message_count INTEGER DEFAULT 0, tool_call_count INTEGER DEFAULT 0, input_tokens INTEGER DEFAULT 0, output_tokens INTEGER DEFAULT 0, cache_read_tokens INTEGER DEFAULT 0, cache_write_tokens INTEGER DEFAULT 0, reasoning_tokens INTEGER DEFAULT 0, billing_provider TEXT, billing_base_url TEXT, billing_mode TEXT, estimated_cost_usd REAL, actual_cost_usd REAL, cost_status TEXT, cost_source TEXT, pricing_version TEXT, title TEXT, FOREIGN KEY (parent_session_id) REFERENCES sessions(id) ); CREATE INDEX IF NOT EXISTS idx_sessions_source ON sessions(source); CREATE INDEX IF NOT EXISTS idx_sessions_parent ON sessions(parent_session_id); CREATE INDEX IF NOT EXISTS idx_sessions_started ON sessions(started_at DESC); CREATE UNIQUE INDEX IF NOT EXISTS idx_sessions_title_unique ON sessions(title) WHERE title IS NOT NULL; ``` ### Messages 表 {#messages-table} ```sql CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, session_id TEXT NOT NULL REFERENCES sessions(id), role TEXT NOT NULL, content TEXT, tool_call_id TEXT, tool_calls TEXT, tool_name TEXT, timestamp REAL NOT NULL, token_count INTEGER, finish_reason TEXT, reasoning TEXT, reasoning_details TEXT, codex_reasoning_items TEXT ); CREATE INDEX IF NOT EXISTS idx_messages_session ON messages(session_id, timestamp); ``` 备注: - `tool_calls` 以 JSON 字符串形式存储(工具调用对象的序列化列表) - `reasoning_details` 和 `codex_reasoning_items` 以 JSON 字符串形式存储 - `reasoning` 存储提供方暴露的原始推理文本 - 时间戳为 Unix 纪元浮点数(`time.time()`) ### FTS5 全文搜索 {#fts5-full-text-search} ```sql CREATE VIRTUAL TABLE IF NOT EXISTS messages_fts USING fts5( content, content=messages, content_rowid=id ); ``` FTS5 表通过三个触发器与 `messages` 表保持同步,这些触发器在 `messages` 表执行 INSERT、UPDATE 和 DELETE 操作时触发: ```sql CREATE TRIGGER IF NOT EXISTS messages_fts_insert AFTER INSERT ON messages BEGIN INSERT INTO messages_fts(rowid, content) VALUES (new.id, new.content); END; CREATE TRIGGER IF NOT EXISTS messages_fts_delete AFTER DELETE ON messages BEGIN INSERT INTO messages_fts(messages_fts, rowid, content) VALUES('delete', old.id, old.content); END; CREATE TRIGGER IF NOT EXISTS messages_fts_update AFTER UPDATE ON messages BEGIN INSERT INTO messages_fts(messages_fts, rowid, content) VALUES('delete', old.id, old.content); INSERT INTO messages_fts(rowid, content) VALUES (new.id, new.content); END; ``` ## 模式版本与迁移 {#schema-version-and-migrations} 当前模式版本:**6** `schema_version` 表存储一个整数。初始化时,`_init_schema()` 检查当前版本并按顺序应用迁移: | 版本 | 变更 | |------|------| | 1 | 初始模式(sessions、messages、FTS5) | | 2 | 在 messages 表中添加 `finish_reason` 列 | | 3 | 在 sessions 表中添加 `title` 列 | | 4 | 在 `title` 上添加唯一索引(允许 NULL,非 NULL 值必须唯一) | | 5 | 添加计费列:`cache_read_tokens`、`cache_write_tokens`、`reasoning_tokens`、`billing_provider`、`billing_base_url`、`billing_mode`、`estimated_cost_usd`、`actual_cost_usd`、`cost_status`、`cost_source`、`pricing_version` | | 6 | 在 messages 表中添加推理列:`reasoning`、`reasoning_details`、`codex_reasoning_items` | 每个迁移使用 `ALTER TABLE ADD COLUMN` 包裹在 try/except 中,以处理列已存在的情况(幂等性)。每次成功迁移后,版本号递增。 ## 写入竞争处理 {#write-contention-handling} 多个 hermes 进程(网关 + CLI 会话 + worktree Agent)共享一个 `state.db`。`SessionDB` 类通过以下方式处理写入竞争: - **短 SQLite 超时时间**(1 秒),而非默认的 30 秒 - **应用层重试**,带有随机抖动(20–150ms,最多 15 次重试) - **BEGIN IMMEDIATE** 事务,使锁竞争在事务开始时即被暴露 - **定期 WAL 检查点**:每成功写入 50 次执行一次(PASSIVE 模式) 这避免了“车队效应”——即 SQLite 的确定性内部退避机制导致所有竞争写入者在同一时间间隔重试。 ``` _WRITE_MAX_RETRIES = 15 _WRITE_RETRY_MIN_S = 0.020 # 20毫秒 _WRITE_RETRY_MAX_S = 0.150 # 150毫秒 _CHECKPOINT_EVERY_N_WRITES = 50 ``` ## 常见操作 {#common-operations} ### 初始化 {#initialize} ```python from hermes_state import SessionDB db = SessionDB() # 默认:`~/.hermes/state.db` db = SessionDB(db_path=Path("/tmp/test.db")) # 自定义路径 ``` ### 创建和管理会话 {#create-and-manage-sessions} ```python # 创建一个新的session db.create_session( session_id="sess_abc123", source="cli", model="anthropic/claude-sonnet-4.6", user_id="user_1", parent_session_id=None, # 或以前的 session ID 血统 ) # 结束一个session db.end_session("sess_abc123", end_reason="user_exit") # 重新打开一个session(清除ended_at/end_reason) db.reopen_session("sess_abc123") ``` ### 存储消息 {#store-messages} ```python msg_id = db.append_message( session_id="sess_abc123", role="assistant", content="Here's the answer...", tool_calls=[{"id": "call_1", "function": {"name": "terminal", "arguments": "{}"}}], token_count=150, finish_reason="stop", reasoning="Let me think about this...", ) ``` ### 检索消息 {#retrieve-messages} ```python # 包含所有元数据的原始消息 messages = db.get_messages("sess_abc123") # OpenAI 对话格式(用于 API 重放) conversation = db.get_messages_as_conversation("sess_abc123") # 返回:[{"role": "user", "content": "..."}, {"role": "assistant", ...}] ``` ### 会话标题 {#session-titles} ```python # 设置标题(在非NULL标题中必须是唯一的) db.set_session_title("sess_abc123", "Fix Docker Build") # 按头衔解析(返回血统中最新的) session_id = db.resolve_session_by_title("Fix Docker Build") # 自动生成谱系中的下一个头衔 next_title = db.get_next_title_in_lineage("Fix Docker Build") # 返回: "Fix Docker Build #2" ``` ## 全文搜索 {#full-text-search} `search_messages()` 方法支持 FTS5 查询语法,并对用户输入进行自动清理。 ### 基本搜索 {#basic-search} ```python results = db.search_messages("docker deployment") ``` ### FTS5 查询语法 {#fts5-query-syntax} | 语法 | 示例 | 含义 | |------|------|------| | 关键词 | `docker deployment` | 两个词同时匹配(隐式 AND) | | 引号短语 | `"exact phrase"` | 精确短语匹配 | | 布尔 OR | `docker OR kubernetes` | 任一词匹配 | | 布尔 NOT | `python NOT java` | 排除该词 | | 前缀匹配 | `deploy*` | 前缀匹配 | ### 过滤搜索 {#filtered-search} ```python # 只搜索 CLI sessions results = db.search_messages("error", source_filter=["cli"]) # 排除 gateway sessions results = db.search_messages("bug", exclude_sources=["telegram", "discord"]) # 仅搜索用户消息 results = db.search_messages("help", role_filter=["user"]) ``` ### 搜索结果格式 {#search-results-format} 每个结果包含: - `id`、`session_id`、`role`、`timestamp` - `snippet` — FTS5 生成的片段,包含 `>>>match<<<` 标记 - `context` — 匹配消息前后各一条消息(内容截断至 200 字符) - `source`、`model`、`session_started` — 来自父会话 `_sanitize_fts5_query()` 方法处理边缘情况: - 剥离不匹配的引号和特殊字符 - 将连字符词用引号包裹(`chat-send` → `"chat-send"`) - 移除悬空的布尔操作符(`hello AND` → `hello`) ## 会话血缘关系 {#session-lineage} 会话可通过 `parent_session_id` 形成链式结构。这发生在网关中上下文压缩触发会话拆分时。 ### 查询:查找会话血缘关系 {#query-find-session-lineage} ```sql -- 查找 session 的所有祖先 WITH RECURSIVE lineage AS ( SELECT * FROM sessions WHERE id = ? UNION ALL SELECT s.* FROM sessions s JOIN lineage l ON s.id = l.parent_session_id ) SELECT id, title, started_at, parent_session_id FROM lineage; -- 查找 session 的所有后代 WITH RECURSIVE descendants AS ( SELECT * FROM sessions WHERE id = ? UNION ALL SELECT s.* FROM sessions s JOIN descendants d ON s.parent_session_id = d.id ) SELECT id, title, started_at FROM descendants; ``` ### 查询:最近会话及预览 {#query-recent-sessions-with-preview} ```sql SELECT s.*, COALESCE( (SELECT SUBSTR(m.content, 1, 63) FROM messages m WHERE m.session_id = s.id AND m.role = 'user' AND m.content IS NOT NULL ORDER BY m.timestamp, m.id LIMIT 1), '' ) AS preview, COALESCE( (SELECT MAX(m2.timestamp) FROM messages m2 WHERE m2.session_id = s.id), s.started_at ) AS last_active FROM sessions s ORDER BY s.started_at DESC LIMIT 20; ``` ### 查询:令牌使用统计 {#query-token-usage-statistics} ```sql -- 按 model 总计 tokens SELECT model, COUNT(*) as session_count, SUM(input_tokens) as total_input, SUM(output_tokens) as total_output, SUM(estimated_cost_usd) as total_cost FROM sessions WHERE model IS NOT NULL GROUP BY model ORDER BY total_cost DESC; -- Sessions 使用率最高的 token SELECT id, title, model, input_tokens + output_tokens AS total_tokens, estimated_cost_usd FROM sessions ORDER BY total_tokens DESC LIMIT 10; ``` ## 导出与清理 {#export-and-cleanup} ```python # 导出带有消息的单个 session data = db.export_session("sess_abc123") # 将所有 sessions(带有消息)导出为字典列表 all_data = db.export_all(source="cli") # 删除旧的sessions(仅结束sessions) deleted_count = db.prune_sessions(older_than_days=90) deleted_count = db.prune_sessions(older_than_days=30, source="telegram") # 清除消息但保留 session 记录 db.clear_messages("sess_abc123") # 删除session和所有消息 db.delete_session("sess_abc123") ``` ## 数据库位置 {#database-location} 默认路径:`~/.hermes/state.db` 该路径由 `hermes_constants.get_hermes_home()` 解析得出,默认为 `~/.hermes/`,或由 `HERMES_HOME` 环境变量指定。 数据库文件、WAL 文件(`state.db-wal`)和共享内存文件(`state.db-shm`)均创建在同一个目录中。 --- ### 工具运行时 - URL: https://hermesagent.org.cn/docs/developer-guide/tools-runtime - Path: developer-guide/tools-runtime.md - Category: developer-guide - Description: 工具注册表、工具集、分派机制及终端环境的运行时行为 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/tools-runtime.md - Translated At: 2026-04-11T03:24:58.129Z - Headings: 工具注册模型 | registry.register() 的工作原理 | 发现: discover tools() | 工具可用性检查(check fn) | 工具集解析 | get tool definitions() 如何过滤工具 | 旧版工具集名称 | 分派 | 分派流程:模型 tool call → 处理程序执行 | 错误包装 | Agent 循环工具 | 异步桥接 # 工具运行时 {#tools-runtime} Hermes 工具是自注册函数,按工具集分组,并通过中央注册/分派系统执行。 主要文件: - `tools/registry.py` - `model_tools.py` - `toolsets.py` - `tools/terminal_tool.py` - `tools/environments/*` ## 工具注册模型 {#tool-registration-model} 每个工具模块在导入时调用 `registry.register(...)`。 `model_tools.py` 负责导入/发现工具模块,并构建模型使用的模式列表。 ### `registry.register()` 的工作原理 {#how-registryregister-works} `tools/` 目录中的每个工具文件在模块级别调用 `registry.register()` 以声明自身。函数签名如下: ```python registry.register( name="terminal", # 唯一的 tool 名称(在 API 模式中使用) toolset="terminal", # Toolset 这个tool 属于 schema={...}, # OpenAI 函数调用架构(描述、参数) handler=handle_terminal, # 调用工具时执行的函数 check_fn=check_terminal, # 可选:返回 True/False 表示是否可用 requires_env=["SOME_VAR"], # 可选:需要环境变量(用于 UI 显示) is_async=False, # 处理程序是否是异步协程 description="Run commands", # 人类可读的描述 emoji="💻", # 旋转器“0”显示的表情符号 ) ``` 每次调用都会创建一个 `ToolEntry`,存储在单例 `ToolRegistry._tools` 字典中,以工具名称为键。如果不同工具集中出现名称冲突,将记录警告信息,后注册的版本将覆盖先注册的版本。 ### 发现:`_discover_tools()` {#discovery-_discover_tools} 当 `model_tools.py` 被导入时,它会调用 `_discover_tools()`,按顺序导入所有工具模块: ```python _modules = [ "tools.web_tools", "tools.terminal_tool", "tools.file_tools", "tools.vision_tools", "tools.mixture_of_agents_tool", "tools.image_generation_tool", "tools.skills_tool", "tools.skill_manager_tool", "tools.browser_tool", "tools.cronjob_tools", "tools.rl_training_tool", "tools.tts_tool", "tools.todo_tool", "tools.memory_tool", "tools.session_search_tool", "tools.clarify_tool", "tools.code_execution_tool", "tools.delegate_tool", "tools.process_registry", "tools.send_message_tool", # "tools.honcho_tools", # 已删除 — Honcho 现在是 memory provider 插件 "tools.homeassistant_tool", ] ``` 每次导入都会触发模块中 `registry.register()` 的调用。对于可选工具(例如缺少 `fal_client` 时的图像生成),导入错误会被捕获并记录——这不会阻止其他工具的加载。 核心工具发现完成后,还会发现 MCP 工具和插件工具: 1. **MCP 工具** — `tools.mcp_tool.discover_mcp_tools()` 读取 MCP 服务器配置,并从外部服务器注册工具。 2. **插件工具** — `hermes_cli.plugins.discover_plugins()` 加载用户/项目/Pip 插件,这些插件可能注册额外的工具。 ## 工具可用性检查(`check_fn`) {#tool-availability-checking-check_fn} 每个工具可选择性地提供一个 `check_fn` —— 一个返回 `True` 表示工具可用、返回 `False` 表示不可用的可调用对象。典型的检查包括: - **API 密钥存在** —— 例如 `lambda: bool(os.environ.get("SERP_API_KEY"))` 用于网络搜索 - **服务正在运行** —— 例如检查 Honcho 服务器是否已配置 - **二进制已安装** —— 例如验证 `playwright` 是否可用于浏览器工具 当 `registry.get_definitions()` 为模型构建模式列表时,会运行每个工具的 `check_fn()`: ```python # 由 registry.py 简化而来 if entry.check_fn: try: available = bool(entry.check_fn()) except Exception: available = False # 例外=不可用 if not available: continue # 完全跳过这个 tool ``` 关键行为: - 检查结果是**按调用缓存的** —— 如果多个工具共享相同的 `check_fn`,它只会运行一次。 - `check_fn()` 中的异常被视为“不可用”(安全降级)。 - `is_toolset_available()` 方法用于检查工具集的 `check_fn` 是否通过,该方法用于 UI 显示和工具集解析。 ## 工具集解析 {#toolset-resolution} 工具集是工具的命名捆绑包。Hermes 通过以下方式解析它们: - 显式启用/禁用的工具集列表 - 平台预设(如 `hermes-cli`、`hermes-telegram` 等) - 动态 MCP 工具集 - 精心策划的专用工具集,如 `hermes-acp` ### `get_tool_definitions()` 如何过滤工具 {#how-get_tool_definitions-filters-tools} 主要入口点是 `model_tools.get_tool_definitions(enabled_toolsets, disabled_toolsets, quiet_mode)`: 1. **如果提供了 `enabled_toolsets`** —— 仅包含这些工具集中的工具。每个工具集名称通过 `resolve_toolset()` 解析,将复合工具集展开为单个工具名称。 2. **如果提供了 `disabled_toolsets`** —— 从**所有工具集**开始,然后减去被禁用的工具集。 3. **如果两者均未提供** —— 包含所有已知工具集。 4. **注册表过滤** —— 解析后的工具名称集合传递给 `registry.get_definitions()`,该函数应用 `check_fn` 过滤,并返回 OpenAI 格式的模式。 5. **动态模式修补** —— 过滤后,`execute_code` 和 `browser_navigate` 模式会动态调整,仅引用实际通过过滤的工具(防止模型幻觉出不可用的工具)。 ### 旧版工具集名称 {#legacy-toolset-names} 带有 `_tools` 后缀的旧版工具集名称(如 `web_tools`、`terminal_tools`)通过 `_LEGACY_TOOLSET_MAP` 映射到现代工具名称,以保证向后兼容。 ## 分派 {#dispatch} 运行时,工具通过中央注册表进行分派,但某些 Agent 层工具(如记忆/待办事项/会话搜索处理)除外。 ### 分派流程:模型 tool_call → 处理程序执行 {#dispatch-flow-model-tool_call-→-handler-execution} 当模型返回 `tool_call` 时,流程如下: ``` Model response with tool_call ↓ run_agent.py agent loop ↓ model_tools.handle_function_call(name, args, task_id, user_task) ↓ [Agent-loop tools?] → handled directly by agent loop (todo, memory, session_search, delegate_task) ↓ [Plugin pre-hook] → invoke_hook("pre_tool_call", ...) ↓ registry.dispatch(name, args, **kwargs) ↓ Look up ToolEntry by name ↓ [Async handler?] → bridge via _run_async() [Sync handler?] → call directly ↓ Return result string (or JSON error) ↓ [Plugin post-hook] → invoke_hook("post_tool_call", ...) ``` ### 错误包装 {#error-wrapping} 所有工具执行在两个层级上都进行了错误处理: 1. **`registry.dispatch()`** —— 捕获处理程序中的任何异常,并返回 `{"error": "Tool execution failed: ExceptionType: message"}` 作为 JSON。 2. **`handle_function_call()`** —— 将整个分派包装在二级 try/except 中,返回 `{"error": "Error executing tool_name: message"}`。 这确保模型始终接收到格式良好的 JSON 字符串,而不会收到未处理的异常。 ### Agent 循环工具 {#agent-loop-tools} 有四个工具在注册表分派前被拦截,因为它们需要 Agent 层状态(如 TodoStore、MemoryStore 等): - `todo` —— 规划/任务跟踪 - `memory` —— 持久化记忆写入 - `session_search` —— 跨会话回忆 - `delegate_task` —— 启动子 Agent 会话 这些工具的模式仍注册在注册表中(用于 `get_tool_definitions`),但如果分派意外到达它们,其处理程序将返回一个存根错误。 ### 异步桥接 {#async-bridging} 当工具处理器为异步时,`_run_async()` 会将其桥接到同步分发路径: - **CLI 路径(无运行中的事件循环)** —— 使用持久化事件循环,以保持缓存的异步客户端处于活跃状态 - **网关路径(正在运行的事件循环)** —— 使用 `asyncio.run()` 启动一个可丢弃的线程 - **工作线程(并行工具)** —— 使用存储在线程局部存储中的每线程持久化事件循环 ## DANGEROUS_PATTERNS 审批流程 {#the-dangerous_patterns-approval-flow} 终端工具集成了在 `tools/approval.py` 中定义的危险命令审批系统: 1. **模式检测** —— `DANGEROUS_PATTERNS` 是一组 `(正则表达式, 描述)` 元组,涵盖破坏性操作: - 递归删除(`rm -rf`) - 文件系统格式化(`mkfs`, `dd`) - SQL 破坏性操作(`DROP TABLE`,`DELETE FROM` 无 `WHERE` 子句) - 系统配置覆盖(`> /etc/`) - 服务操作(`systemctl stop`) - 远程代码执行(`curl | sh`) - 分叉炸弹、进程终止等 2. **检测** —— 在执行任何终端命令之前,`detect_dangerous_command(command)` 会与所有模式进行比对。 3. **审批提示** —— 若发现匹配项: - **CLI 模式** —— 交互式提示要求用户批准、拒绝或永久允许 - **网关模式** —— 异步审批回调将请求发送至消息平台 - **智能审批** —— 可选地,辅助 LLM 可自动批准低风险且匹配模式的命令(例如 `rm -rf node_modules/` 虽匹配“递归删除”模式,但属于安全操作) 4. **会话状态** —— 审批记录按会话进行。一旦在当前会话中批准了“递归删除”,后续的 `rm -rf` 命令将不再重复提示。 5. **永久白名单** —— “永久允许”选项会将该模式写入 `config.yaml` 的 `command_allowlist`,实现跨会话持久化。 ## 终端/运行时环境 {#terminalruntime-environments} 终端系统支持多种后端: - local - docker - ssh - singularity - modal - daytona 同时支持: - 每任务的 cwd 覆盖 - 后台进程管理 - PTY 模式 - 危险命令的审批回调 ## 并发性 {#concurrency} 工具调用可根据工具组合和交互需求,选择顺序执行或并发执行。 ## 相关文档 {#related-docs} - [Toolsets 参考](../reference/toolsets-reference) - [内置工具参考](../reference/tools-reference) - [Agent Loop 内部机制](agent-loop) - [ACP 内部机制](acp-internals) --- ### 轨迹格式 { trajectory format} - URL: https://hermesagent.org.cn/docs/developer-guide/trajectory-format - Path: developer-guide/trajectory-format.md - Category: developer-guide - Description: Hermes Agent 以 ShareGPT 兼容的 JSONL 格式保存对话轨迹,用于训练数据、调试工件以及强化学习数据集。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/trajectory-format.md - Translated At: 2026-04-11T03:24:53.362Z - Headings: 文件命名约定 | JSONL 条目格式 | CLI/交互式格式(来自 save trajectory) | 批处理运行器格式(来自 batch runner.py) | 对话数组(ShareGPT 格式) | 完整示例 | 归一化规则 | 推理内容标记 | 工具调用归一化 | 工具响应归一化 | 系统消息 | 加载轨迹 # 轨迹格式 {#trajectory-format} Hermes Agent 以 ShareGPT 兼容的 JSONL 格式保存对话轨迹,用于训练数据、调试工件以及强化学习数据集。 源文件:`agent/trajectory.py`、`run_agent.py`(搜索 `_save_trajectory`)、`batch_runner.py` ## 文件命名约定 {#file-naming-convention} 轨迹文件被写入当前工作目录: | 文件 | 触发时机 | |------|----------| | `trajectory_samples.jsonl` | 成功完成的对话(`completed=True`) | | `failed_trajectories.jsonl` | 失败或中断的对话(`completed=False`) | 批处理运行器(`batch_runner.py`)为每个批次写入自定义输出文件(例如 `batch_001_output.jsonl`),并包含额外的元数据字段。 可通过 `save_trajectory()` 中的 `filename` 参数覆盖文件名。 ## JSONL 条目格式 {#jsonl-entry-format} 文件中的每一行都是一个独立的 JSON 对象。存在两种变体: ### CLI/交互式格式(来自 `_save_trajectory`) {#cliinteractive-format-from-_save_trajectory} ```json { "conversations": [ ... ], "timestamp": "2026-03-30T14:22:31.456789", "model": "anthropic/claude-sonnet-4.6", "completed": true } ``` ### 批处理运行器格式(来自 `batch_runner.py`) {#batch-runner-format-from-batch_runnerpy} ```json { "prompt_index": 42, "conversations": [ ... ], "metadata": { "prompt_source": "gsm8k", "difficulty": "hard" }, "completed": true, "partial": false, "api_calls": 7, "toolsets_used": ["code_tools", "file_tools"], "tool_stats": { "terminal": {"count": 3, "success": 3, "failure": 0}, "read_file": {"count": 2, "success": 2, "failure": 0}, "write_file": {"count": 0, "success": 0, "failure": 0} }, "tool_error_counts": { "terminal": 0, "read_file": 0, "write_file": 0 } } ``` `tool_stats` 和 `tool_error_counts` 字典已归一化,包含所有可能的工具(来自 `model_tools.TOOL_TO_TOOLSET_MAP`),并以零值作为默认值,确保 HuggingFace 数据集加载时的模式一致性。 ## 对话数组(ShareGPT 格式) {#conversations-array-sharegpt-format} `conversations` 数组使用 ShareGPT 的角色约定: | API 角色 | ShareGPT `from` | |----------|-----------------| | system | `"system"` | | user | `"human"` | | assistant | `"gpt"` | | tool | `"tool"` | ### 完整示例 {#complete-example} ```json { "conversations": [ { "from": "system", "value": "You are a function calling AI model. You are provided with function signatures within XML tags. You may call one or more functions to assist with the user query. If available tools are not relevant in assisting with user query, just respond in natural conversational language. Don't make assumptions about what values to plug into functions. After calling & executing the functions, you will be provided with function results within XML tags. Here are the available tools:\n\n[{\"name\": \"terminal\", \"description\": \"Execute shell commands\", \"parameters\": {\"type\": \"object\", \"properties\": {\"command\": {\"type\": \"string\"}}}, \"required\": null}]\n\nFor each function call return a JSON object, with the following pydantic model json schema for each:\n{'title': 'FunctionCall', 'type': 'object', 'properties': {'name': {'title': 'Name', 'type': 'string'}, 'arguments': {'title': 'Arguments', 'type': 'object'}}, 'required': ['name', 'arguments']}\nEach function call should be enclosed within XML tags.\nExample:\n\n{'name': ,'arguments': }\n" }, { "from": "human", "value": "What Python version is installed?" }, { "from": "gpt", "value": "\nThe user wants to know the Python version. I should run python3 --version.\n\n\n{\"name\": \"terminal\", \"arguments\": {\"command\": \"python3 --version\"}}\n" }, { "from": "tool", "value": "\n{\"tool_call_id\": \"call_abc123\", \"name\": \"terminal\", \"content\": \"Python 3.11.6\"}\n" }, { "from": "gpt", "value": "\nGot the version. I can now answer the user.\n\nPython 3.11.6 is installed on this system." } ], "timestamp": "2026-03-30T14:22:31.456789", "model": "anthropic/claude-sonnet-4.6", "completed": true } ``` ## 归一化规则 {#normalization-rules} ### 推理内容标记 {#reasoning-content-markup} 轨迹转换器将所有推理内容统一归一化为 `` 标签,无论模型原始生成方式如何: 1. **原生思考令牌**(来自 Anthropic、OpenAI o 系列等 Provider 的 `msg["reasoning"]` 字段):包裹为 `\n{reasoning}\n\n`,并前置到内容之前。 2. **REASONING_SCRATCHPAD XML**(当禁用原生思考且模型通过 System Prompt 指定的 XML 进行推理时):通过 `convert_scratchpad_to_think()` 将 `` 标签转换为 ``。 3. **空 think 块**:每个 `gpt` 轮次都保证包含一个 `` 块。若未生成推理内容,则插入空块:`\n\n` —— 这确保了训练数据格式的一致性。 ### 工具调用归一化 {#tool-call-normalization} API 格式中的工具调用(包含 `tool_call_id`、函数名、参数作为 JSON 字符串)被转换为 XML 包裹的 JSON: ``` {"name": "terminal", "arguments": {"command": "ls -la"}} ``` - 参数从 JSON 字符串解析回对象(不进行双重编码) - 若 JSON 解析失败(理论上不应发生——对话期间已验证),则使用空 `{}` 并记录警告 - 一个助手回合中包含多个工具调用时,会在单个 `gpt` 消息中生成多个 `` 块 ### 工具响应归一化 {#tool-response-normalization} 所有在助手消息之后的工具结果都会合并为单个 `tool` 轮次,并以 XML 包裹的 JSON 响应形式呈现: ``` {"tool_call_id": "call_abc123", "name": "terminal", "content": "output here"} ``` - 若工具内容看起来像 JSON(以 `{` 或 `[` 开头),则解析为对象/数组,而非字符串 - 多个工具结果通过换行符连接在一条消息中 - 工具名称通过与父级助手的 `tool_calls` 数组位置匹配 ### 系统消息 {#system-message} 系统消息在保存时生成(而非从对话中获取)。它遵循 Hermes 函数调用提示模板,包含: - 说明函数调用协议的前言 - 包含 JSON 工具定义的 `` XML 块 - `FunctionCall` 对象的模式引用 - `` 示例 工具定义包含 `name`、`description`、`parameters` 和 `required`(设为 `null` 以匹配标准格式)。 ## 加载轨迹 {#loading-trajectories} 轨迹为标准 JSONL 格式——可使用任意 JSON 行读取器加载: ```python import json def load_trajectories(path: str): """Load trajectory entries from a JSONL file.""" entries = [] with open(path, "r", encoding="utf-8") as f: for line in f: line = line.strip() if line: entries.append(json.loads(line)) return entries # 仅筛选成功完成的情况 successful = [e for e in load_trajectories("trajectory_samples.jsonl") if e.get("completed")] # 仅提取对话进行训练 training_data = [e["conversations"] for e in successful] ``` ### 用于 HuggingFace 数据集的加载 {#loading-for-huggingface-datasets} ```python from datasets import load_dataset ds = load_dataset("json", data_files="trajectory_samples.jsonl") ``` 归一化的 `tool_stats` 模式确保所有条目具有相同的列,防止数据集加载时出现 Arrow 模式不匹配错误。 ## 控制轨迹保存 {#controlling-trajectory-saving} 在 CLI 中,轨迹保存由以下方式控制: ```yaml # config.yaml agent: save_trajectories: true # 默认值:假 ``` 或通过 `--save-trajectories` 标志。当 Agent 初始化时设置 `save_trajectories=True`,将在每个对话回合结束时调用 `_save_trajectory()` 方法。 批处理运行器始终保存轨迹(这是其主要目的)。 批处理运行器会自动丢弃所有回合中均无推理内容的样本,以避免非推理示例污染训练数据。 --- ### 视频生成提供商插件 - URL: https://hermesagent.org.cn/docs/developer-guide/video-gen-provider-plugin - Path: developer-guide/video-gen-provider-plugin.md - Category: developer-guide - Description: 如何为 Hermes Agent 构建视频生成后端插件 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/video-gen-provider-plugin.md - Translated At: 2026-06-16T00:43:16.783Z - Headings: 统一接口(一个工具,两种模态) | 发现机制如何工作 | 目录结构 | VideoGenProvider 抽象基类 | 插件清单 | video generate 模式 | 模型系列和端点路由(FAL 模式) | 选择优先级 | 响应结构 | 保存工件的位置 | 测试 # 构建视频生成提供商插件 {#building-a-video-generation-provider-plugin} 视频生成(video-gen)提供商插件注册一个后端,用于服务每次 `video_generate` 工具调用。内置提供商(xAI、FAL)作为插件提供。通过将目录放入 `plugins/video_gen//` 中,可以添加新的提供商或覆盖捆绑的提供商。 :::tip 视频生成几乎逐行镜像了[图像生成提供商插件](/docs/developer-guide/image-gen-provider-plugin)——如果你已经构建过图像生成后端,你就已经了解了其结构。主要区别在于:一个用于宣传模态/宽高比/时长的 `capabilities()` 方法,以及一种路由约定(传递 `image_url` 以使用图生视频,省略它以使用文生视频——提供商在内部选择正确的端点)。 ::: ## 统一接口(一个工具,两种模态) {#the-unified-surface-one-tool-two-modalities} `video_generate` 工具通过一个参数暴露两种模态: - **文生视频** — 仅使用 `prompt` 调用。提供商将其路由到文生视频端点。 - **图生视频** — 使用 `prompt` + `image_url` 调用。提供商将其路由到图生视频端点。 编辑和扩展功能故意不在范围内。大多数后端不支持这些功能,且这种不一致性会迫使代理的工具描述中包含针对每个后端的说明文字。 ## 发现机制如何工作 {#how-discovery-works} Hermes 在三个位置扫描视频生成后端: 1. **捆绑** — `/plugins/video_gen//`(随 `kind: backend` 自动加载) 2. **用户** — `~/.hermes/plugins/video_gen//`(通过 `plugins.enabled` 启用) 3. **Pip** — 声明了 `hermes_agent.plugins` 入口点的包 每个插件的 `register(ctx)` 函数调用 `ctx.register_video_gen_provider(...)`。活动提供商由 `config.yaml` 中的 `video_gen.provider` 选定;`hermes tools` → Video Generation 会引导用户进行选择。与 `image_generate` 不同,代码库中没有遗留的后端——每个提供商都是一个插件。 ## 目录结构 {#directory-structure} ``` plugins/video_gen/my-backend/ ├── __init__.py # VideoGenProvider subclass + register() └── plugin.yaml # Manifest with kind: backend ``` ## VideoGenProvider 抽象基类 {#the-videogenprovider-abc} 子类化 `agent.video_gen_provider.VideoGenProvider`。必需项:`name` 属性和 `generate()` 方法。 ```python # plugins/video_gen/my-backend/__init__.py from typing import Any, Dict, List, Optional import os from agent.video_gen_provider import ( VideoGenProvider, error_response, success_response, ) class MyVideoGenProvider(VideoGenProvider): @property def name(self) -> str: return "my-backend" @property def display_name(self) -> str: return "My Backend" def is_available(self) -> bool: return bool(os.environ.get("MY_API_KEY")) def list_models(self) -> List[Dict[str, Any]]: # Each entry is a model FAMILY — a name the user picks once. # Your provider's generate() routes within the family based on # whether image_url was passed. return [ { "id": "fast", "display": "Fast", "speed": "~30s", "strengths": "Cheapest tier", "price": "$0.05/s", "modalities": ["text", "image"], # advisory }, ] def default_model(self) -> Optional[str]: return "fast" def capabilities(self) -> Dict[str, Any]: return { "modalities": ["text", "image"], "aspect_ratios": ["16:9", "9:16"], "resolutions": ["720p", "1080p"], "min_duration": 1, "max_duration": 10, "supports_audio": False, "supports_negative_prompt": True, "max_reference_images": 0, } def get_setup_schema(self) -> Dict[str, Any]: return { "name": "My Backend", "badge": "paid", "tag": "Short description shown in `hermes tools`", "env_vars": [ { "key": "MY_API_KEY", "prompt": "My Backend API key", "url": "https://mybackend.example.com/keys", }, ], } def generate( self, prompt: str, *, model: Optional[str] = None, image_url: Optional[str] = None, reference_image_urls: Optional[List[str]] = None, duration: Optional[int] = None, aspect_ratio: str = "16:9", resolution: str = "720p", negative_prompt: Optional[str] = None, audio: Optional[bool] = None, seed: Optional[int] = None, **kwargs: Any, # always ignore unknown kwargs for forward-compat ) -> Dict[str, Any]: # ROUTE: image_url presence picks the endpoint. if image_url: endpoint = "my-backend/image-to-video" modality_used = "image" else: endpoint = "my-backend/text-to-video" modality_used = "text" # ... call your API ... return success_response( video="https://your-cdn/output.mp4", model=model or "fast", prompt=prompt, modality=modality_used, aspect_ratio=aspect_ratio, duration=duration or 5, provider=self.name, ) def register(ctx) -> None: ctx.register_video_gen_provider(MyVideoGenProvider()) ``` ## 插件清单 {#the-plugin-manifest} ```yaml # plugins/video_gen/my-backend/plugin.yaml name: my-backend version: 1.0.0 description: "My video generation backend" author: Your Name kind: backend requires_env: - MY_API_KEY ``` ## `video_generate` 模式 {#the-video_generate-schema} 该工具在所有后端之间暴露统一的模式。提供商忽略其不支持的参数。 | 参数 | 作用 | |---|---| | `prompt` | 文本指令(必需) | | `image_url` | 设置时 → 图生视频;省略时 → 文生视频 | | `reference_image_urls` | 风格/角色参考(取决于提供商) | | `duration` | 秒数——由提供商限制范围 | | `aspect_ratio` | `"16:9"`、`"9:16"`、`"1:1"` 等——由提供商限制范围 | | `resolution` | `"480p"` / `"540p"` / `"720p"` / `"1080p"`——由提供商限制范围 | | `negative_prompt` | 要避免的内容(仅限 Pixverse/Kling) | | `audio` | 原生音频(Veo3 / Pixverse 定价层级) | | `seed` | 可复现性 | | `model` | 覆盖活动模型/系列 | 提供商的 `capabilities()` 会宣传哪些参数受支持。代理在工具描述中看到活动后端的功能,当用户通过 `hermes tools` 更改后端时,这些功能会动态重建。 ## 模型系列和端点路由(FAL 模式) {#model-families-and-endpoint-routing-the-fal-pattern} 当你的后端每个“模型”有多个端点时——例如 FAL,其中每个系列(Veo 3.1、Pixverse v6、Kling O3)都有 `/text-to-video` 和 `/image-to-video` URL——将每个**系列**表示为一个目录条目。你的 `generate()` 根据是否传递了 `image_url` 来选择正确的端点: ```python FAMILIES = { "veo3.1": { "text_endpoint": "fal-ai/veo3.1", "image_endpoint": "fal-ai/veo3.1/image-to-video", # ... family-specific capability flags ... }, } def generate(self, prompt, *, image_url=None, model=None, **kwargs): family_id, family = _resolve_family(model) endpoint = family["image_endpoint"] if image_url else family["text_endpoint"] # ... build payload from family's declared capability flags, call endpoint ... ``` 用户在 `hermes tools` 中选择一次 `veo3.1`。代理从不考虑端点——它只是传递(或不传递)`image_url`。 ## 选择优先级 {#selection-precedence} 对于每个实例的模型调节参数(参见 `plugins/video_gen/fal/__init__.py`): 1. 工具调用中的 `model=` 关键字 2. `_VIDEO_MODEL` 环境变量 3. `config.yaml` 中的 `video_gen..model` 4. `config.yaml` 中的 `video_gen.model`(当它是你的 ID 之一时) 5. 提供商的 `default_model()` ## 响应结构 {#response-shape} `success_response()` 和 `error_response()` 生成每个后端返回的字典结构。请使用它们——不要手动构建字典。 成功键:`success`、`video`(URL 或绝对路径)、`model`、`prompt`、`modality`(`"text"` 或 `"image"`)、`aspect_ratio`、`duration`、`provider`,以及 `extra`。 错误键:`success`、`video`(None)、`error`、`error_type`、`model`、`prompt`、`aspect_ratio`、`provider`。 ## 保存工件的位置 {#where-to-save-artifacts} 如果你的后端返回 base64,请使用 `save_b64_video()` 写入 `$HERMES_HOME/cache/videos/` 下。对于来自后续 HTTP 获取的原始字节,请使用 `save_bytes_video()`。否则直接返回上游 URL——网关会在交付时解析远程 URL。 ## 测试 {#testing} 将冒烟测试放入 `tests/plugins/video_gen/test__plugin.py`。xAI 和 FAL 测试展示了模式——注册、验证目录、在有和没有 `image_url` 的情况下练习路由、断言在缺少身份验证时的干净错误响应。 --- ### 网络搜索提供商插件 - URL: https://hermesagent.org.cn/docs/developer-guide/web-search-provider-plugin - Path: developer-guide/web-search-provider-plugin.md - Category: developer-guide - Description: 如何为 Hermes Agent 构建网页搜索/提取/爬取后端插件 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/developer-guide/web-search-provider-plugin.md - Translated At: 2026-06-16T00:43:32.813Z - Headings: 发现机制的工作原理 | 目录结构 | WebSearchProvider 抽象基类 (ABC) | plugin.yaml | ABC 参考 | 响应结构 | 能力标志 | Hermes 如何将其接入工具 | 懒安装可选依赖项 | 参考实现 | 通过 pip 分发 | 相关页面 # 构建 Web 搜索提供商插件 {#building-a-web-search-provider-plugin} Web 搜索提供商插件注册一个后端,用于处理 `web_search`、`web_extract` 以及(可选的)深度爬取工具调用。内置提供商——Firecrawl、SearXNG、Tavily、Exa、Parallel、Brave Search(免费层)、xAI 和 DDGS——均作为插件位于 `plugins/web//` 下。你可以通过在它们旁边放置一个目录来添加新的提供商,或覆盖 bundled 的提供商。 :::tip Web 搜索是 Hermes 支持的几种**后端插件**之一。其他插件(拥有各自的抽象基类 ABC)包括 [图像生成提供商插件](/docs/developer-guide/image-gen-provider-plugin)、[视频生成提供商插件](/docs/developer-guide/video-gen-provider-plugin)、[记忆提供商插件](/docs/developer-guide/memory-provider-plugin)、[上下文引擎插件](/docs/developer-guide/context-engine-plugin) 和 [模型提供商插件](/docs/developer-guide/model-provider-plugin)。通用的工具/hook/CLI 插件请参阅 [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin)。 ::: ## 发现机制的工作原理 {#how-discovery-works} Hermes 会在以下三个位置扫描 Web 搜索后端: 1. **Bundled(内置)** — `/plugins/web//`(随 `kind: backend` 自动加载,始终可用) 2. **User(用户)** — `~/.hermes/plugins/web//`(通过 `plugins.enabled` 或 `hermes plugins enable ` 选择启用) 3. **Pip** — 声明了 `hermes_agent.plugins` 入口点的包 每个插件的 `register(ctx)` 函数都会调用 `ctx.register_web_search_provider(...)`——这会将实例放入 `agent/web_search_registry.py` 中的注册表。每种能力的活动提供商由配置决定: | 能力 | 配置键 | 回退至 | |---|---|---| | `web_search` | `web.search_backend` | `web.backend` | | `web_extract` | `web.extract_backend` | `web.backend` | | `web_extract` 内的深度爬取模式 | `web.extract_backend` | `web.backend` | 当两个键均未设置时,Hermes 会根据环境中存在的 API 密钥/URL 自动检测后端。`hermes tools` 会引导用户进行选择。 ## 目录结构 {#directory-structure} ``` plugins/web/my-backend/ ├── __init__.py # register() entry point ├── provider.py # WebSearchProvider subclass └── plugin.yaml # Manifest with kind: backend and provides_web_providers ``` `brave_free/` 和 `ddgs/` 是代码库中最小的参考示例——`brave_free` 是一个需要 API 密钥且仅支持搜索的提供商,`ddgs` 是一个无需密钥且会懒安装其 SDK 的提供商。 ## WebSearchProvider 抽象基类 (ABC) {#the-websearchprovider-abc} 继承 `agent.web_search_provider.WebSearchProvider`。唯一必需的成员是 `name`、`is_available()`,以及你实现的 `search()` 或 `extract()` 中的任意一个。(深度爬取不是一个单独的方法——它是 `extract()` 的一种模式。) ```python # plugins/web/my-backend/provider.py from __future__ import annotations import os from typing import Any, Dict, List from agent.web_search_provider import WebSearchProvider class MyBackendWebSearchProvider(WebSearchProvider): """Minimal search-only provider against the My Backend HTTP API.""" @property def name(self) -> str: # Stable id used in web.search_backend / web.extract_backend / web.backend # config keys. Lowercase, no spaces; hyphens permitted. return "my-backend" @property def display_name(self) -> str: # Human label shown in `hermes tools`. Defaults to `name`. return "My Backend" def is_available(self) -> bool: # Cheap check — env var present, optional dep importable, etc. # MUST NOT make network calls (runs on every `hermes tools` paint). return bool(os.getenv("MY_BACKEND_API_KEY", "").strip()) def supports_search(self) -> bool: return True def supports_extract(self) -> bool: return False def search(self, query: str, limit: int = 5) -> Dict[str, Any]: import httpx api_key = os.environ["MY_BACKEND_API_KEY"] try: resp = httpx.get( "https://api.example.com/search", params={"q": query, "count": max(1, min(int(limit), 20))}, headers={"Authorization": f"Bearer {api_key}"}, timeout=15, ) resp.raise_for_status() data = resp.json() except httpx.HTTPError as exc: return {"success": False, "error": str(exc)} # Response shape is fixed — see "Response shape" below. return { "success": True, "data": { "web": [ { "title": item.get("title", ""), "url": item.get("url", ""), "description": item.get("snippet", ""), "position": idx + 1, } for idx, item in enumerate(data.get("results", [])) ], }, } ``` ```python # plugins/web/my-backend/__init__.py from plugins.web.my_backend.provider import MyBackendWebSearchProvider def register(ctx) -> None: """Plugin entry point — called once at load time.""" ctx.register_web_search_provider(MyBackendWebSearchProvider()) ``` ## plugin.yaml {#pluginyaml} ```yaml name: web-my-backend version: 1.0.0 description: "My Backend web search — Bearer-auth REST API" author: Your Name kind: backend provides_web_providers: - my-backend requires_env: - MY_BACKEND_API_KEY ``` | 键 | 用途 | |---|---| | `kind: backend` | 将插件路由到后端加载路径 | | `provides_web_providers` | 此插件注册的提供商 `name` 列表——加载器使用它在 `register()` 运行之前在 `hermes tools` 中宣传该插件 | | `requires_env` | 在 `hermes plugins install` 期间交互式提示凭证(参见 [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin#gate-on-environment-variables) 了解丰富格式) | ## ABC 参考 {#abc-reference} 完整契约位于 `agent/web_search_provider.py`。你可以重写的方法: | 成员 | 必需 | 默认值 | 用途 | |---|---|---|---| | `name` | ✅ | — | 在 `web.*_backend` 配置中使用的稳定 ID | | `display_name` | — | `name` | 在 `hermes tools` 中显示的标签 | | `is_available()` | ✅ | — | 轻量级的可用性检查——环境变量、可选依赖 | | `supports_search()` | — | `True` | `web_search` 路由的能力标志 | | `supports_extract()` | — | `False` | `web_extract` 路由的能力标志 | | `search(query, limit)` | 条件性 | 抛出异常 | 当 `supports_search()` 返回 `True` 时为必需 | | `extract(urls, **kwargs)` | 条件性 | 抛出异常 | 当 `supports_extract()` 返回 `True` 时为必需 | 提供商可以从单个类中宣传多种能力——Firecrawl、Tavily、Exa 和 Parallel 都同时实现了搜索和提取。Brave Search 和 DDGS 仅支持搜索;SearXNG 仅支持搜索,并有文档记录的“与提取提供商配对”工作流。 ## 响应结构 {#response-shape} 工具包装器期望一个固定的信封结构,以便无需在后端之间进行转换。 **搜索成功:** ```python { "success": True, "data": { "web": [ {"title": str, "url": str, "description": str, "position": int}, ... ], }, } ``` **提取成功:** ```python { "success": True, "data": [ { "url": str, "title": str, "content": str, "raw_content": str, "metadata": dict, # optional "error": str, # optional, only on per-URL failure }, ... ], } ``` **任一能力,失败时:** ```python {"success": False, "error": "human-readable message"} ``` `search()` 和 `extract()` 都可以是 `async def`——调度程序通过 `inspect.iscoroutinefunction` 检测协程函数并相应地 await。执行阻塞 I/O(HTTP、SDK 调用)的同步实现对于小型后端来说是可以接受的;调度程序会处理线程问题。 ## 能力标志 {#capability-flags} Hermes 根据 `supports_*` 标志将调用路由到正确的提供商。常见的多提供商设置: ```yaml # ~/.hermes/config.yaml web: search_backend: "brave-free" # search-only, fast, free 2k/mo extract_backend: "firecrawl" # extract + crawl, paid quota ``` 当未设置 `web.search_backend` 或 `web.extract_backend` 时,两者都会回退到 `web.backend`。当后者也未设置时,Hermes 会根据环境变量的存在情况,选择第一个支持所请求能力的可用提供商。 如果你的提供商仅支持一种能力,请将其他标志保留为默认值(`False`),注册表将针对该工具跳过这些能力——当用户仅使用 X 进行搜索并要求代理执行提取时,不会看到误导性的“provider X failed”错误。 ## Hermes 如何将其接入工具 {#how-hermes-wires-it-into-the-tools} `web_search` 和 `web_extract` 工具位于 `tools/web_tools.py` 中。在调用时,它们会: 1. 读取相关的配置键(`web_search` 对应 `web.search_backend`,`web_extract` 对应 `web.extract_backend`) 2. 向注册表请求具有该 `name` 的提供商 3. 检查 `is_available()` 和匹配的 `supports_*()` 标志 4. 分派到 `search()` / `extract()`(深度爬取作为 `extract()` 内部的一种模式运行),如果方法是协程则进行 await 5. 对响应信封进行 JSON 序列化并将其返回给 LLM 错误会作为工具结果呈现;由 LLM 决定如何解释这些错误。如果没有注册提供商(或者所有可用的提供商都未通过能力检查),工具将返回一个指向 `hermes tools` 的帮助性错误。 ## 懒安装可选依赖项 {#lazy-installing-optional-dependencies} 如果你的提供商封装了第三方 SDK(例如 DDGS 使用 `ddgs` 包),不要在模块顶层 `import` 它。请在 `is_available()` 或 `search()` 中使用 `tools.lazy_deps.ensure(...)` —— Hermes 将在首次使用时安装该包,并受 `security.allow_lazy_installs` 控制。有关安全模型,请参阅 [构建 Hermes 插件 → 懒安装](/docs/guides/build-a-hermes-plugin)。 ## 参考实现 {#reference-implementations} - **`plugins/web/brave_free/`** — 小型、需 API 密钥、仅支持搜索的 HTTP 提供商。良好的起始模板。 - **`plugins/web/ddgs/`** — 无需密钥且懒安装其 SDK 的提供商。对于封装 Python 包的后端而言,这是一种有用的模式。 - **`plugins/web/firecrawl/`** — 功能完整的多能力提供商(搜索 + 提取 + 爬取),支持多种格式模式。 - **`plugins/web/searxng/`** — 自托管、通过 URL 配置且无需认证的后端。 - **`plugins/web/xai/`** — 通过 Grok 的服务端 `web_search` 工具实现的基于 LLM 的搜索。展示了如何复用现有的 OAuth/环境变量凭据表面(`tools/xai_http.py`)而无需添加新的环境变量,以及如何编写遵守无网络契约的低成本 `is_available()`。 ## 通过 pip 分发 {#distribute-via-pip} ```toml # pyproject.toml [project.entry-points."hermes_agent.plugins"] my-backend-web = "my_backend_web_package" ``` `my_backend_web_package` 必须暴露一个顶层的 `register` 函数。完整设置请参阅通用插件指南中的 [通过 pip 分发](/docs/guides/build-a-hermes-plugin#distribute-via-pip)。 ## 相关页面 {#related-pages} - [网页搜索](/docs/user-guide/features/web-search) — 面向用户的功能文档和各后端配置 - [插件概览](/docs/user-guide/features/plugins) — 所有插件类型一览 - [构建 Hermes 插件](/docs/guides/build-a-hermes-plugin) — 通用工具/hooks/斜杠命令指南 --- ### 安装 - URL: https://hermesagent.org.cn/docs/getting-started/installation - Path: getting-started/installation.md - Category: getting-started - Description: 在 Linux、macOS、Windows(PowerShell / WSL2)或 Android 上安装 Hermes Agent - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/getting-started/installation.md - Translated At: 2026-04-11T03:25:13.730Z - Headings: 快速安装 | 类 Linux / macOS / WSL2 | Windows 原生 PowerShell | PowerShell 直装小白步骤 | Android / Termux | 安装程序执行的操作 | 安装后操作 | 类 Unix / WSL2 | Windows PowerShell | 先决条件 | 手动安装 | 步骤 1:克隆仓库 # 安装 {#installation} :::tip 安装遇到困难? 点击加入 [中文社区微信群](/community),提问并获取群内专家帮助。 **完全没有经验?** 强烈建议先下载 [WorkBuddy](https://www.workbuddy.cn/)(微信扫码即用,无需任何配置),然后让它安装中文社区文档 MCP 来协助你安装 Hermes Agent。如果后续 Hermes 出现问题,也可以让 WorkBuddy 对其进行修复,反之亦然——两个 Agent 互为主备,这是社区推荐的最佳方案。 **电脑上已经有 Agent?** 如果你已经在用龙虾 [OpenClaw](https://github.com/openclaw/openclaw) 或国内版本([QClaw](https://qclaw.qq.com/)、[AutoClaw](https://autoglm.zhipuai.cn/autoclaw/)),或者 [Trae](https://www.trae.ai/)、[Claude Code](https://claude.ai/code)、[Codex](https://openai.com/index/introducing-codex/)、[Cursor](https://www.cursor.com/)、[Qoder](https://qoder.ai/) 等 Coding Agent,都可以让它读文档来协助你完成安装,你可以不用关心任何技术细节。 **如何让你的 Agent 接入中文社区文档?** - **方式一(最简单)**:把中文社区网址 [https://hermesagent.org.cn](https://hermesagent.org.cn) 发给它,让它自己访问并阅读文档。 - **方式二(更精准,推荐)**:直接把下面这段话复制发给你的 Agent,它会自己完成配置: ```agent-prompt 请把这个 Hermes 中文文档 MCP server 加到你的配置里: https://mcp.hermesagent.org.cn/v1 (Streamable HTTP,无需 API Key、无需登录) 加完后用它帮我查 Hermes Agent 中文文档来指导我完成安装。 ``` - 方式二配好后,Agent 就能按关键词直接检索并读取中文社区全部文档的全文。 **其他求助途径**:也可以先询问 [豆包](https://www.doubao.com/)、[DeepSeek](https://chat.deepseek.com/) 等 AI 助手。 ::: Hermes Agent 现在已经有 **类 Unix 安装路径** 和 **Windows 安装路径** 两套方案。 如果你是 Windows 用户,可以先把 **WSL2** 理解成: - 一个运行在 Windows 里的 Linux 环境 - 安装后你会在开始菜单里看到一个 **Ubuntu** 之类的终端 - 你可以继续日常使用 Windows,但在这个 Ubuntu 终端里执行 Linux 命令 对 Hermes Agent 来说,WSL2 的意义是:**提供一个类 Unix 工作流选项**。不过现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以直接在 Windows PowerShell 中原生安装和使用。 - **Windows 原生 PowerShell**:使用中文社区维护的镜像版 `install.ps1`,优先走国内可直连链路,适合大多数希望直接在 Windows 本机使用 Hermes Agent 的用户。 - **Linux / macOS / WSL2**:使用镜像版 `install.sh`,适合类 Unix 系统,或偏好 Ubuntu / Linux 终端工作流的 Windows 用户。 - **Android / Termux**:使用专门的移动端安装路径。 如果你主要在 Windows 上使用,建议先阅读 **[Windows 安装指南](windows-installation)**,里面把原生 PowerShell、WSL2、飞书接入和常见坑都拆开说明了。 ## 快速安装 {#quick-install} ### 类 Linux / macOS / WSL2 {#linux-macos-wsl2} ```bash curl -fsSL https://res1.hermesagent.org.cn/install.sh | bash ``` 适合: - Linux 桌面 / 服务器 - macOS - Windows + WSL2(适合偏好 Linux / Ubuntu 终端的 Windows 用户) ### Windows 原生 PowerShell {#windows-powershell} ```powershell irm https://res1.hermesagent.org.cn/install.ps1 | iex ``` 如果你完全不熟悉 Windows 命令行,先记住这三件事: 1. **PowerShell 是什么?** 它是 Windows 自带的命令行程序,可以理解成“Windows 里的终端”。 2. **怎么打开?** 按键盘左下角 **Windows 键**,输入 `PowerShell`,点击 **Windows PowerShell** 或 **PowerShell** 即可。 3. **在哪里粘贴命令?** 就粘贴到 PowerShell 窗口里。**不要**粘贴到浏览器地址栏、文件资源管理器地址栏,或“运行”对话框里。 适合: - 想在 Windows 本机直接安装和长期使用 Hermes Agent - 不想先配置 WSL2 的用户 ### PowerShell 直装小白步骤 {#powershell-beginner-steps} 如果你想直接在 Windows 本机安装,可以按下面这套最短步骤来: 1. 按一下 **Windows 键** 2. 输入 `PowerShell` 3. 点击 **Windows PowerShell** 或 **PowerShell** 4. 把下面这行命令完整复制进去: ```powershell irm https://res1.hermesagent.org.cn/install.ps1 | iex ``` 5. 在 PowerShell 窗口里粘贴并按回车 6. 等安装器自己跑完 7. **关闭当前 PowerShell 窗口** 8. 再重新打开一个新的 PowerShell 9. 输入: ```powershell hermes ``` 如果这时能正常进入 Hermes,说明安装已经成功。 :::tip 什么时候需要“管理员 PowerShell”? - **安装 WSL2** 时,通常需要管理员 PowerShell。 - **直接安装 Hermes** 时,一般用普通 PowerShell 就可以,不需要管理员权限。 ::: :::warning 如果窗口一闪而过,通常是打开方式不对 最常见的原因是: - 你把命令输到了别的地方,不是在 PowerShell 里执行 - 你双击了某个 `.ps1` 文件,导致窗口执行完立即关闭 - 你打开的是别的终端程序,但没有进入 PowerShell 标签页 最稳的方式还是:**开始菜单搜索 `PowerShell` → 打开 → 粘贴命令 → 回车**。 ::: :::tip Windows 用户怎么选? - **想在 Windows 本机直接使用**:运行上面的 `install.ps1`。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以原生安装了。 - **偏好 Linux / Ubuntu 终端工作流**:先装 [WSL2](https://zhuanlan.zhihu.com/p/466001838),再在 WSL2 里运行 `install.sh`。 - 如果你看到的是 bash 命令,请不要粘贴到原生 PowerShell;如果你在 PowerShell 中安装,请使用 `install.ps1`。 ::: :::tip 中国大陆网络环境提示 当前页面提供的安装命令已经由 **Hermes Agent 中文社区** 接入了 **国内镜像加速**,会优先使用国内可直连的下载链路。 为了提高中国大陆用户的安装体验,镜像版安装器默认精简了部分国人不常用、或体积较大且经常受外网影响的可选功能,例如浏览器自动化、Chromium 下载、WhatsApp 桥接等。建议先完成核心安装,确认 Hermes Agent 可以正常运行;之后可让 Hermes Agent 自身补全这些能力。 如果你仍然需要处理 WSL 网络、终端代理或手动镜像配置,可参考这些链接: - **WSL 安装(中文)**:[Windows 10/11 安装 WSL2 指南](https://zhuanlan.zhihu.com/p/466001838) - **WSL 网络 / autoProxy(官方)**:[Microsoft Learn - Accessing network applications with WSL](https://learn.microsoft.com/en-us/windows/wsl/networking) - **Python / pip 镜像说明**:[清华 TUNA - PyPI 镜像帮助](https://mirror.tuna.tsinghua.edu.cn/help/pypi/) - **Node.js / npm 镜像说明**:[清华 TUNA - NodeJS Release 镜像帮助](https://mirror.tuna.tsinghua.edu.cn/help/nodejs-release/) / [npmmirror](https://npmmirror.com/) ::: ### Android / Termux {#android--termux} Hermes 也提供了针对 Termux 的安装路径: ```bash curl -fsSL https://res1.hermesagent.org.cn/install.sh | bash ``` 安装程序会自动检测 Termux 并切换到经过测试的 Android 流程: - 优先复用系统已有的 Python;缺失时通过 `pkg` 安装 Python - 自动补齐 Android 构建所需的基础工具链(`clang`、`rust`、`make`、`pkg-config`、`libffi`、`openssl`) - 使用 `python -m venv` 创建虚拟环境 - 自动导出 `ANDROID_API_LEVEL` 用于 Android 轮子构建 - 通过 `pip` 安装经过精选的 `.[termux]` 额外组件 - 默认跳过浏览器 / WhatsApp 等额外 Node 组件 如需完全显式路径,请参考专用的 [Termux 指南](termux)。 ### 安装程序执行的操作 {#what-the-installer-does} 安装器会自动处理以下工作: - 优先使用站点镜像 / R2 资源下载源码包,失败时再回退到上游仓库 - 优先复用系统已有的 Python(>= 3.11);没有时再尝试通过 `uv` 安装 Python - 创建虚拟环境并安装 `hermes` 命令 - 引导你完成模型配置与首次启动 - 默认跳过浏览器、Chromium、WhatsApp 桥接等额外 Node 组件 ### 安装后操作 {#after-installation} #### 类 Unix / WSL2 ```bash source ~/.bashrc # 或:source ~/.zshrc hermes # 开始聊天 ``` #### Windows PowerShell ```powershell # 关闭并重新打开 PowerShell 后再运行 hermes ``` 如需后续重新配置个别设置,请使用这些命令: ```bash hermes model # 选择大语言模型提供商和模型 hermes tools # 配置启用哪些工具 hermes gateway setup # 设置消息平台 hermes config set # 单独设置某个配置项 hermes setup # 或再次运行完整设置向导 ``` --- ## 先决条件 {#prerequisites} 推荐先决条件: - **Python 3.11+**(安装器会优先复用系统已有 Python) - **Git**(只有当镜像源码包不可用时,安装器才会回退到 `git clone`) - **Node.js v22+**(仅在你需要浏览器 / 其他额外 Node 组件时再装) - **ripgrep** / **ffmpeg**(非硬性依赖,缺失时会提示手动安装) :::info 对大多数中国大陆用户来说,最稳的路径是:**先用镜像版 `install.sh` 完成核心安装,再按需单独补浏览器 / WhatsApp 等额外组件**。 ::: :::tip Nix 用户 如果你使用 Nix(在 NixOS、macOS 或 Linux 上),有专门的设置路径,包括 Nix flake、声明式 NixOS 模块以及可选容器模式。请参阅 **[Nix & NixOS 设置](nix-setup)** 指南。 ::: --- ## 手动安装 {#manual-installation} 如果你希望对安装过程拥有完全控制,请遵循以下步骤。 :::tip Windows 用户 下面这组手动命令是给 **类 Unix shell / WSL2** 准备的,不适合直接在 PowerShell 中照抄。如果你使用的是原生 Windows,请优先走上面的 `install.ps1`,或直接看 **[Windows 安装指南](windows-installation)**。 ::: ### 步骤 1:克隆仓库 {#step-1-clone-the-repository} 使用 `--recurse-submodules` 克隆以拉取所需子模块: ```bash git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git cd hermes-agent ``` 如果您已不带 `--recurse-submodules` 克隆: ```bash git submodule update --init --recursive ``` ### 步骤 2:安装 uv 并创建虚拟环境 {#step-2-install-uv--create-virtual-environment} ```bash # 安装 uv(如果尚未安装) curl -LsSf https://astral.sh/uv/install.sh | sh # 使用 Python 3.11 创建虚拟环境(若本机不存在,uv 会自动下载,无需 sudo) uv venv venv --python 3.11 ``` :::tip 您**无需**激活虚拟环境即可使用 `hermes`。入口点已硬编码指向虚拟环境的 Python,因此一旦创建符号链接,即可全局使用。 ::: ### 步骤 3:安装 Python 依赖项 {#step-3-install-python-dependencies} ```bash # 告诉 uv 要安装到哪个虚拟环境 export VIRTUAL_ENV="$(pwd)/venv" # 安装完整推荐依赖 uv pip install -e ".[all]" ``` 如果您仅需要核心 Agent(无 Telegram/Discord/cron 支持): ```bash uv pip install -e "." ```
可选额外组件说明 | 额外组件 | 添加内容 | 安装命令 | |-------|-------------|-----------------| | `all` | 以下所有内容 | `uv pip install -e ".[all]"` | | `messaging` | Telegram 与 Discord 网关 | `uv pip install -e ".[messaging]"` | | `cron` | 用于定时任务的 cron 表达式解析 | `uv pip install -e ".[cron]"` | | `cli` | 设置向导的终端菜单 UI | `uv pip install -e ".[cli]"` | | `modal` | Modal 云执行后端 | `uv pip install -e ".[modal]"` | | `tts-premium` | ElevenLabs 高级语音 | `uv pip install -e ".[tts-premium]"` | | `voice` | CLI 麦克风输入 + 音频播放 | `uv pip install -e ".[voice]"` | | `pty` | PTY 终端支持 | `uv pip install -e ".[pty]"` | | `termux` | 经测试的 Android / Termux 套件(`cron`、`cli`、`pty`、`mcp`、`honcho`、`acp`) | `python -m pip install -e ".[termux]" -c constraints-termux.txt` | | `honcho` | AI 原生记忆(Honcho 集成) | `uv pip install -e ".[honcho]"` | | `mcp` | 模型上下文协议支持 | `uv pip install -e ".[mcp]"` | | `homeassistant` | Home Assistant 集成 | `uv pip install -e ".[homeassistant]"` | | `acp` | ACP 编辑器集成支持 | `uv pip install -e ".[acp]"` | | `slack` | Slack 消息 | `uv pip install -e ".[slack]"` | | `dev` | pytest 与测试工具 | `uv pip install -e ".[dev]"` | 您可以组合使用额外组件:`uv pip install -e ".[messaging,cron]"` :::tip Termux 用户 `.[all]` 当前在 Android 上不可用,因为 `voice` 额外组件依赖 `faster-whisper`,而 `faster-whisper` 依赖 `ctranslate2` 轮子,这些轮子尚未发布到 Android。请使用 `.[termux]` 获取经过测试的移动端安装路径,然后按需添加个别额外组件。 :::
### 步骤 4:安装可选子模块(如需) {#step-4-install-optional-submodules-if-needed} ```bash # 强化学习训练后端(可选) uv pip install -e "./tinker-atropos" ``` 两者均为可选 —— 如果跳过,相应工具集将不可用。 ### 步骤 5:安装 Node.js 依赖项(可选) {#step-5-install-nodejs-dependencies-optional} 仅在需要 **浏览器自动化**(Browserbase 驱动)和 **WhatsApp 桥接** 时才需要: ```bash npm install ``` ### 步骤 6:创建配置目录 {#step-6-create-the-configuration-directory} ```bash # 创建目录结构 mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills,pairing,hooks,image_cache,audio_cache,whatsapp/session} # 复制示例配置文件 cp cli-config.yaml.example ~/.hermes/config.yaml # 创建用于保存 API 密钥的空 `.env` 文件 touch ~/.hermes/.env ``` ### 第 7 步:添加您的 API 密钥 {#step-7-add-your-api-keys} 打开 `~/.hermes/.env` 文件,并至少添加一个 LLM 提供商的密钥: ```bash # 必填:至少配置一个大语言模型提供商 OPENROUTER_API_KEY=sk-or-v1-your-key-here # 可选:启用额外工具能力 FIRECRAWL_API_KEY=fc-your-key # 网络搜索和抓取(或自托管,请参阅文档) FAL_KEY=your-fal-key # 图像生成(FLUX) ``` 或者通过 CLI 设置: ```bash hermes config set OPENROUTER_API_KEY sk-or-v1-your-key-here ``` ### 第 8 步:将 `hermes` 添加到您的 PATH {#step-8-add-hermes-to-your-path} ```bash mkdir -p ~/.local/bin ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes ``` 如果 `~/.local/bin` 不在您的 PATH 中,请将其添加到您的 shell 配置文件中: ```bash # Bash echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc # Zsh echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc # Fish fish_add_path $HOME/.local/bin ``` ### 第 9 步:配置您的提供方 {#step-9-configure-your-provider} ```bash hermes model # 选择大语言模型提供商和具体模型 ``` ### 第 10 步:验证安装 {#step-10-verify-the-installation} ```bash hermes version # 检查命令是否可用 hermes doctor # 运行诊断,确认环境工作正常 hermes status # 检查当前配置 hermes chat -q "你好,告诉我你当前可用的工具。" ``` --- ## 快速参考:手动安装(精简版) {#quick-reference-manual-install-condensed} 适用于只想获取命令的用户: ```bash # 安装 uv curl -LsSf https://astral.sh/uv/install.sh | sh # 克隆仓库并进入目录 git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git cd hermes-agent # 使用 Python 3.11 创建虚拟环境 uv venv venv --python 3.11 export VIRTUAL_ENV="$(pwd)/venv" # 安装完整依赖 uv pip install -e ".[all]" uv pip install -e "./tinker-atropos" npm install # 可选:浏览器工具和 WhatsApp 桥接需要它 # 准备配置文件 mkdir -p ~/.hermes/{cron,sessions,logs,memories,skills,pairing,hooks,image_cache,audio_cache,whatsapp/session} cp cli-config.yaml.example ~/.hermes/config.yaml touch ~/.hermes/.env echo 'OPENROUTER_API_KEY=sk-or-v1-your-key' >> ~/.hermes/.env # 让 hermes 成为全局命令 mkdir -p ~/.local/bin ln -sf "$(pwd)/venv/bin/hermes" ~/.local/bin/hermes # 验证安装 hermes doctor hermes ``` --- ## 故障排除 {#troubleshooting} | 问题 | 解决方案 | |------|----------| | `hermes: command not found` | 重新加载您的 shell(`source ~/.bashrc`)或检查 PATH | | `API key not set` | 运行 `hermes model` 来配置您的提供方,或运行 `hermes config set OPENROUTER_API_KEY your_key` | | `hermes` 不是内部或外部命令 | 关闭并重新打开 PowerShell,或确认 `%LOCALAPPDATA%\hermes\bin` 已加入 PATH;WSL2 用户请重新加载 shell | | 更新后配置丢失 | 运行 `hermes config check`,然后运行 `hermes config migrate` | 如需更多诊断信息,请运行 `hermes doctor` —— 它将明确告知您缺少什么以及如何修复。 --- ### 学习路径 - URL: https://hermesagent.org.cn/docs/getting-started/learning-path - Path: getting-started/learning-path.md - Category: getting-started - Description: 根据您的经验水平和目标,选择适合你的 Hermes Agent 文档学习路径。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/getting-started/learning-path.md - Translated At: 2026-04-11T03:25:20.156Z - Headings: 如何使用本页面 | 按经验水平 | 按使用场景 | “我想要一个 CLI 编程助手” | “我想要一个 Telegram/Discord 机器人” | “我想要自动化任务” | “我想要构建自定义工具/技能” | “我想要训练模型” | “我想将其作为 Python 库使用” | 一目了然的关键功能 | 接下来该读什么 # 学习路径 {#learning-path} Hermes Agent 功能强大——可作为 CLI 助手、Telegram/Discord 机器人、任务自动化工具、强化学习训练平台等。本页面将帮助你根据自身经验水平和目标,确定从何处开始以及应阅读哪些内容。 :::tip 从这里开始 如果你尚未安装 Hermes Agent,请先阅读 [安装指南](/docs/getting-started/installation)。如果你使用的是 Windows,请优先看 [Windows 安装指南](/docs/getting-started/windows-installation)。然后再完成 [快速入门](/docs/getting-started/quickstart)。以下所有内容均假设你已成功安装并运行。 ::: ## 如何使用本页面 {#how-to-use-this-page} - **了解自身水平?** 直接跳转至 [按经验水平划分](#by-experience-level) 表格,按照对应层级的阅读顺序进行学习。 - **有明确目标?** 跳转至 [按使用场景](#by-use-case) 部分,找到与你需求匹配的场景。 - **随意浏览?** 查看 [核心功能概览](#key-features-at-a-glance) 表格,快速了解 Hermes Agent 的全部能力。 ## 按经验水平 {#by-experience-level} | 水平 | 目标 | 推荐阅读 | 预计耗时 | |---|---|---|---| | **初级** | 快速上手,进行基础对话,使用内置工具 | [安装](/docs/getting-started/installation) / [Windows 安装](/docs/getting-started/windows-installation) → [快速入门](/docs/getting-started/quickstart) → [CLI 使用](/docs/user-guide/cli) → [配置](/docs/user-guide/configuration) | ~1 小时 | | **中级** | 部署消息机器人,使用高级功能如记忆、定时任务和技能 | [会话](/docs/user-guide/sessions) → [消息通信](/docs/user-guide/messaging) → [工具](/docs/user-guide/features/tools) → [技能](/docs/user-guide/features/skills) → [记忆](/docs/user-guide/features/memory) → [定时任务](/docs/user-guide/features/cron) | ~2–3 小时 | | **高级** | 构建自定义工具,创建技能,使用强化学习训练模型,参与项目贡献 | [架构](/docs/developer-guide/architecture) → [添加工具](/docs/developer-guide/adding-tools) → [创建技能](/docs/developer-guide/creating-skills) → [强化学习训练](/docs/reference/toolsets-reference) → [贡献指南](/docs/developer-guide/contributing) | ~4–6 小时 | ## 按使用场景 {#by-use-case} 选择与你目标相符的场景。每个场景均提供按顺序阅读的相关文档链接。 ### “我想要一个 CLI 编程助手” {#i-want-a-cli-coding-assistant} 将 Hermes Agent 用作交互式终端助手,用于编写、审查和运行代码。 1. [安装](/docs/getting-started/installation)(Windows 用户请改看 [Windows 安装](/docs/getting-started/windows-installation)) 2. [快速入门](/docs/getting-started/quickstart) 3. [CLI 使用](/docs/user-guide/cli) 4. [代码执行](/docs/user-guide/features/code-execution) 5. [上下文文件](/docs/user-guide/features/context-files) 6. [技巧与窍门](/docs/guides/tips) :::tip 通过上下文文件直接将文件传入对话中。Hermes Agent 可读取、编辑并运行你项目中的代码。 ::: ### “我想要一个 Telegram/Discord 机器人” {#i-want-a-telegramdiscord-bot} 将 Hermes Agent 部署为在你喜爱的消息平台上的机器人。 1. [安装](/docs/getting-started/installation)(Windows 用户请改看 [Windows 安装](/docs/getting-started/windows-installation)) 2. [配置](/docs/user-guide/configuration) 3. [消息通信概览](/docs/user-guide/messaging) 4. [Telegram 设置](/docs/user-guide/messaging/telegram) 5. [Discord 设置](/docs/user-guide/messaging/discord) 6. [语音模式](/docs/user-guide/features/voice-mode) 7. [使用语音模式与 Hermes](/docs/guides/use-voice-mode-with-hermes) 8. [安全](/docs/user-guide/security) 完整项目示例请参见: - [每日简报机器人](/docs/guides/daily-briefing-bot) - [团队 Telegram 助手](/docs/guides/team-telegram-assistant) ### “我想要自动化任务” {#i-want-to-automate-tasks} 安排重复性任务,运行批处理作业,或串联多个 Agent 动作。 1. [快速入门](/docs/getting-started/quickstart) 2. [定时任务调度](/docs/user-guide/features/cron) 3. [批量处理](/docs/user-guide/features/batch-processing) 4. [委托](/docs/user-guide/features/delegation) 5. [钩子](/docs/user-guide/features/hooks) :::tip 定时任务(Cron)可让 Hermes Agent 在预定时间自动执行任务——如每日摘要、周期性检查、自动生成报告——无需你实时在场。 ::: ### “我想要构建自定义工具/技能” {#i-want-to-build-custom-toolsskills} 通过自定义工具和可复用的技能包扩展 Hermes Agent 的能力。 1. [工具概览](/docs/user-guide/features/tools) 2. [技能概览](/docs/user-guide/features/skills) 3. [MCP(模型上下文协议)](/docs/user-guide/features/mcp) 4. [架构](/docs/developer-guide/architecture) 5. [添加工具](/docs/developer-guide/adding-tools) 6. [创建技能](/docs/developer-guide/creating-skills) :::tip 工具是 Agent 可调用的独立函数。技能是工具、提示词和配置打包在一起的组合。建议从工具开始,逐步进阶到技能。 ::: ### “我想要训练模型” {#i-want-to-train-models} 使用强化学习,通过 Hermes Agent 内置的强化学习训练流程对模型行为进行微调。 1. [快速入门](/docs/getting-started/quickstart) 2. [配置](/docs/user-guide/configuration) 3. [强化学习训练](/docs/reference/toolsets-reference) 4. [提供者路由](/docs/user-guide/features/provider-routing) 5. [架构](/docs/developer-guide/architecture) :::tip 在您已经了解 Hermes Agent 处理对话和工具调用的基本原理的情况下,强化学习(RL)训练效果最佳。如果您是新手,请先完成入门路径。 ::: ### “我想将其作为 Python 库使用” {#i-want-to-use-it-as-a-python-library} 通过编程方式将 Hermes Agent 集成到您自己的 Python 应用程序中。 1. [安装](/docs/getting-started/installation)(Windows 用户请改看 [Windows 安装](/docs/getting-started/windows-installation)) 2. [快速入门](/docs/getting-started/quickstart) 3. [Python 库指南](/docs/guides/python-library) 4. [架构](/docs/developer-guide/architecture) 5. [工具](/docs/user-guide/features/tools) 6. [会话](/docs/user-guide/sessions) ## 一目了然的关键功能 {#key-features-at-a-glance} 不确定有哪些可用功能?以下是主要功能的快速目录: | 功能 | 作用 | 链接 | |---|---|---| | **工具** | Agent 可调用的内置工具(文件 I/O、搜索、Shell 等) | [工具](/docs/user-guide/features/tools) | | **技能** | 可安装的插件包,用于添加新功能 | [技能](/docs/user-guide/features/skills) | | **记忆** | 跨会话的持久化记忆 | [记忆](/docs/user-guide/features/memory) | | **上下文文件** | 把文件和目录带入当前对话 | [上下文文件](/docs/user-guide/features/context-files) | | **MCP** | 通过模型上下文协议(Model Context Protocol)连接外部工具服务器 | [MCP](/docs/user-guide/features/mcp) | | **定时任务** | 安排重复执行的 Agent 任务 | [定时任务](/docs/user-guide/features/cron) | | **委派** | 启动子 Agent 以并行工作 | [委派](/docs/user-guide/features/delegation) | | **代码执行** | 在沙箱环境中运行代码 | [代码执行](/docs/user-guide/features/code-execution) | | **浏览器** | 网页浏览与爬取 | [浏览器](/docs/user-guide/features/browser) | | **钩子** | 基于事件的回调和中间件 | [钩子](/docs/user-guide/features/hooks) | | **批量处理** | 批量处理多个输入 | [批量处理](/docs/user-guide/features/batch-processing) | | **强化学习训练** | 使用强化学习微调模型 | [强化学习训练](/docs/reference/toolsets-reference) | | **提供者路由** | 在多个大语言模型(LLM)提供者之间路由请求 | [提供者路由](/docs/user-guide/features/provider-routing) | ## 接下来该读什么 {#what-to-read-next} 根据您当前所处的位置: - **刚完成安装?** → 前往 [快速入门](/docs/getting-started/quickstart),运行您的第一个对话。 - **已完成快速入门?** → 阅读 [CLI 使用](/docs/user-guide/cli) 和 [配置](/docs/user-guide/configuration),自定义您的设置。 - **对基础操作感到熟悉?** → 探索 [工具](/docs/user-guide/features/tools)、[技能](/docs/user-guide/features/skills) 和 [记忆](/docs/user-guide/features/memory),充分释放 Agent 的全部潜力。 - **正在为团队搭建环境?** → 阅读 [安全](/docs/user-guide/security) 和 [会话](/docs/user-guide/sessions),了解访问控制和对话管理。 - **准备开始构建?** → 跳转至 [开发者指南](/docs/developer-guide/architecture),深入理解内部机制并开始贡献代码。 - **想要实际示例?** → 查看 [指南](/docs/guides/tips) 部分,获取真实项目和实用技巧。 :::tip 您无需阅读全部内容。选择与您目标匹配的路径,按链接顺序阅读,即可快速上手。您随时可以返回此页面,找到下一步要学习的内容。 ::: --- ### Nix & NixOS 设置 - URL: https://hermesagent.org.cn/docs/getting-started/nix-setup - Path: getting-started/nix-setup.md - Category: getting-started - Description: 使用 Nix 安装和部署 Hermes Agent — 从快速的 nix run 到完全声明式的 NixOS 模块(容器模式) - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/getting-started/nix-setup.md - Translated At: 2026-04-11T03:26:19.314Z - Headings: 先决条件 | 快速入门(任何 Nix 用户) | NixOS 模块 | 添加 Flake 输入 | 最小配置 | 验证是否正常工作 | 选择部署模式 | 配置 | 声明式设置 | 逃生通道:使用你自己的配置 | 自定义速查表 | 密钥管理 # Nix & NixOS 部署 {#nix--nixos-setup} Hermes Agent 随附一个 Nix flake,提供三个层级的集成: | 层级 | 适用对象 | 你将获得 | |------|--------|---------| | **`nix run` / `nix profile install`** | 任何 Nix 用户(macOS、Linux) | 包含所有依赖的预构建二进制文件 —— 然后使用标准 CLI 工作流 | | **NixOS 模块(原生)** | NixOS 服务器部署 | 声明式配置、强化的 systemd 服务、受管理的密钥 | | **NixOS 模块(容器)** | 需要自我修改的 Agent | 上述所有功能,外加一个持久化的 Ubuntu 容器,Agent 可在其中执行 `apt`/`pip`/`npm install` | :::info 与标准安装的不同之处 `curl | bash` 安装程序自行管理 Python、Node 和依赖项。而 Nix flake 替代了所有这些内容 —— 每个 Python 依赖都是由 [uv2nix](https://github.com/pyproject-nix/uv2nix) 构建的 Nix 衍生品,运行时工具(Node.js、git、ripgrep、ffmpeg)也被封装进二进制文件的 PATH 中。运行时不再需要 `pip`,无需虚拟环境激活,也不再需要 `npm install`。 **对于非 NixOS 用户**,这仅改变了安装步骤。之后的所有操作(`hermes setup`、`hermes gateway install`、配置编辑)与标准安装完全相同。 **对于 NixOS 模块用户**,整个生命周期完全不同:配置位于 `configuration.nix`,密钥通过 sops-nix/agenix 管理,服务为 systemd 单元,CLI 配置命令被禁用。你管理 hermes 的方式与管理其他任何 NixOS 服务一致。 ::: ## 先决条件 {#prerequisites} - **启用 flakes 的 Nix** —— 推荐使用 [Determinate Nix](https://install.determinate.systems)(默认启用 flakes) - 你希望使用的服务的 API 密钥(至少需要一个 OpenRouter 或 Anthropic 密钥) --- ## 快速入门(任何 Nix 用户) {#quick-start-any-nix-user} 无需克隆。Nix 会自动获取、构建并运行所有内容: ```bash # 直接运行(首次使用时构建,之后缓存) nix run github:NousResearch/hermes-agent -- 设置 nix run github:NousResearch/hermes-agent -- 聊天 # 或者持久安装 nix profile install github:NousResearch/hermes-agent hermes setup hermes chat ``` `nix profile install` 之后,`hermes`、`hermes-agent` 和 `hermes-acp` 将出现在你的 PATH 中。从这一步开始,工作流与 [标准安装](installation) 完全相同 —— `hermes setup` 会引导你完成提供者选择,`hermes gateway install` 会设置 launchd(macOS)或 systemd 用户服务,配置文件位于 `~/.hermes/`。
从本地克隆构建 ```bash git clone https://github.com/NousResearch/hermes-agent.git cd hermes-agent nix build ./result/bin/hermes setup ```
--- ## NixOS 模块 {#nixos-module} flake 导出了 `nixosModules.default` —— 一个完整的 NixOS 服务模块,声明式地管理用户创建、目录、配置生成、密钥、文档和服务生命周期。 :::note 此模块需要 NixOS。对于非 NixOS 系统(macOS、其他 Linux 发行版),请使用 `nix profile install` 和上述标准 CLI 工作流。 ::: ### 添加 Flake 输入 {#add-the-flake-input} ```nix # /etc/nixos/flake.nix(或您的系统碎片) { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; hermes-agent.url = "github:NousResearch/hermes-agent"; }; outputs = { nixpkgs, hermes-agent, ... }: { nixosConfigurations.your-host = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ hermes-agent.nixosModules.default ./configuration.nix ]; }; }; } ``` ### 最小配置 {#minimal-configuration} ```nix # configuration.nix { config, ... }: { services.hermes-agent = { enable = true; settings.model.default = "anthropic/claude-sonnet-4"; environmentFiles = [ config.sops.secrets."hermes-env".path ]; addToSystemPackages = true; }; } ``` 仅此而已。`nixos-rebuild switch` 会创建 `hermes` 用户,生成 `config.yaml`,连接密钥,并启动网关 —— 一个长时间运行的服务,将 Agent 连接到消息平台(Telegram、Discord 等)并监听传入消息。 :::warning 密钥是必需的 上面的 `environmentFiles` 行假设你已配置 [sops-nix](https://github.com/Mic92/sops-nix) 或 [agenix](https://github.com/ryantm/agenix)。该文件应至少包含一个 LLM 提供商密钥(例如 `OPENROUTER_API_KEY=sk-or-...`)。完整设置请参见 [密钥管理](#secrets-management)。如果你尚未配置密钥管理器,可以先使用普通文件作为起点 —— 但请确保它不可被世界读取: ```bash echo "OPENROUTER_API_KEY=sk-or-your-key" | sudo install -m 0600 -o hermes /dev/stdin /var/lib/hermes/env ``` ```nix services.hermes-agent.environmentFiles = [ "/var/lib/hermes/env" ]; ``` ::: :::tip addToSystemPackages 设置 `addToSystemPackages = true` 有两点作用:将 `hermes` CLI 添加到系统 PATH **并且** 全局设置 `HERMES_HOME`,使交互式 CLI 与网关服务共享状态(会话、技能、cron)。若不设置,你在 shell 中运行 `hermes` 会创建一个独立的 `~/.hermes/` 目录。 ::: ### 验证是否正常工作 {#verify-it-works} `nixos-rebuild switch` 之后,检查服务是否正在运行: ```bash # 检查服务状态 systemctl status hermes-agent # 查看日志(按 Ctrl+C 停止) journalctl -u hermes-agent -f # 如果 addToSystemPackages 为 true,则测试 CLI hermes version hermes config # 显示生成的配置 ``` ### 选择部署模式 {#choosing-a-deployment-mode} 该模块支持两种模式,由 `container.enable` 控制: | | **原生**(默认) | **容器** | |---|---|---| | 运行方式 | 主机上的强化 systemd 服务 | 持久化的 Ubuntu 容器,`/nix/store` 绑定挂载 | | 安全性 | `NoNewPrivileges`、`ProtectSystem=strict`、`PrivateTmp` | 容器隔离,以非特权用户运行 | | Agent 能否在运行时安装包 | 否 —— 仅限 Nix 提供的 PATH 中的工具 | 是 —— `apt`、`pip`、`npm` 安装在重启后仍持久存在 | | 配置面 | 相同 | 相同 | | 何时选择 | 标准部署、最大安全性、可复现性 | Agent 需要运行时包安装、可变环境、实验性工具 | 要启用容器模式,只需添加一行: ```nix { services.hermes-agent = { enable = true; container.enable = true; # ...配置的其余部分是相同的 }; } ``` :::info 容器模式会通过 `mkDefault` 自动启用 `virtualisation.docker.enable`。如果你使用 Podman 而非 Docker,请设置 `container.backend = "podman"` 并将 `virtualisation.docker.enable = false`。 ::: --- ## 配置 {#configuration} ### 声明式设置 {#declarative-settings} `settings` 选项接受一个任意的 attrset,该 attrset 会被渲染为 `config.yaml`。它支持通过 `lib.recursiveUpdate` 在多个模块定义之间进行深度合并,因此你可以将配置拆分到多个文件中: ```nix # base.nix services.hermes-agent.settings = { model.default = "anthropic/claude-sonnet-4"; toolsets = [ "all" ]; terminal = { backend = "local"; timeout = 180; }; }; # personality.nix services.hermes-agent.settings = { display = { compact = false; personality = "kawaii"; }; memory = { memory_enabled = true; user_profile_enabled = true; }; }; ``` 两者在评估时都会被深度合并。Nix 声明的键始终优先于磁盘上已存在的 `config.yaml` 中的键,但 **Nix 不会触及的用户添加的键将被保留**。这意味着,如果 Agent 或手动编辑添加了如 `skills.disabled` 或 `streaming.enabled` 这样的键,它们在执行 `nixos-rebuild switch` 后依然会保留。 :::note 模型命名 `settings.model.default` 使用的是你的提供商所期望的模型标识符。使用 [OpenRouter](https://openrouter.ai)(默认)时,这些标识符看起来像 `"anthropic/claude-sonnet-4"` 或 `"google/gemini-3-flash"`。如果你直接使用提供商(如 Anthropic、OpenAI),请将 `settings.model.base_url` 设置为指向其 API,并使用其原生模型 ID(例如 `"claude-sonnet-4-20250514"`)。当未设置 `base_url` 时,Hermes 默认使用 OpenRouter。 ::: :::tip 查看可用的配置键 运行 `nix build .#configKeys && cat result` 可以查看从 Python 的 `DEFAULT_CONFIG` 中提取的所有叶级配置键。你可以将现有的 `config.yaml` 粘贴到 `settings` attrset 中——其结构完全一一对应。 :::
完整示例:所有常见自定义设置 ```nix { config, ... }: { services.hermes-agent = { enable = true; container.enable = true; # ── Model ────────────────────────────────────────────────────────── settings = { model = { base_url = "https://openrouter.ai/api/v1"; default = "anthropic/claude-opus-4.6"; }; toolsets = [ "all" ]; max_turns = 100; terminal = { backend = "local"; cwd = "."; timeout = 180; }; compression = { enabled = true; threshold = 0.85; summary_model = "google/gemini-3-flash-preview"; }; memory = { memory_enabled = true; user_profile_enabled = true; }; display = { compact = false; personality = "kawaii"; }; agent = { max_turns = 60; verbose = false; }; }; # ── 秘密────────────────────────────────────────────────────────── environmentFiles = [ config.sops.secrets."hermes-env".path ]; # ── 文件────────────────────────────────────────────────────── documents = { "SOUL.md" = builtins.readFile /home/user/.hermes/SOUL.md; "USER.md" = ./documents/USER.md; }; # ── MCP 服务器 ──────────────────────────────────────────────────── mcpServers.filesystem = { command = "npx"; args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ]; }; # ── 容器选项────────────────────────────────────────────── container = { image = "ubuntu:24.04"; backend = "docker"; extraVolumes = [ "/home/user/projects:/projects:rw" ]; extraOptions = [ "--gpus" "all" ]; }; # ── 服务调整────────────────────────────────────────────────── addToSystemPackages = true; extraArgs = [ "--verbose" ]; restart = "always"; restartSec = 5; }; } ```
### 逃生通道:使用你自己的配置 {#escape-hatch-bring-your-own-config} 如果你更愿意完全在 Nix 之外管理 `config.yaml`,请使用 `configFile`: ```nix services.hermes-agent.configFile = /etc/hermes/config.yaml; ``` 这将完全绕过 `settings` —— 不进行合并,也不生成配置。该文件会在每次激活时原封不动地复制到 `$HERMES_HOME/config.yaml`。 ### 自定义速查表 {#customization-cheatsheet} Nix 用户最常需要自定义的快速参考: | 我想... | 选项 | 示例 | |---|---|---| | 更改 LLM 模型 | `settings.model.default` | `"anthropic/claude-sonnet-4"` | | 使用不同的提供商端点 | `settings.model.base_url` | `"https://openrouter.ai/api/v1"` | | 添加 API 密钥 | `environmentFiles` | `[ config.sops.secrets."hermes-env".path ]` | | 给 Agent 赋予个性 | `documents."SOUL.md"` | `builtins.readFile ./my-soul.md` | | 添加 MCP 工具服务器 | `mcpServers.` | 参见 [MCP 服务器](#mcp-servers) | | 将主机目录挂载到容器中 | `container.extraVolumes` | `[ "/data:/data:rw" ]` | | 向容器传递 GPU 访问权限 | `container.extraOptions` | `[ "--gpus" "all" ]` | | 使用 Podman 而非 Docker | `container.backend` | `"podman"` | | 向服务 PATH 添加工具(仅原生) | `extraPackages` | `[ pkgs.pandoc pkgs.imagemagick ]` | | 使用自定义基础镜像 | `container.image` | `"ubuntu:24.04"` | | 覆盖 hermes 包 | `package` | `inputs.hermes-agent.packages.${system}.default.override { ... }` | | 更改状态目录 | `stateDir` | `"/opt/hermes"` | | 设置 Agent 的工作目录 | `workingDirectory` | `"/home/user/projects"` | --- ## 密钥管理 {#secrets-management} :::danger 永远不要将 API 密钥放入 `settings` 或 `environment` Nix 表达式中的值最终会出现在 `/nix/store` 中,而该目录对世界可读。请始终使用 `environmentFiles` 配合密钥管理器。 ::: `environment`(非敏感变量)和 `environmentFiles`(密钥文件)会在激活时(`nixos-rebuild switch`)合并到 `$HERMES_HOME/.env`。Hermes 在每次启动时都会读取该文件,因此更改只需通过 `systemctl restart hermes-agent` 即可生效——无需重建容器。 ### sops-nix {#sops-nix} ```nix { sops = { defaultSopsFile = ./secrets/hermes.yaml; age.keyFile = "/home/user/.config/sops/age/keys.txt"; secrets."hermes-env" = { format = "yaml"; }; }; services.hermes-agent.environmentFiles = [ config.sops.secrets."hermes-env".path ]; } ``` 密钥文件包含键值对: ```yaml # Secrets/hermes.yaml(使用 sops 加密) hermes-env: | OPENROUTER_API_KEY=sk-or-... TELEGRAM_BOT_TOKEN=123456:ABC... ANTHROPIC_API_KEY=sk-ant-... ``` ### agenix {#agenix} ```nix { age.secrets.hermes-env.file = ./secrets/hermes-env.age; services.hermes-agent.environmentFiles = [ config.age.secrets.hermes-env.path ]; } ``` ### OAuth / 认证种子 {#oauth--auth-seeding} 对于需要 OAuth 的平台(如 Discord),请使用 `authFile` 在首次部署时注入凭据: ```nix { services.hermes-agent = { authFile = config.sops.secrets."hermes/auth.json".path; # authFileForceOverwrite = true; # 每次激活时覆盖 }; } ``` 该文件仅在 `auth.json` 不存在时才会被复制(除非设置 `authFileForceOverwrite = true`)。运行时的 OAuth 令牌刷新会写入状态目录,并在重建之间保留。 --- ## 文档 {#documents} `documents` 选项将文件安装到 Agent 的工作目录中(即 `workingDirectory`,Agent 将其作为工作区读取)。Hermes 会按约定查找特定文件名: - **`SOUL.md`** —— Agent 的系统提示 / 个性。Hermes 在启动时读取此文件,并将其作为持久化指令,影响其在所有对话中的行为。 - **`USER.md`** —— Agent 交互的用户的相关上下文。 - 你在此处放置的任何其他文件都会被 Agent 作为工作区文件可见。 ```nix { services.hermes-agent.documents = { "SOUL.md" = '' You are a helpful research assistant specializing in NixOS packaging. Always cite sources and prefer reproducible solutions. ''; "USER.md" = ./documents/USER.md; # 路径参考,从 Nix 商店复制 }; } ``` 值可以是内联字符串或路径引用。每次执行 `nixos-rebuild switch` 时都会安装这些文件。 --- ## MCP 服务器 {#mcp-servers} `mcpServers` 选项声明式地配置 [MCP(模型上下文协议)](https://modelcontextprotocol.io) 服务器。每个服务器使用 **stdio**(本地命令)或 **HTTP**(远程 URL)传输。 ### Stdio 传输(本地服务器) {#stdio-transport-local-servers} ```nix { services.hermes-agent.mcpServers = { filesystem = { command = "npx"; args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ]; }; github = { command = "npx"; args = [ "-y" "@modelcontextprotocol/server-github" ]; env.GITHUB_PERSONAL_ACCESS_TOKEN = "\${GITHUB_TOKEN}"; # 从 `.env` 解析 }; }; } ``` :::tip `env` 值中的环境变量会在运行时从 `$HERMES_HOME/.env` 解析。请使用 `environmentFiles` 注入密钥——永远不要将令牌直接写入 Nix 配置。 ::: ### HTTP 传输(远程服务器) {#http-transport-remote-servers} ```nix { services.hermes-agent.mcpServers.remote-api = { url = "https://mcp.example.com/v1/mcp"; headers.Authorization = "Bearer \${MCP_REMOTE_API_KEY}"; timeout = 180; }; } ``` ### 使用 OAuth 的 HTTP 传输 {#http-transport-with-oauth} 对于使用 OAuth 2.1 的服务器,请设置 `auth = "oauth"`。Hermes 实现了完整的 PKCE 流程 —— 元数据发现、动态客户端注册、令牌交换以及自动刷新。 ```nix { services.hermes-agent.mcpServers.my-oauth-server = { url = "https://mcp.example.com/mcp"; auth = "oauth"; }; } ``` 令牌存储在 `$HERMES_HOME/mcp-tokens/.json` 中,并在重启和重建之间持久化。
无头服务器上的初始 OAuth 授权 首次 OAuth 授权需要基于浏览器的同意流程。在无头部署中,Hermes 会将授权 URL 输出到 stdout/logs,而不是打开浏览器。 **选项 A:交互式引导** —— 通过 `docker exec`(容器)或 `sudo -u hermes`(原生)运行一次流程: ```bash # 容器模式 docker exec -it hermes-agent \ hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth # 本机模式 sudo -u hermes HERMES_HOME=/var/lib/hermes/.hermes \ hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth ``` 容器使用 `--network=host`,因此 `127.0.0.1` 上的 OAuth 回调监听器可从主机浏览器访问。 **选项 B:预先填充令牌** —— 在工作站上完成流程后,复制令牌: ```bash hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth scp ~/.hermes/mcp-tokens/my-oauth-server{,.client}.json \ server:/var/lib/hermes/.hermes/mcp-tokens/ # 确保:chown hermes:hermes,chmod 0600 ```
### 采样(由服务器发起的 LLM 请求) {#sampling-server-initiated-llm-requests} 某些 MCP 服务器可以向 Agent 请求 LLM 完成: ```nix { services.hermes-agent.mcpServers.analysis = { command = "npx"; args = [ "-y" "analysis-server" ]; sampling = { enabled = true; model = "google/gemini-3-flash"; max_tokens_cap = 4096; timeout = 30; max_rpm = 10; }; }; } ``` --- ## 管理模式 {#managed-mode} 当通过 NixOS 模块运行 hermes 时,以下 CLI 命令将被**阻止**,并返回描述性错误,提示您前往 `configuration.nix`: | 被阻止的命令 | 原因 | |---|---| | `hermes setup` | 配置是声明式的 —— 编辑 Nix 配置中的 `settings` | | `hermes config edit` | 配置由 `settings` 生成 | | `hermes config set ` | 配置由 `settings` 生成 | | `hermes gateway install` | systemd 服务由 NixOS 管理 | | `hermes gateway uninstall` | systemd 服务由 NixOS 管理 | 这可防止 Nix 声明的内容与磁盘上的实际内容之间出现偏差。检测机制使用两个信号: 1. **`HERMES_MANAGED=true`** 环境变量 —— 由 systemd 服务设置,对网关进程可见 2. **`.managed` 标记文件** 在 `HERMES_HOME` 中 —— 由激活脚本设置,对交互式 shell 可见(例如 `docker exec -it hermes-agent hermes config set ...` 也被阻止) 如需更改配置,请编辑您的 Nix 配置并运行 `sudo nixos-rebuild switch`。 --- ## 容器架构 {#container-architecture} :::info 本节仅适用于使用 `container.enable = true` 的情况。原生模式部署请跳过。 ::: 启用容器模式后,Hermes 在一个持久的 Ubuntu 容器中运行,Nix 构建的二进制文件以只读方式从主机绑定挂载: ``` Host Container ──── ───────── /nix/store/...-hermes-agent-0.1.0 ──► /nix/store/... (ro) /var/lib/hermes/ ──► /data/ (rw) ├── current-package -> /nix/store/... (symlink, updated each rebuild) ├── .gc-root -> /nix/store/... (prevents nix-collect-garbage) ├── .container-identity (sha256 hash, triggers recreation) ├── .hermes/ (HERMES_HOME) │ ├── .env (merged from environment + environmentFiles) │ ├── config.yaml (Nix-generated, deep-merged by activation) │ ├── .managed (marker file) │ ├── state.db, sessions/, memories/ (runtime state) │ └── mcp-tokens/ (OAuth tokens for MCP servers) ├── home/ ──► /home/hermes (rw) └── workspace/ (MESSAGING_CWD) ├── SOUL.md (from documents option) └── (agent-created files) Container writable layer (apt/pip/npm): /usr, /usr/local, /tmp ``` Nix 构建的二进制文件能在 Ubuntu 容器中运行,因为 `/nix/store` 被绑定挂载 —— 它自带解释器和所有依赖项,因此不依赖容器的系统库。容器入口点通过 `current-package` 符号链接解析:`/data/current-package/bin/hermes gateway run --replace`。在 `nixos-rebuild switch` 时,仅更新符号链接 —— 容器保持运行。 ### 什么在什么之间持久化 {#what-persists-across-what} | 事件 | 容器是否重新创建? | `/data`(状态) | `/home/hermes` | 可写层(`apt`/`pip`/`npm`) | |---|---|---|---|---| | `systemctl restart hermes-agent` | 否 | 持久化 | 持久化 | 持久化 | | `nixos-rebuild switch`(代码变更) | 否(仅更新符号链接) | 持久化 | 持久化 | 持久化 | | 主机重启 | 否 | 持久化 | 持久化 | 持久化 | | `nix-collect-garbage` | 否(GC 根) | 持久化 | 持久化 | 持久化 | | 镜像变更(`container.image`) | **是** | 持久化 | 持久化 | **丢失** | | 卷/选项变更 | **是** | 持久化 | 持久化 | **丢失** | | `environment`/`environmentFiles` 变更 | 否 | 持久化 | 持久化 | 持久化 | 容器仅在它的**身份哈希**发生变化时才会被重新创建。该哈希涵盖:模式版本、镜像、`extraVolumes`、`extraOptions` 和入口脚本。对环境变量、设置、文档或 hermes 包本身的更改**不会**触发重建。 :::warning 可写层丢失 当身份哈希发生变化时(镜像升级、新增卷、新增容器选项),容器会被销毁并从 `container.image` 的新镜像中重新创建。可写层中的任何 `apt install`、`pip install` 或 `npm install` 包都将丢失。`/data` 和 `/home/hermes` 中的状态会被保留(这些是绑定挂载)。 如果 Agent 依赖特定包,建议将其打包进自定义镜像(`container.image = "my-registry/hermes-base:latest"`)或在 Agent 的 SOUL.md 中编写安装脚本。 ::: ### GC 根保护 {#gc-root-protection} `preStart` 脚本在 `${stateDir}/.gc-root` 创建一个 GC 根,指向当前的 hermes 包。这可防止 `nix-collect-garbage` 删除正在运行的二进制文件。如果 GC 根意外损坏,重启服务将重新创建它。 --- ## 开发 {#development} ### 开发 Shell {#dev-shell} flake 提供了一个开发 shell,包含 Python 3.11、uv、Node.js 和所有运行时工具: ```bash cd hermes-agent nix develop # 壳牌提供: # - Python 3.11 + uv(首次进入时安装到 .venv 中) # - Node.js 20、ripgrep、git、openssh、ffmpeg 在 PATH 上 # - 标记文件优化:如果 deps 没有改变,重新进入几乎是即时的 hermes setup hermes chat ``` ### direnv(推荐) {#direnv-recommended} 包含的 `.envrc` 会自动激活开发 shell: ```bash cd hermes-agent direnv allow # 一度 # 后续条目几乎是即时的(标记文件跳过 dep 安装) ``` ### Flake 检查 {#flake-checks} flake 包含构建时验证,会在 CI 和本地运行: ```bash # 运行所有检查 nix flake check # 个人支票 nix build .#checks.x86_64-linux.package-contents # 二进制文件存在+版本 nix build .#checks.x86_64-linux.entry-points-sync # pyproject.toml ↔ Nix 包同步 nix build .#checks.x86_64-linux.cli-commands # gateway/config 子命令 nix build .#checks.x86_64-linux.managed-guard # HERMES_MANAGED 阻止突变 nix build .#checks.x86_64-linux.bundled-skills # skills 存在于包装中 nix build .#checks.x86_64-linux.config-roundtrip # 合并脚本保留用户密钥 ```
每个检查项验证的内容 | 检查项 | 验证内容 | |---|---| | `package-contents` | `hermes` 和 `hermes-agent` 二进制文件存在,且 `hermes version` 命令可执行 | | `entry-points-sync` | `pyproject.toml` 中的每个 `[project.scripts]` 条目在 Nix 包中都有对应的封装二进制文件 | | `cli-commands` | `hermes --help` 正确暴露 `gateway` 和 `config` 子命令 | | `managed-guard` | `HERMES_MANAGED=true hermes config set ...` 命令会打印 NixOS 错误信息 | | `bundled-skills` | 技能目录存在,包含 SKILL.md 文件,且 `HERMES_BUNDLED_SKILLS` 在包装器中已设置 | | `config-roundtrip` | 7 种合并场景:全新安装、Nix 覆盖、用户密钥保留、混合合并、MCP 增量合并、嵌套深度合并、幂等性 |
--- ## 选项参考 {#options-reference} ### 核心配置 {#core} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `enable` | `bool` | `false` | 启用 hermes-agent 服务 | | `package` | `package` | `hermes-agent` | 使用的 hermes-agent 包 | | `user` | `str` | `"hermes"` | 系统用户 | | `group` | `str` | `"hermes"` | 系统组 | | `createUser` | `bool` | `true` | 自动创建用户/组 | | `stateDir` | `str` | `"/var/lib/hermes"` | 状态目录(`HERMES_HOME` 的父目录) | | `workingDirectory` | `str` | `"${stateDir}/workspace"` | Agent 工作目录(`MESSAGING_CWD`) | | `addToSystemPackages` | `bool` | `false` | 将 `hermes` CLI 添加到系统 PATH,并全局设置 `HERMES_HOME` | ### 配置 {#configuration-1} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `settings` | `attrs`(深度合并) | `{}` | 以 `config.yaml` 形式渲染的声明式配置。支持任意嵌套;多个定义通过 `lib.recursiveUpdate` 合并 | | `configFile` | `null` 或 `path` | `null` | 指向现有 `config.yaml` 的路径。若设置,则完全覆盖 `settings` | ### 密钥与环境 {#secrets--environment} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `environmentFiles` | `listOf str` | `[]` | 包含密钥的环境文件路径。在激活时合并到 `$HERMES_HOME/.env` | | `environment` | `attrsOf str` | `{}` | 非密钥环境变量。**可见于 Nix 存储** —— 请勿在此处放置密钥 | | `authFile` | `null` 或 `path` | `null` | OAuth 凭据种子文件。仅在首次部署时复制 | | `authFileForceOverwrite` | `bool` | `false` | 在激活时始终从 `authFile` 覆盖 `auth.json` | ### 文档 {#documents-1} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `documents` | `attrsOf (either str path)` | `{}` | 工作区文件。键为文件名,值为内联字符串或路径。在激活时安装到 `workingDirectory` | ### MCP 服务器 {#mcp-servers-1} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `mcpServers` | `attrsOf submodule` | `{}` | MCP 服务器定义,合并到 `settings.mcp_servers` | | `mcpServers..command` | `null` 或 `str` | `null` | 服务器命令(标准输入输出传输) | | `mcpServers..args` | `listOf str` | `[]` | 命令参数 | | `mcpServers..env` | `attrsOf str` | `{}` | 服务器进程的环境变量 | | `mcpServers..url` | `null` 或 `str` | `null` | 服务器端点 URL(HTTP/StreamableHTTP 传输) | | `mcpServers..headers` | `attrsOf str` | `{}` | HTTP 头信息,例如 `Authorization` | | `mcpServers..auth` | `null` 或 `"oauth"` | `null` | 认证方式。`"oauth"` 启用 OAuth 2.1 PKCE | | `mcpServers..enabled` | `bool` | `true` | 启用或禁用此服务器 | | `mcpServers..timeout` | `null` 或 `int` | `null` | 工具调用超时时间(秒),默认为 120 | | `mcpServers..connect_timeout` | `null` 或 `int` | `null` | 连接超时时间(秒),默认为 60 | | `mcpServers..tools` | `null` 或 `submodule` | `null` | 工具过滤配置(`include`/`exclude` 列表) | | `mcpServers..sampling` | `null` 或 `submodule` | `null` | 服务器发起的 LLM 请求的采样配置 | ### 服务行为 {#service-behavior} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `extraArgs` | `listOf str` | `[]` | 传递给 `hermes gateway` 的额外参数 | | `extraPackages` | `listOf package` | `[]` | 服务 PATH 上的额外包(仅原生模式) | | `restart` | `str` | `"always"` | systemd `Restart=` 策略 | | `restartSec` | `int` | `5` | systemd `RestartSec=` 值 | ### 容器 {#container} | 选项 | 类型 | 默认值 | 描述 | |---|---|---|---| | `container.enable` | `bool` | `false` | 启用 OCI 容器模式 | | `container.backend` | `enum ["docker" "podman"]` | `"docker"` | 容器运行时 | | `container.image` | `str` | `"ubuntu:24.04"` | 基础镜像(运行时拉取) | | `container.extraVolumes` | `listOf str` | `[]` | 额外的卷挂载(`host:container:mode` 格式) | | `container.extraOptions` | `listOf str` | `[]` | 传递给 `docker create` 的额外参数 | --- ## 目录结构 {#directory-layout} ### 原生模式 {#native-mode} ``` /var/lib/hermes/ # stateDir(由 hermes:hermes、0750 拥有) ├── .hermes/ # HERMES_HOME │ ├── config.yaml # Nix 生成(深度合并每个重建) │ ├── .managed # 标记:CLI 配置突变被阻止 │ ├── .env # 由环境 + 环境文件合并 │ ├── auth.json # OAuth 凭证(种子,然后自我管理) │ ├── gateway.pid │ ├── state.db │ ├── mcp-tokens/ # OAuth tokens 适用于 MCP 服务器 │ ├── sessions/ │ ├── memories/ │ ├── skills/ │ ├── cron/ │ └── logs/ ├── home/ # Agent HOME └── workspace/ # MESSAGING_CWD ├── SOUL.md # 从文档选项 └── (agent-created files) ``` ### 容器模式 {#container-mode} 相同布局,挂载至容器中: | 容器路径 | 主机路径 | 模式 | 说明 | |---|---|---|---| | `/nix/store` | `/nix/store` | `ro` | Hermes 二进制文件 + 所有 Nix 依赖 | | `/data` | `/var/lib/hermes` | `rw` | 所有状态、配置、工作区 | | `/home/hermes` | `${stateDir}/home` | `rw` | 持久化 Agent 主目录 — `pip install --user`、工具缓存 | | `/usr`, `/usr/local`, `/tmp` | (可写层) | `rw` | `apt`/`pip`/`npm` 安装 — 重启后仍保留,重建容器时丢失 | --- ## 更新 {#updating} ```bash # 更新 flake 输入 nix flake update hermes-agent --flake /etc/nixos # 重建 sudo nixos-rebuild switch ``` 在容器模式下,`current-package` 符号链接会被更新,Agent 在重启时会自动加载新二进制文件。无需重建容器,也不会丢失已安装的包。 --- ## 故障排除 {#troubleshooting} :::tip Podman 用户 下面所有的 `docker` 命令在 `podman` 中使用方式相同。如果设置了 `container.backend = "podman"`,请相应替换。 ::: ### 服务日志 {#service-logs} ```bash # 错误 500(服务器错误)!!1500。这是一个错误。出现错误。请稍后重试。我们只知道这些。 journalctl -u hermes-agent -f # 容器模式:也可直接使用 docker logs -f hermes-agent ``` ### 容器检查 {#container-inspection} ```bash systemctl status hermes-agent docker ps -a --filter name=hermes-agent docker inspect hermes-agent --format='{{.State.Status}}' docker exec -it hermes-agent bash docker exec hermes-agent readlink /data/current-package docker exec hermes-agent cat /data/.container-identity ``` ### 强制重建容器 {#force-container-recreation} 如果需要重置可写层(全新 Ubuntu 环境): ```bash sudo systemctl stop hermes-agent docker rm -f hermes-agent sudo rm /var/lib/hermes/.container-identity sudo systemctl start hermes-agent ``` ### 验证密钥已加载 {#verify-secrets-are-loaded} 如果 Agent 启动但无法与 LLM 提供商认证,请检查 `.env` 文件是否正确合并: ```bash # 本机模式 sudo -u hermes cat /var/lib/hermes/.hermes/.env # 容器模式 docker exec hermes-agent cat /data/.hermes/.env ``` ### GC 根验证 {#gc-root-verification} ```bash nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package) ``` ### 常见问题 {#common-issues} | 现象 | 原因 | 解决方法 | |---|---|---| | `Cannot save configuration: managed by NixOS` | CLI 保护机制启用 | 编辑 `configuration.nix` 并执行 `nixos-rebuild switch` | | 容器意外重建 | `extraVolumes`、`extraOptions` 或 `image` 发生变化 | 正常行为 — 可写层重置。需重新安装包或使用自定义镜像 | | `hermes version` 显示旧版本 | 容器未重启 | 执行 `systemctl restart hermes-agent` | | `/var/lib/hermes` 权限拒绝 | 状态目录权限为 `0750 hermes:hermes` | 使用 `docker exec` 或 `sudo -u hermes` | | `nix-collect-garbage` 删除了 hermes | GC 根缺失 | 重启服务(preStart 会重新创建 GC 根) | --- ### 快速入门 - URL: https://hermesagent.org.cn/docs/getting-started/quickstart - Path: getting-started/quickstart.md - Category: getting-started - Description: 你与 Hermes Agent 的首次对话 —— 从安装到两分钟内开始聊天 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/getting-started/quickstart.md - Translated At: 2026-04-11T03:25:47.226Z - Headings: 1. 安装 Hermes Agent | 类 Linux / macOS / WSL2 | Windows 原生 PowerShell | 类 Unix / WSL2 | Windows PowerShell | 2. 配置大模型提供商 | 3. 开始对话 | 4. 尝试核心功能 | 让它使用终端 | 使用斜杠命令 | 多行输入 | 中断 Agent # 快速入门 {#quickstart} :::tip 安装遇到困难? 点击加入 [中文社区微信群](/community),提问并获取群内专家帮助。 **完全没有经验?** 强烈建议先下载 [WorkBuddy](https://www.workbuddy.cn/)(微信扫码即用,无需任何配置),然后让它安装中文社区文档 MCP 来协助你安装 Hermes Agent。如果后续 Hermes 出现问题,也可以让 WorkBuddy 对其进行修复,反之亦然——两个 Agent 互为主备,这是社区推荐的最佳方案。 **电脑上已经有 Agent?** 如果你已经在用龙虾 [OpenClaw](https://github.com/openclaw/openclaw) 或国内版本([QClaw](https://qclaw.qq.com/)、[AutoClaw](https://autoglm.zhipuai.cn/autoclaw/)),或者 [Trae](https://www.trae.ai/)、[Claude Code](https://claude.ai/code)、[Codex](https://openai.com/index/introducing-codex/)、[Cursor](https://www.cursor.com/)、[Qoder](https://qoder.ai/) 等 Coding Agent,都可以让它读文档来协助你完成安装,你可以不用关心任何技术细节。 **如何让你的 Agent 接入中文社区文档?** - **方式一(最简单)**:把中文社区网址 [https://hermesagent.org.cn](https://hermesagent.org.cn) 发给它,让它自己访问并阅读文档。 - **方式二(更精准,推荐)**:直接把下面这段话复制发给你的 Agent,它会自己完成配置: ```agent-prompt 请把这个 Hermes 中文文档 MCP server 加到你的配置里: https://mcp.hermesagent.org.cn/v1 (Streamable HTTP,无需 API Key、无需登录) 加完后用它帮我查 Hermes Agent 中文文档来指导我完成安装。 ``` - 方式二配好后,Agent 就能按关键词直接检索并读取中文社区全部文档的全文。 **其他求助途径**:也可以先询问 [豆包](https://www.doubao.com/)、[DeepSeek](https://chat.deepseek.com/) 等 AI 助手。 ::: 本指南将引导你完成安装 Hermes Agent、配置大模型提供商,并与 Hermes Agent进行首次对话。 ## 1. 安装 Hermes Agent {#1-install-hermes-agent} ### 类 Linux / macOS / WSL2 ```bash curl -fsSL https://res1.hermesagent.org.cn/install.sh | bash ``` ### Windows 原生 PowerShell ```powershell irm https://res1.hermesagent.org.cn/install.ps1 | iex ``` :::tip 什么是 PowerShell?怎么打开? - **PowerShell** 是 Windows 自带的命令行程序,可以理解成“Windows 里的终端”。 - 打开方式:按一下键盘左下角 **Windows 键**,输入 `PowerShell`,然后点击 **Windows PowerShell** 或 **PowerShell**。 - 如果你看到的是 **Windows Terminal** 也没关系,只要里面开的标签页是 **PowerShell** 即可。 - **不要**把上面的命令粘贴到浏览器地址栏、资源管理器地址栏,或“运行”对话框里。 ::: :::tip Windows 用户 - **想直接在 Windows 本机安装**:运行上面的 `install.ps1`。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以原生安装了。 - **偏好 Linux / Ubuntu 终端工作流**:可以先安装 [WSL2](https://zhuanlan.zhihu.com/p/466001838),再在 WSL2 终端里运行上面的 `install.sh`。 - **WSL2 是什么?** 可以把它理解成“Windows 里的 Linux 终端环境”。它是可选路径,不是 Windows 用户安装 Hermes Agent 的前置条件。 - 详细说明请看 [Windows 安装指南](windows-installation)。 ::: :::tip 中国大陆网络环境提示 当前页的一键安装命令已经由 **Hermes Agent 中文社区** 提供 **国内镜像加速**,默认优先走国内可直连链路。 为了提高中国大陆用户的安装体验,镜像版安装器默认精简了部分国人不常用、或体积较大且经常受外网影响的可选功能,例如浏览器自动化、Chromium 下载、WhatsApp 桥接等。建议先完成核心安装,确认 Hermes Agent 可以正常运行;之后可让 Hermes Agent 自身补全这些能力。 如果你需要继续处理 WSL 网络、终端代理或手动镜像配置,可参考: - **WSL 安装(中文)**:[Windows 10/11 安装 WSL2 指南](https://zhuanlan.zhihu.com/p/466001838) - **WSL 网络 / autoProxy(官方)**:[Microsoft Learn - Accessing network applications with WSL](https://learn.microsoft.com/en-us/windows/wsl/networking) - **Python / pip 镜像说明**:[清华 TUNA - PyPI 镜像帮助](https://mirror.tuna.tsinghua.edu.cn/help/pypi/) - **Node.js / npm 镜像说明**:[清华 TUNA - NodeJS Release 镜像帮助](https://mirror.tuna.tsinghua.edu.cn/help/nodejs-release/) / [npmmirror](https://npmmirror.com/) ::: 安装完成后: #### 类 Unix / WSL2 ```bash source ~/.bashrc # 或:source ~/.zshrc ``` #### Windows PowerShell ```powershell # 关闭并重新打开 PowerShell 即可 ``` 如果你是第一次接触 Windows 命令行,建议直接继续看 **[Windows 安装指南](windows-installation)**,里面把: - 什么是 PowerShell - 怎么打开 PowerShell - 什么时候需要管理员 PowerShell - PowerShell 直装的完整步骤 都拆开写了。 ## 2. 配置大模型提供商 {#2-set-up-a-provider} 安装程序会自动为你配置 LLM 提供商。如需后续更改,可使用以下任一命令: ```bash hermes model # 选择大语言模型提供商和模型 hermes tools # 配置启用哪些工具 hermes setup # 或一次性完成全部配置 ``` `hermes model` 会引导你选择推理提供者: | 提供者 | 是什么 | 如何配置 | |--------|--------|----------| | **Nous Portal** | 基于订阅、零配置 | 通过 `hermes model` 进行 OAuth 登录 | | **OpenAI Codex** | ChatGPT OAuth,使用 Codex 模型 | 通过 `hermes model` 进行设备码认证 | | **Anthropic** | 直接使用 Claude 模型(Pro/Max 或 API 密钥) | 使用 `hermes model` 进行 Claude Code 认证,或提供 Anthropic API 密钥 | | **OpenRouter** | 跨多种模型的多提供者路由 | 输入你的 API 密钥 | | **Z.AI** | GLM / Zhipu 托管模型 | 设置 `GLM_API_KEY` / `ZAI_API_KEY` | | **Kimi / Moonshot** | Moonshot 托管的代码与聊天模型 | 设置 `KIMI_API_KEY` | | **MiniMax** | 国际 MiniMax 接口 | 设置 `MINIMAX_API_KEY` | | **MiniMax 中国区** | 中国区域 MiniMax 接口 | 设置 `MINIMAX_CN_API_KEY` | | **阿里云** | 通过 DashScope 使用 Qwen 模型 | 设置 `DASHSCOPE_API_KEY` | | **Hugging Face** | 通过统一路由使用 20+ 开源模型(Qwen、DeepSeek、Kimi 等) | 设置 `HF_TOKEN` | | **Kilo Code** | KiloCode 托管模型 | 设置 `KILOCODE_API_KEY` | | **OpenCode Zen** | 按使用量付费访问精选模型 | 设置 `OPENCODE_ZEN_API_KEY` | | **OpenCode Go** | 每月 $10 订阅,访问开源模型 | 设置 `OPENCODE_GO_API_KEY` | | **DeepSeek** | 直接访问 DeepSeek API | 设置 `DEEPSEEK_API_KEY` | | **GitHub Copilot** | GitHub Copilot 订阅(GPT-5.x、Claude、Gemini 等) | 通过 `hermes model` 进行 OAuth,或设置 `COPILOT_GITHUB_TOKEN` / `GH_TOKEN` | | **GitHub Copilot ACP** | Copilot ACP Agent 后端(启动本地 `copilot` CLI) | 使用 `hermes model`(需安装 `copilot` CLI 并执行 `copilot login`) | | **Vercel AI Gateway** | Vercel AI Gateway 路由 | 设置 `AI_GATEWAY_API_KEY` | | **自定义端点** | VLLM、SGLang、Ollama 或任何 OpenAI 兼容 API | 设置基础 URL + API 密钥 | :::tip 你可以随时通过 `hermes model` 切换提供者——无需修改代码,无锁定风险。配置自定义端点时,Hermes 会提示你输入上下文窗口大小,并在可能的情况下自动检测。详情请参见 [上下文长度检测](../integrations/providers#context-length-detection)。 ::: ## 3. 开始对话 {#3-start-chatting} ```bash hermes ``` 完成!你将看到包含模型信息、可用工具和技能的欢迎横幅。输入消息并按 Enter 键。 ``` ❯ 你现在能帮我做什么? ``` 该 Agent 已具备访问网络搜索、文件操作、终端命令等工具的能力——开箱即用。 ## 4. 尝试核心功能 {#4-try-key-features} ### 让它使用终端 {#ask-it-to-use-the-terminal} ``` ❯ 帮我看看磁盘空间占用情况,并列出最大的 5 个目录。 ``` Agent 将代表你执行终端命令,并显示结果。 ### 使用斜杠命令 {#use-slash-commands} 输入 `/` 可查看所有命令的自动补全下拉菜单: | 命令 | 功能 | |------|------| | `/help` | 显示所有可用命令 | | `/tools` | 列出可用工具 | | `/model` | 交互式切换模型 | | `/personality pirate` | 尝试有趣的个性模式 | | `/save` | 保存对话 | ### 多行输入 {#multi-line-input} 按 `Alt+Enter` 或 `Ctrl+J` 可换行。非常适合粘贴代码或撰写详细提示。 ### 中断 Agent {#interrupt-the-agent} 如果 Agent 运行时间过长,只需输入新消息并按 Enter——它将中断当前任务并切换到你的新指令。`Ctrl+C` 也有效。 ### 恢复会话 {#resume-a-session} 退出时,hermes 会打印出恢复命令: ```bash hermes --continue # 恢复最近一次会话 hermes -c # 简写形式 ``` ## 5. 进一步探索 {#5-explore-further} 以下是一些你可以尝试的进阶操作: ### 设置沙箱终端 {#set-up-a-sandboxed-terminal} 为确保安全,建议在 Docker 容器或远程服务器上运行 Agent: ```bash hermes config set terminal.backend docker # 使用 Docker 隔离终端 hermes config set terminal.backend ssh # 把终端切到远程服务器 ``` ### 连接消息平台 {#connect-messaging-platforms} 通过微信、飞书、QQ、Discord、WhatsApp、Signal、电子邮件或 Home Assistant 从手机或其他设备与 Hermes 对话: ```bash hermes gateway setup # 交互式配置消息平台 ``` ### 添加语音模式 {#add-voice-mode} 希望在 CLI 中使用麦克风输入,或在消息中获得语音回复? ```bash pip install "hermes-agent[voice]" # 可选,但推荐:启用免费的本地语音转文字 pip install faster-whisper ``` 然后启动 Hermes 并在 CLI 中启用语音模式: ```text /voice on ``` 按 `Ctrl+B` 开始录音,或使用 `/voice tts` 让 Hermes 朗读其回复。完整设置请参见 [语音模式](../user-guide/features/voice-mode),涵盖 CLI、Telegram、Discord 及 Discord 语音频道。 ### 安排自动化任务 {#schedule-automated-tasks} ``` ❯ 每天早上 9 点检查 Hacker News 上的 AI 新闻,并通过飞书给我发一份摘要。 ``` Agent 将通过网关自动设置一个 cron 任务,定时运行。 ### 浏览并安装技能 {#browse-and-install-skills} ```bash hermes skills search kubernetes hermes skills search react --source skills-sh hermes skills search https://mintlify.com/docs --source well-known hermes skills install openai/skills/k8s hermes skills install official/security/1password hermes skills install skills-sh/vercel-labs/json-render/json-render-react --force ``` 提示: - 使用 `--source skills-sh` 搜索公共的 `skills.sh` 目录。 - 使用 `--source well-known` 并配合文档/网站 URL,从 `/.well-known/skills/index.json` 发现技能。 - 仅在审查第三方技能后使用 `--force`。它可覆盖非危险策略块,但无法覆盖 `dangerous` 扫描结论。 也可在聊天中使用 `/skills` 斜杠命令。 ### 通过 ACP 在编辑器中使用 Hermes {#use-hermes-inside-an-editor-via-acp} Hermes 还可作为 ACP 服务器运行,兼容 VS Code、Zed 和 JetBrains 等 ACP 编辑器: ```bash pip install -e '.[acp]' hermes acp ``` 有关设置详情,请参阅 [ACP 编辑器集成](../user-guide/features/acp)。 ### 尝试 MCP 服务器 {#try-mcp-servers} 通过模型上下文协议(Model Context Protocol)连接外部工具: ```yaml # 添加到 ~/.hermes/config.yaml mcp_servers: github: command: npx args: ["-y", "@modelcontextprotocol/server-github"] env: GITHUB_PERSONAL_ACCESS_TOKEN: "ghp_xxx" ``` --- ## 快速参考 {#quick-reference} | 命令 | 描述 | |------|------| | `hermes` | 开始聊天 | | `hermes model` | 选择你的大语言模型(LLM)提供商和模型 | | `hermes tools` | 配置各平台启用的工具 | | `hermes setup` | 完整设置向导(一次性配置所有内容) | | `hermes doctor` | 诊断问题 | | `hermes update` | 更新至最新版本 | | `hermes gateway` | 启动消息网关 | | `hermes --continue` | 恢复上次会话 | ## 下一步 {#next-steps} - **[CLI 指南](../user-guide/cli)** — 掌握终端界面 - **[配置](../user-guide/configuration)** — 自定义你的设置 - **[消息网关](../user-guide/messaging)** — 连接微信、飞书、QQ、Discord、WhatsApp、Signal、电子邮件或 Home Assistant - **[工具与工具集](../user-guide/features/tools)** — 探索可用功能 --- ### 安装后的配置教程 - URL: https://hermesagent.org.cn/docs/getting-started/setup-wizard - Path: getting-started/setup-wizard.md - Category: getting-started - Description: Hermes Agent 配置向导(Setup Wizard)胎教级别教程 - Headings: 第一步:进入配置向导 | 第二步:选择模型提供商 | 输入 API 密钥 | 选择具体模型 | 第三步:选择终端后端 | 第四步:配置消息平台(可选) | 4.1 选择飞书 | 4.2 选择飞书应用创建方式 | 4.3 在浏览器中创建飞书应用 | 4.4 回到终端完成配置 | 第五步:启动 Hermes | 第六步:绑定飞书机器人(如果上一步配置了飞书) # 安装后的配置教程 这是一篇给中文用户准备的 **Hermes Agent 配置向导(Setup Wizard)胎教级别教程**。 :::info 适用环境 本教程以 Ubuntu 系统为例,同样适用于 Windows 原生 PowerShell、Windows WSL2 及 Linux 服务器上的安装场景;如果你使用 Windows 原生安装,直接在 PowerShell 中运行同名 `hermes` 命令即可。 ::: :::tip 开始之前 - **前置条件**:你已经通过中文社区的安装指令完成了 Hermes Agent 的安装。如果还没有,请先看 [安装教程](./installation) - **预计耗时**:约 10 分钟 - **你需要准备**:一个大模型提供商的账号(本教程以 [DeepSeek 开放平台](https://platform.deepseek.com/) 的 deepseek-v4-flash 模型为例,价格低廉、性能优秀);一个 [飞书](https://www.feishu.cn/) 账号(用于配置消息平台) ::: 整个配置分为三大步:**选择模型提供商** → **选择终端后端** → **配置消息平台(可选)**。下面一步步来。 --- ## 第一步:进入配置向导 ![安装完成界面](./img/setup-wizard/01-install-complete.png) 如果你已经看到了类似上图的界面,说明 Hermes Agent 已经安装完成了。 在这个界面输入 `1` 并按回车,进入快速设置模式。 --- ## 第二步:选择模型提供商 ![模型提供商选择](./img/setup-wizard/02-select-provider.png) 接下来会出现模型提供商选择界面。**模型提供商**就是为 Hermes 提供 AI 大脑的服务商,你需要选一个来驱动 Hermes。 :::tip 不知道选哪个? **国内用户推荐选 16. DeepSeek**——注册简单、价格便宜、国内直连不需要翻墙。本教程以 DeepSeek 为例。 ::: 使用方向键 ↑↓ 移动光标到你想要的提供商上,按回车确认。
完整提供商列表及中文对照(点击展开) | 原文 | 中文翻译 | | --- | --- | | 1. Nous Portal (Nous Research subscription) | 1. Nous Portal(Nous Research 官方订阅服务) | | 2. OpenRouter (100+ models, pay-per-use) | 2. OpenRouter 中转站(100+ 模型,按量付费) | | 3. NovitaAI (AI-native cloud: Model API, Agent Sandbox, GPU Cloud) | 3. NovitaAI(AI 原生云:模型 API、Agent 沙箱、GPU 云) | | 4. LM Studio (local desktop app with built-in model server) | 4. LM Studio(本地桌面应用,内置模型服务器) | | 5. Anthropic (Claude models — API key or Claude Code) | 5. Anthropic(Claude 模型 —— 使用 API 密钥或 Claude Code) | | 6. OpenAI Codex | 6. OpenAI Codex | | 7. Qwen Cloud / DashScope Coding (Qwen + multi-provider) | 7. 通义千问云 / DashScope Coding(Qwen + 多提供商能力) | | 8. Xiaomi MiMo (MiMo-V2.5 and V2 models — pro, omni, flash) | 8. 小米 MiMo(MiMo-V2.5 及 V2 系列模型 —— pro、omni、flash) | | 9. Tencent TokenHub (Hy3 Preview — direct API via tokenhub.tencentmaas.com) | 9. 腾讯 TokenHub(混元 Hy3 预览版 —— 通过 tokenhub.tencentmaas.com 直连) | | 10. NVIDIA NIM (Nemotron models — build.nvidia.com or local NIM) | 10. NVIDIA NIM(Nemotron 模型 —— build.nvidia.com 或本地 NIM) | | 11. GitHub Copilot (uses GITHUB_TOKEN or gh auth token) | 11. GitHub Copilot(使用 `GITHUB_TOKEN` 或 `gh` 登录 token) | | 12. GitHub Copilot ACP (spawns `copilot --acp --stdio`) | 12. GitHub Copilot ACP(启动 `copilot --acp --stdio`) | | 13. Hugging Face Inference Providers (20+ open models) | 13. Hugging Face Inference Providers(20+ 开源模型) | | 14. Google AI Studio (Gemini models — native Gemini API) | 14. Google AI Studio(Gemini 模型 —— 原生 Gemini API) | | 15. Google Gemini via OAuth + Code Assist (free tier supported; no API key needed) | 15. Google Gemini OAuth + Code Assist(支持免费额度,无需 API 密钥) | | 16. DeepSeek (DeepSeek-V3, R1, coder — direct API) | 16. DeepSeek(DeepSeek-V3、R1、Coder —— 官方直连 API) | | 17. xAI (Grok models — direct API) | 17. xAI(Grok 模型 —— 官方直连 API) | | 18. Z.AI / GLM (Zhipu AI direct API) | 18. Z.AI / GLM(智谱 AI 官方直连 API) | | 19. Kimi Coding Plan (api.kimi.com) & Moonshot API | 19. Kimi Coding Plan(api.kimi.com)& Moonshot API | | 20. Kimi / Moonshot China (Moonshot CN direct API) | 20. Kimi / Moonshot China(Moonshot 中国区官方直连 API) | | 21. StepFun Step Plan (agent/coding models via Step Plan API) | 21. 阶跃星辰 StepFun Step Plan(通过 Step Plan API 使用 agent/coding 模型) | | 22. MiniMax (global direct API) | 22. MiniMax(国际版官方直连 API) | | 23. MiniMax via OAuth browser login (Coding Plan, minimax.io) | 23. MiniMax OAuth 浏览器登录(Coding Plan,minimax.io) | | 24. MiniMax China (domestic direct API) | 24. MiniMax China(国内版官方直连 API) | | 25. Ollama Cloud (cloud-hosted open models — ollama.com) | 25. Ollama Cloud(云托管开源模型 —— ollama.com) | | 26. Arcee AI (Trinity models — direct API) | 26. Arcee AI(Trinity 系列模型 —— 官方直连 API) | | 27. GMI Cloud (multi-model direct API) | 27. GMI Cloud(多模型直连 API) | | 28. Kilo Code (Kilo Gateway API) | 28. Kilo Code(Kilo Gateway API) | | 29. OpenCode Zen (35+ curated models, pay-as-you-go) | 29. OpenCode Zen(35+ 精选模型,按量付费) | | 30. OpenCode Go (open models, $10/month subscription) | 30. OpenCode Go(开放模型,10 美元/月订阅) | | 31. AWS Bedrock (Claude, Nova, Llama, DeepSeek — IAM or API key) | 31. AWS Bedrock(Claude、Nova、Llama、DeepSeek —— IAM 或 API 密钥) | | 32. Azure Foundry (OpenAI-style or Anthropic-style endpoint — your Azure AI deployment) | 32. Azure Foundry(OpenAI 风格或 Anthropic 风格端点 —— 你的 Azure AI 部署) | | 33. Vercel AI Gateway | 33. Vercel AI Gateway | | 34. Qwen OAuth (reuses local Qwen CLI login) | 34. Qwen OAuth(复用本地 Qwen CLI 登录状态) | | 35. Alibaba Cloud Coding Plan — dedicated coding tier | 35. 阿里云 Coding Plan —— 专属 coding 套餐 | | 36. custom (direct API) | 36. 自定义(直连 API) | | 37. Custom endpoint (enter URL manually) | 37. 自定义端点(手动输入 URL) | | 38. Configure auxiliary models... | 38. 配置辅助模型… | | 39. Leave unchanged | 39. 保持不变 |
### 输入 API 密钥 选择提供商后,会提示你输入 API Key(API 密钥)。 > **什么是 API 密钥?** 可以理解为一把"钥匙",让 Hermes 能以你的身份调用大模型服务。每个提供商都可以在其后台免费生成。 ![输入 API Key](./img/setup-wizard/03-enter-api-key.png) 这时需要前往模型提供商的后台生成密钥。以 DeepSeek 为例,打开 https://platform.deepseek.com/api_keys ,创建一个 API 密钥并复制: ![DeepSeek 后台创建 API 密钥](./img/setup-wizard/04-deepseek-api-key.png) 然后回到终端窗口中粘贴(可右键选择粘贴)并回车。 :::caution 粘贴后看不到内容? 这是正常的!为了保护密钥安全,终端不会显示你粘贴的内容。直接按回车即可。 ::: ![粘贴 API Key](./img/setup-wizard/05-paste-api-key.png) ### 选择具体模型 稍等片刻,Hermes 会向 DeepSeek 发送请求获取可用的模型列表。 选择你想用的模型。这里我选 **deepseek-v4-flash**(社区比较推荐的模型,智力在线且便宜),输入对应编号并回车: ![选择模型](./img/setup-wizard/06-select-model.png) --- ## 第三步:选择终端后端 ![终端后端选择](./img/setup-wizard/07-terminal-backend.png) 接下来是 **Terminal Backend(终端后端)** 选择。简单来说就是:Hermes 在**哪里**执行命令和代码? | 选项 | 说明 | | --- | --- | | **Local**(默认) | 直接在你的电脑上执行,最简单,推荐新手选这个 | | Docker | 在 Docker 容器中运行,与系统隔离,需要先安装 Docker | | Modal | 使用 Modal 云平台运行,按量计费 | | SSH | 通过 SSH 连接到远程服务器执行 | | Daytona | 使用 Daytona 持久化云开发环境 | | Vercel Sandbox | Vercel 提供的云端微虚拟机 | | Singularity/Apptainer | 面向超算/HPC 集群的容器方案,适合学术科研场景 | | Keep current | 保持当前设置不变 | **大多数用户直接选 Local(默认)即可**,按回车跳过。 --- ## 第四步:配置消息平台(可选) :::tip 可以跳过 如果你只想先在终端里体验 Hermes,可以选择 **Skip** 跳过这一步。之后随时可以通过 `hermes setup` 重新配置。 ::: ![消息平台选择](./img/setup-wizard/08-messaging-platform.png) 消息平台指的是把 Hermes 接入飞书、微信、Discord 等聊天工具,让你可以在手机上跟 Hermes 对话。目前社区最推荐的是**飞书**,下面以飞书为例。 ### 4.1 选择飞书 使用方向键选中 **Feishu / Lark** 并回车: ![选择飞书](./img/setup-wizard/09-feishu-select.png) ### 4.2 选择飞书应用创建方式 这个界面问你用哪种方式创建飞书应用,选第一个(自动创建)回车即可: ![飞书创建方式](./img/setup-wizard/10-feishu-setup-method.png) ### 4.3 在浏览器中创建飞书应用 终端会显示一个 `open.feishu.cn` 开头的链接,把它复制到浏览器中打开: ![复制飞书链接](./img/setup-wizard/11-feishu-open-link.png) 在打开的页面中,给你的飞书应用起个名字(随便取,比如"Hermes助手"),然后点击**立即创建**: ![设定应用名称](./img/setup-wizard/12-feishu-create-app-name.png) ![创建完成](./img/setup-wizard/13-feishu-create-app-done.png) ### 4.4 回到终端完成配置 回到终端,接下来会有几个确认界面。 这一步是确认应用已经创建好了,直接回车: ![确认应用创建](./img/setup-wizard/14-feishu-confirm-1.png) 这一步是确认权限配置,同样回车: ![确认权限配置](./img/setup-wizard/15-feishu-confirm-2.png) Hermes 会自动为飞书应用配置所需的权限: ![权限配置中](./img/setup-wizard/16-feishu-permissions.png) 看到 **DM pairing enabled**(私聊配对已开启)后,说明飞书应用配置成功了。继续回车: ![DM pairing 完成](./img/setup-wizard/17-feishu-dm-pairing.png) --- ## 第五步:启动 Hermes 配置完成!现在关掉当前终端窗口,打开一个**新的终端**,输入以下命令: ```bash hermes ``` 你会看到 Hermes 的聊天界面,可以直接在这里跟它对话了: ![Hermes 聊天界面](./img/setup-wizard/18-hermes-chat.png) --- ## 第六步:绑定飞书机器人(如果上一步配置了飞书) 如果你在第四步配置了飞书,还需要一个"配对"步骤,让飞书机器人和你的 Hermes 绑定在一起。 ### 6.1 在飞书中给机器人发一条消息 打开飞书,找到你刚创建的机器人(就是第 4.3 步起的那个名字),随便发一句话给它: ![给飞书机器人发消息](./img/setup-wizard/19-feishu-bot-message.png) ### 6.2 在终端中执行配对命令 机器人收到消息后,Hermes 终端会显示一条 `hermes pairing approve` 开头的命令。打开一个**新终端**,把这条命令粘贴进去并回车: ![执行配对命令](./img/setup-wizard/20-pairing-approve.png) 看到类似下图的确认信息,说明配对成功: ![配对成功](./img/setup-wizard/21-pairing-done.png) ### 6.3 验证 现在回到飞书,给机器人发条消息试试,它应该能正常回复了: ![飞书机器人正常工作](./img/setup-wizard/22-feishu-working.png) --- ## 配置完成 恭喜!Hermes Agent 已经配置完成并可以正常使用了。你可以: - **在终端中对话**:打开终端输入 `hermes` 开始聊天 - **在飞书中对话**:直接给机器人发消息 - **重新配置**:随时运行 `hermes setup` 修改设置 如果遇到问题,欢迎来社区提问: - 社区官网:https://hermesagent.org.cn - 微信群入口:https://hermesagent.org.cn/community --- ### Android / Termux - URL: https://hermesagent.org.cn/docs/getting-started/termux - Path: getting-started/termux.md - Category: getting-started - Description: 使用 Termux 在 Android 手机上直接运行 Hermes Agent - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/getting-started/termux.md - Translated At: 2026-04-11T03:26:17.674Z - Headings: 经验证路径支持哪些功能? | 目前尚未包含在验证路径中的功能? | 选项 1:一键安装器 | 选项 2:手动安装(完全显式) | 1. 更新 Termux 并安装系统包 | 2. 克隆 Hermes | 3. 创建虚拟环境 | 4. 安装经验证的 Termux 包 | 5. 将 hermes 加入 Termux PATH | 6. 验证安装 | 7. 启动 Hermes | 推荐后续设置 # 在 Android 上使用 Termux 运行 Hermes {#hermes-on-android-with-termux} 这是通过 [Termux](https://termux.dev/) 在 Android 手机上直接运行 Hermes Agent 的经过验证的路径。 该方案为你在手机上提供一个可工作的本地 CLI,以及目前确认可在 Android 上干净安装的核心附加功能。 ## 经验证路径支持哪些功能? {#what-is-supported-in-the-tested-path} 经验证的 Termux 包含以下组件: - Hermes CLI - cron 支持 - PTY/后台终端支持 - MCP 支持 - Honcho 记忆支持 - ACP 支持 具体对应如下: ```bash python -m pip install -e '.[termux]' -c constraints-termux.txt ``` ## 目前尚未包含在验证路径中的功能? {#what-is-not-part-of-the-tested-path-yet} 一些功能仍需要桌面/服务器风格的依赖项,这些依赖项尚未发布适用于 Android 的版本,或尚未在手机上验证通过: - `.[all]` 当前不支持 Android - `voice` 附加功能受阻于 `faster-whisper -> ctranslate2`,而 `ctranslate2` 未发布 Android 的 wheel 包 - Termux 安装器会跳过自动浏览器 / Playwright 启动流程 - Docker 基于的终端隔离功能在 Termux 内不可用 这并不妨碍 Hermes 作为原生手机 CLI Agent 良好运行——只是意味着推荐的移动端安装路径有意比桌面/服务器安装路径更窄。 --- ## 选项 1:一键安装器 {#option-1-one-line-installer} Hermes 现在提供一个对 Termux 友好的安装路径: ```bash curl -fsSL https://res1.hermesagent.org.cn/install.sh | bash ``` 在 Termux 中,安装器会自动执行以下操作: - 使用 `pkg` 安装系统包 - 使用 `python -m venv` 创建虚拟环境 - 使用 `pip` 安装 `.[termux]` - 将 `hermes` 链接到 `$PREFIX/bin`,使其保留在 Termux 的 PATH 中 - 跳过未经测试的浏览器 / WhatsApp 启动流程 如果你希望查看具体命令或需要调试安装失败问题,请使用下方的手动安装路径。 --- ## 选项 2:手动安装(完全显式) {#option-2-manual-install-fully-explicit} ### 1. 更新 Termux 并安装系统包 {#1-update-termux-and-install-system-packages} ```bash pkg update pkg install -y git python clang rust make pkg-config libffi openssl nodejs ripgrep ffmpeg ``` 为何需要这些包? - `python` —— 运行时 + 虚拟环境支持 - `git` —— 克隆/更新仓库 - `clang`, `rust`, `make`, `pkg-config`, `libffi`, `openssl` —— 用于在 Android 上构建部分 Python 依赖项 - `nodejs` —— 可选 Node 运行时,用于超出验证核心路径的实验 - `ripgrep` —— 快速文件搜索 - `ffmpeg` —— 媒体 / TTS 转换 ### 2. 克隆 Hermes {#2-clone-hermes} ```bash git clone --recurse-submodules https://github.com/NousResearch/hermes-agent.git cd hermes-agent ``` 如果你已克隆但未包含子模块: ```bash git submodule update --init --recursive ``` ### 3. 创建虚拟环境 {#3-create-a-virtual-environment} ```bash python -m venv venv source venv/bin/activate export ANDROID_API_LEVEL="$(getprop ro.build.version.sdk)" python -m pip install --upgrade pip setuptools wheel ``` `ANDROID_API_LEVEL` 对于基于 Rust / maturin 的包(如 `jiter`)非常重要。 ### 4. 安装经验证的 Termux 包 {#4-install-the-tested-termux-bundle} ```bash python -m pip install -e '.[termux]' -c constraints-termux.txt ``` 如果你只需要最小核心 Agent,也可以使用以下命令: ```bash python -m pip install -e '.' -c constraints-termux.txt ``` ### 5. 将 `hermes` 加入 Termux PATH {#5-put-hermes-on-your-termux-path} ```bash ln -sf "$PWD/venv/bin/hermes" "$PREFIX/bin/hermes" ``` `$PREFIX/bin` 已在 Termux 的 PATH 中,因此该操作可使 `hermes` 命令在新 shell 中持久可用,无需每次重新激活虚拟环境。 ### 6. 验证安装 {#6-verify-the-install} ```bash hermes version hermes doctor ``` ### 7. 启动 Hermes {#7-start-hermes} ```bash hermes ``` --- ## 推荐后续设置 {#recommended-follow-up-setup} ### 配置模型 {#configure-a-model} ```bash hermes model ``` 或直接在 `~/.hermes/.env` 中设置密钥。 ### 稍后重新运行完整的交互式设置向导 {#re-run-the-full-interactive-setup-wizard-later} ```bash hermes setup ``` ### 手动安装可选的 Node 依赖项 {#install-optional-node-dependencies-manually} 经验证的 Termux 路径有意跳过 Node/浏览器启动流程。如果你希望后续进行实验: ```bash npm install ``` 请将 Android 上的浏览器 / WhatsApp 工具链视为实验性功能,直到另有文档说明。 --- ## 故障排除 {#troubleshooting} ### 安装 `.[all]` 时提示 `No solution found` {#no-solution-found-when-installing-all} 请改用经验证的 Termux 包: ```bash python -m pip install -e '.[termux]' -c constraints-termux.txt ``` 当前障碍是 `voice` 附加功能: - `voice` 依赖 `faster-whisper` - `faster-whisper` 依赖 `ctranslate2` - `ctranslate2` 未发布 Android 的 wheel 包 ### `uv pip install` 在 Android 上失败 {#uv-pip-install-fails-on-android} 请改用 Termux 路径,使用标准库虚拟环境 + `pip`: ```bash python -m venv venv source venv/bin/activate export ANDROID_API_LEVEL="$(getprop ro.build.version.sdk)" python -m pip install --upgrade pip setuptools wheel python -m pip install -e '.[termux]' -c constraints-termux.txt ``` ### `jiter` / `maturin` 报告 `ANDROID_API_LEVEL` 问题 {#jiter--maturin-complains-about-android_api_level} 安装前显式设置 API 级别: ```bash export ANDROID_API_LEVEL="$(getprop ro.build.version.sdk)" python -m pip install -e '.[termux]' -c constraints-termux.txt ``` ### `hermes doctor` 提示 ripgrep 或 Node 缺失 {#hermes-doctor-says-ripgrep-or-node-is-missing} 使用 Termux 包安装它们: ```bash pkg install ripgrep nodejs ``` ### 安装 Python 包时构建失败 {#build-failures-while-installing-python-packages} 请确保已安装构建工具链: ```bash pkg install clang rust make pkg-config libffi openssl ``` 然后重试: ```bash python -m pip install -e '.[termux]' -c constraints-termux.txt ``` --- ## 手机上的已知限制 {#known-limitations-on-phones} - Docker 后端不可用 - 通过 `faster-whisper` 实现的本地语音转录在验证路径中不可用 - 浏览器自动化设置被安装器有意跳过 - 某些可选附加功能可能可用,但目前仅 `.[termux]` 被记录为经过验证的 Android 包 如果你遇到新的 Android 特定问题,请在 GitHub 上提交问题并附上: - 你的 Android 版本 - `termux-info` - `python --version` - `hermes doctor` - 完整的安装命令和错误输出 --- ### 更新与卸载 - URL: https://hermesagent.org.cn/docs/getting-started/updating - Path: getting-started/updating.md - Category: getting-started - Description: 如何更新 Hermes Agent 到最新版本或卸载它 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/getting-started/updating.md - Translated At: 2026-04-11T03:26:28.640Z - Headings: 更新 | 更新期间发生的情况 | 推荐的更新后验证 | 检查当前版本 | 从消息平台更新 | 手动更新 | 回滚说明 | Nix 用户注意事项 | 卸载 | 手动卸载 # 更新与卸载 {#updating--uninstalling} ## 更新 {#updating} 通过一条命令即可更新到最新版本: ```bash hermes update ``` 此命令会拉取最新代码,更新依赖项,并提示你配置自上次更新以来新增的任何选项。 :::tip `hermes update` 会自动检测新增的配置选项,并提示你添加。如果你跳过了该提示,可以手动运行 `hermes config check` 来查看缺失的选项,然后运行 `hermes config migrate` 以交互方式添加它们。 ::: ### 更新期间发生的情况 {#what-happens-during-an-update} 当你运行 `hermes update` 时,将执行以下步骤: 1. **Git 拉取** — 从 `main` 分支拉取最新代码,并更新子模块 2. **依赖安装** — 运行 `uv pip install -e ".[all]"` 以获取新增或更改的依赖项 3. **配置迁移** — 检测自你当前版本以来新增的配置选项,并提示你设置它们 4. **网关自动重启** — 如果网关服务正在运行(Linux 上为 systemd,macOS 上为 launchd),在更新完成后将**自动重启**,使新代码立即生效 预期输出如下: ``` $ hermes update Updating Hermes Agent... 📥 Pulling latest code... Already up to date. (or: Updating abc1234..def5678) 📦 Updating dependencies... ✅ Dependencies updated 🔍 Checking for new config options... ✅ Config is up to date (or: Found 2 new options — running migration...) 🔄 Restarting gateway service... ✅ Gateway restarted ✅ Hermes Agent updated successfully! ``` ### 推荐的更新后验证 {#recommended-post-update-validation} `hermes update` 处理了主要的更新流程,但快速验证可确保一切顺利落地: 1. `git status --short` — 如果工作树意外处于非干净状态,请检查后再继续 2. `hermes doctor` — 检查配置、依赖项和服务健康状况 3. `hermes --version` — 确认版本号已按预期更新 4. 如果你使用网关:`hermes gateway status` 5. 如果 `doctor` 报告 npm 审计问题:在标记的目录中运行 `npm audit fix` :::warning 更新后工作树处于脏状态 如果 `git status --short` 在 `hermes update` 后显示意外更改,请停止并检查这些更改。这通常意味着本地修改被重新应用到了更新后的代码上,或某个依赖步骤刷新了锁文件。 ::: ### 检查当前版本 {#checking-your-current-version} ```bash hermes version ``` 与 [GitHub 发布页面](https://github.com/NousResearch/hermes-agent/releases) 上的最新版本进行对比,或检查是否有可用更新: ```bash hermes update --check ``` ### 从消息平台更新 {#updating-from-messaging-platforms} 你也可以通过发送以下内容直接从 Telegram、Discord、Slack 或 WhatsApp 进行更新: ``` /update ``` 此操作会拉取最新代码,更新依赖项,并重启网关。机器人在重启期间将短暂离线(通常为 5–15 秒),然后恢复运行。 ### 手动更新 {#manual-update} 如果你是手动安装的(非通过快速安装器): ```bash cd /path/to/hermes-agent export VIRTUAL_ENV="$(pwd)/venv" # 拉取最新代码和子模块 git pull origin main git submodule update --init --recursive # 重新安装(选择新的依赖项) uv pip install -e ".[all]" uv pip install -e "./tinker-atropos" # 检查新的配置选项 hermes config check hermes config migrate # 交互式添加任何缺少的选项 ``` ### 回滚说明 {#rollback-instructions} 如果更新引入了问题,你可以回滚到之前的版本: ```bash cd /path/to/hermes-agent # 列出最近版本 git log --oneline -10 # 回滚到特定提交 git checkout git submodule update --init --recursive uv pip install -e ".[all]" # 如果正在运行,请重新启动 gateway hermes gateway restart ``` 要回滚到特定的发布标签: ```bash git checkout v0.6.0 git submodule update --init --recursive uv pip install -e ".[all]" ``` :::warning 回滚可能导致配置不兼容,如果新增了配置选项。回滚后请运行 `hermes config check`,若遇到错误,请从 `config.yaml` 中移除任何无法识别的选项。 ::: ### Nix 用户注意事项 {#note-for-nix-users} 如果你通过 Nix flake 安装,更新由 Nix 包管理器管理: ```bash # 更新 flake 输入 nix flake update hermes-agent # 或者用最新的重建 nix profile upgrade hermes-agent ``` Nix 安装是不可变的 —— 回滚由 Nix 的生成系统处理: ```bash nix profile rollback ``` 更多详情请参见 [Nix 设置](nix-setup)。 --- ## 卸载 {#uninstalling} ```bash hermes uninstall ``` 卸载程序会提示你是否保留配置文件(`~/.hermes/`),以便将来重新安装时使用。 ### 手动卸载 {#manual-uninstall} ```bash rm -f ~/.local/bin/hermes rm -rf /path/to/hermes-agent rm -rf ~/.hermes # 可选 - 如果您打算重新安装,请保留 ``` :::info 如果你将网关作为系统服务安装,请先停止并禁用它: ```bash hermes gateway stop # Linux: systemctl --user 禁用 hermes-gateway # macOS:launchctl删除ai.hermes.gateway ``` ::: --- ### Windows 安装 - URL: https://hermesagent.org.cn/docs/getting-started/windows-installation - Path: getting-started/windows-installation.md - Category: getting-started - Description: Windows 用户如何用 PowerShell 原生安装或选择 WSL2 安装 Hermes Agent,并处理飞书接入常见问题。 - Upstream Source: https://developer.aliyun.com/article/1725007 - Translated At: 2026-04-13T06:00:00.000Z - Headings: 先回答三个问题 | 1. 什么是 PowerShell? | 2. 怎么打开 PowerShell? | 3. 什么时候需要管理员 PowerShell? | WSL2 到底是什么? | 现在还必须装 WSL2 吗? | 安装了 WSL2 之后,你实际会怎么用? | 先决定走哪条路径 | 方案一:原生 PowerShell(推荐直接安装) | 一键安装 | 原生 Windows 安装后文件大致在哪里 | 方案二:WSL2(可选) # Windows 安装 {#windows-installation} :::tip 安装遇到困难? 点击加入 [中文社区微信群](/community),提问并获取群内专家帮助。 **完全没有经验?** 强烈建议先下载 [WorkBuddy](https://www.workbuddy.cn/)(微信扫码即用,无需任何配置),然后让它安装中文社区文档 MCP 来协助你安装 Hermes Agent。如果后续 Hermes 出现问题,也可以让 WorkBuddy 对其进行修复,反之亦然——两个 Agent 互为主备,这是社区推荐的最佳方案。 **电脑上已经有 Agent?** 如果你已经在用龙虾 [OpenClaw](https://github.com/openclaw/openclaw) 或国内版本([QClaw](https://qclaw.qq.com/)、[AutoClaw](https://autoglm.zhipuai.cn/autoclaw/)),或者 [Trae](https://www.trae.ai/)、[Claude Code](https://claude.ai/code)、[Codex](https://openai.com/index/introducing-codex/)、[Cursor](https://www.cursor.com/)、[Qoder](https://qoder.ai/) 等 Coding Agent,都可以让它读文档来协助你完成安装,你可以不用关心任何技术细节。 **如何让你的 Agent 接入中文社区文档?** - **方式一(最简单)**:把中文社区网址 [https://hermesagent.org.cn](https://hermesagent.org.cn) 发给它,让它自己访问并阅读文档。 - **方式二(更精准,推荐)**:直接把下面这段话复制发给你的 Agent,它会自己完成配置: ```agent-prompt 请把这个 Hermes 中文文档 MCP server 加到你的配置里: https://mcp.hermesagent.org.cn/v1 (Streamable HTTP,无需 API Key、无需登录) 加完后用它帮我查 Hermes Agent 中文文档来指导我完成安装。 ``` - 方式二配好后,Agent 就能按关键词直接检索并读取中文社区全部文档的全文。 **其他求助途径**:也可以先询问 [豆包](https://www.doubao.com/)、[DeepSeek](https://chat.deepseek.com/) 等 AI 助手。 ::: 如果你主要在 Windows 上使用 Hermes Agent,这一页就是给你的。**重点只有一句话:Windows 和类 Linux / macOS 的安装命令不一样。** ## 先回答三个问题 {#three-beginner-questions} ### 1. 什么是 PowerShell? {#what-is-powershell} PowerShell 是 Windows 自带的命令行程序。你可以把它理解成: - **Windows 里的终端** - 一个可以输入命令、安装软件、运行脚本的窗口 如果你以前听过这些词,它们大致是一个意思: - 命令行 - 终端 - Shell - PowerShell 对 Windows 用户来说,**你不需要先理解所有概念**。你只需要知道: > 后面文档里写的 PowerShell 命令,就是要粘贴到 PowerShell 窗口里执行。 ### 2. 怎么打开 PowerShell? {#how-to-open-powershell} 最简单的方法: 1. 按一下键盘左下角 **Windows 键** 2. 输入 `PowerShell` 3. 点击 **Windows PowerShell** 或 **PowerShell** 你也可能会看到: - **Windows Terminal** 这也可以用,但请确认打开后当前标签页是 **PowerShell**。 :::tip 你应该把命令粘贴到哪里? 请把命令粘贴到 **PowerShell 窗口本身**,不要粘贴到: - 浏览器地址栏 - 文件资源管理器地址栏 - “运行”对话框 - Word / 记事本 / 聊天框 如果你不知道怎么粘贴,可以用下面任意一种方法: - **最常用**:按键盘 **Ctrl + V** - **如果 Ctrl + V 没反应**:在 PowerShell 窗口里点一下鼠标右键,很多电脑会直接粘贴 - **Windows Terminal** 里通常也支持 **Ctrl + Shift + V**,但大多数情况下先试 **Ctrl + V** 就够了 粘贴成功后,你会看到那一整行命令出现在 PowerShell 窗口里;这时再按一下 **Enter(回车键)** 才会真正开始执行。 ::: ### 3. 什么时候需要管理员 PowerShell? {#when-to-use-admin-powershell} - **安装 WSL2**:通常需要 **管理员 PowerShell** - **直接安装 Hermes**:通常普通 PowerShell 就够了 也就是说: - 想装 WSL2 → 可以右键 PowerShell,选择“**以管理员身份运行**” - 想直接跑 `install.ps1` → 一般直接打开普通 PowerShell 即可 ## WSL2 到底是什么? {#what-is-wsl2} WSL2 的全名是 **Windows Subsystem for Linux 2**。 你可以把它简单理解成: - 在 Windows 电脑里放了一个 **Linux 终端环境** - 你不用单独装双系统,也不用自己手搓虚拟机 - 安装完成后,开始菜单里通常会多一个 **Ubuntu** - 打开 Ubuntu 后,你看到的是 **Linux 命令行** 对新手来说,最重要的不是记住全名,而是记住下面这句话: > **WSL2 = 让你在 Windows 电脑上,按 Linux 的方式装和用 Hermes。** ### 现在还必须装 WSL2 吗? {#why-we-recommend-wsl2} 不必须。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以直接在 PowerShell 中原生安装和使用。WSL2 现在更像是一条可选路径,适合你明确偏好 Linux / Ubuntu 终端,或者需要 POSIX 语义、Linux 文件监听、Dashboard 内嵌终端等特定能力时使用。 如果你只是想在 Windows 本机安装 Hermes、配置模型、运行 CLI、接入飞书或其他消息网关,可以优先使用原生 PowerShell 安装命令。 ### 安装了 WSL2 之后,你实际会怎么用? {#how-you-will-actually-use-wsl2} 你平时还是正常用 Windows。 只有在安装和运行 Hermes 的时候,你改为: 1. 打开 **Ubuntu** 2. 在 Ubuntu 终端里粘贴 Linux 安装命令 3. 后续也主要在 Ubuntu 终端里运行 `hermes` 也就是说: - **Windows 继续是你的桌面系统** - **Ubuntu(WSL2)只是 Hermes 的运行终端** 如果你看到文档里写: ```bash curl -fsSL https://res1.hermesagent.org.cn/install.sh | bash ``` 那么这条命令就应该: - 在 **macOS 终端** - 或 **Linux 终端** - 或 **Windows 里的 Ubuntu(WSL2)终端** 里执行,**不要**粘贴到原生 PowerShell。 ## 先决定走哪条路径 {#choose-your-path} | 路径 | 适合谁 | 推荐程度 | 你要运行的命令 | |---|---|---|---| | **原生 PowerShell** | 想在 Windows 本机直接安装和长期使用 Hermes Agent | **推荐直接安装** | 在 PowerShell 里运行 `install.ps1` | | **WSL2 + Ubuntu** | 偏好 Linux / Ubuntu 终端,或需要 POSIX 语义、Linux 工具链和 WSL 网络环境 | 可选 | 在 WSL2 里运行 `install.sh` | :::tip 推荐结论 - **大多数 Windows 用户**:可以直接选 **原生 PowerShell**。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以原生安装了。 - **偏好 Linux 工作流 / 需要 POSIX 语义**:再选择 **WSL2**。 ::: :::tip 中国大陆网络环境提示 当前页给出的安装命令已经由 **Hermes Agent 中文社区** 接入 **国内镜像加速**,会优先使用国内可直连的下载链路。 为了提高中国大陆用户的安装体验,镜像版安装器默认精简了部分国人不常用、或体积较大且经常受外网影响的可选功能,例如浏览器自动化、Chromium 下载、WhatsApp 桥接等。建议先完成核心安装,确认 Hermes Agent 可以正常运行;之后可让 Hermes Agent 自身补全这些能力。 如果你还需要处理 WSL 网络、终端代理或镜像源配置,可参考: - **WSL 安装(中文)**:[Windows 10/11 安装 WSL2 指南](https://zhuanlan.zhihu.com/p/466001838) - **WSL 网络 / autoProxy(官方)**:[Microsoft Learn - Accessing network applications with WSL](https://learn.microsoft.com/en-us/windows/wsl/networking) - **Python / pip 镜像说明**:[清华 TUNA - PyPI 镜像帮助](https://mirror.tuna.tsinghua.edu.cn/help/pypi/) - **Node.js / npm 镜像说明**:[清华 TUNA - NodeJS Release 镜像帮助](https://mirror.tuna.tsinghua.edu.cn/help/nodejs-release/) / [npmmirror](https://npmmirror.com/) ::: ## 方案一:原生 PowerShell(推荐直接安装) {#native-powershell} ### 一键安装 {#native-powershell-install} 如果你想直接在 Windows 本机安装,请按下面步骤来: 1. 按 **Windows 键** 2. 输入 `PowerShell` 3. 点击 **Windows PowerShell** 或 **PowerShell** 4. 把下面这行命令完整复制进去 5. 在 PowerShell 窗口里粘贴并按回车 你要执行的命令是: ```powershell irm https://res1.hermesagent.org.cn/install.ps1 | iex ``` :::tip 粘贴小提示 - 现在多数 Windows 终端都支持 **Ctrl+V** - 如果不行,也可以直接在窗口里 **右键粘贴** ::: 这个安装器会自动尝试处理: - uv - Python 3.11 - Node.js - Git - ripgrep / ffmpeg - Hermes 本体与虚拟环境 安装完成后,**关闭并重新打开 PowerShell**,再运行: ```powershell hermes hermes model ``` 如果你重新打开 PowerShell 后输入 `hermes` 能正常启动,就说明 Windows 原生安装已经成功了。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,已经可以把这条路径作为日常使用方案。 ### 原生 Windows 安装后文件大致在哪里 {#native-windows-paths} 默认安装目录通常在: ```text %LOCALAPPDATA%\hermes ``` 例如: - Hermes 主目录:`%LOCALAPPDATA%\hermes` - 仓库目录:`%LOCALAPPDATA%\hermes\hermes-agent` - 虚拟环境:`%LOCALAPPDATA%\hermes\hermes-agent\venv` 如果 `hermes` 命令暂时不可用,最常见的解决方法就是:**关掉当前 PowerShell 窗口,再开一个新的。** ## 方案二:WSL2(可选) {#wsl2-recommended} ### 第一步:在管理员 PowerShell 中安装 WSL2 {#install-wsl2} 如果你偏好 Linux / Ubuntu 终端,或者明确需要 POSIX 语义、Linux 工具链和 WSL 网络环境,可以继续选择 WSL2。如果你还没装过 WSL,建议先看这篇中文帖子: - [Windows 10/11 安装 WSL2 指南(知乎)](https://zhuanlan.zhihu.com/p/466001838) 然后再执行: ```powershell wsl --install -d Ubuntu ``` 执行后按提示重启电脑。重启完成后,打开 **Ubuntu**,设置 Linux 用户名和密码。 ### 第二步:在 WSL2 终端里运行 Linux 安装命令 {#run-linux-installer-in-wsl} ```bash curl -fsSL https://res1.hermesagent.org.cn/install.sh | bash ``` 安装完成后,重新加载 shell: ```bash source ~/.bashrc # 或:source ~/.zshrc hermes ``` ### 第三步:继续配置模型 {#configure-provider-in-wsl} ```bash hermes model hermes setup ``` 如果你选择 WSL2,后续就主要在 Ubuntu 终端里运行 `hermes`。这是一条可选的 Linux 工作流,不是 Windows 用户安装 Hermes Agent 的前置条件。 :::tip 如果你的模型跑在 Windows 主机上 例如 Ollama、LM Studio 跑在 Windows 本机,而 Hermes 跑在 WSL2 中,这时 `localhost` 不一定直接可用。请继续看 [提供商文档里的 WSL2 网络配置](/docs/integrations/providers#wsl2-networking-windows-users)。 ::: ## 飞书接入:Windows 用户最容易踩的坑 {#windows-feishu} 这一节参考并改写自阿里云文章《[Windows 也能跑 Hermes Agent!完整安装教程 + 飞书接入,全程避坑](https://developer.aliyun.com/article/1725007)》。为了避免直接照抄,这里只保留最关键的结论和更稳的写法。 ### 1. 先完成 Hermes 本体安装,再单独配置网关 {#gateway-setup-first} ```powershell hermes gateway setup ``` 在渠道列表中选择 **飞书**,填入: - App ID - App Secret - 国内版填 `feishu`,海外版填 `lark` - 连接方式一般先用默认的 `websocket` 然后再启动网关: ```powershell hermes gateway run -vv ``` ### 2. 如果报 `lark-oapi 未安装` {#lark-oapi-missing} 原生 Windows 下,飞书 SDK 有时没有被装进 Hermes 自己的虚拟环境。可以这样补装: ```powershell $hermesExe = (Get-Command hermes).Source $venvPython = Join-Path (Split-Path $hermesExe -Parent) 'python.exe' uv pip install lark-oapi --python $venvPython ``` 如果你还缺 `websockets` 或 `aiohttp`,也可以用同样方式补进去: ```powershell uv pip install websockets aiohttp --python $venvPython ``` ### 3. 如果网关一启动就退出,或看到 `WinError 11` {#winerror-11} 阿里云文章里提到,早期某些 Windows 环境下,`gateway/status.py` 里的 `os.kill(pid, 0)` 检查会触发 `WinError 11`,导致网关异常退出。现阶段 Hermes Agent 已经对 Windows 原生安装做了很多适配,如果你仍然遇到这个旧问题,建议先升级 Hermes 并运行 `hermes doctor` 排查。 如果升级后仍需要临时规避,可以按阿里云文章中的思路,对 `gateway/status.py` 做临时补丁,把 `OSError` 也纳入异常捕获。下面这段 PowerShell 会自动定位文件并打补丁: ```powershell $hermesExe = (Get-Command hermes).Source $installRoot = Split-Path (Split-Path $hermesExe -Parent) -Parent $statusPy = Join-Path $installRoot 'gateway\status.py' $content = Get-Content $statusPy -Raw -Encoding UTF8 $content = $content.Replace( 'except (ProcessLookupError, PermissionError):', 'except (ProcessLookupError, PermissionError, OSError):' ) Set-Content $statusPy $content -Encoding UTF8 -NoNewline ``` 然后重新启动: ```powershell $env:PYTHONUTF8 = '1' hermes gateway run -vv ``` :::warning 这是面向旧版本或个别环境的临时规避方案。正常情况下请优先升级 Hermes Agent,或使用 `hermes doctor` 自动诊断,不需要因为这个旧问题放弃 Windows 原生安装。 ::: ### 4. 飞书群里 @ 机器人没反应 {#feishu-no-response} 先确认两件事: 1. 飞书开放平台里的机器人权限和事件订阅已经配好。 2. 你已经启动了网关,并用 `hermes gateway run -vv` 看到了正常日志。 如果日志没报错,但群里依然不响应,可以先把群策略放宽为 `open` 进行排查: ```powershell Add-Content "$env:LOCALAPPDATA\hermes\.env" "`nFEISHU_GROUP_POLICY=open" -Encoding UTF8 ``` 然后重新运行: ```powershell $env:PYTHONUTF8 = '1' hermes gateway run -vv ``` 如果这样能恢复,再回头逐步收紧白名单配置。 ## Windows 用户的推荐上手顺序 {#recommended-flow-for-windows} 1. 大多数 Windows 用户可以先走 **原生 PowerShell**,直接运行 `install.ps1`。 2. 安装完成后,先用 `hermes` 和 `hermes model` 验证 CLI 与模型配置。 3. 再去接飞书、微信、Telegram 等消息网关。 4. 如果你偏好 Linux / Ubuntu 终端,或明确需要 POSIX 语义、Linux 文件监听、Dashboard 内嵌终端等能力,再选择 **WSL2**。 ## 补充阅读 {#further-reading} - [安装总览](/docs/getting-started/installation) - [快速入门](/docs/getting-started/quickstart) - [飞书接入文档](/docs/user-guide/messaging/feishu) - [提供商配置与 WSL2 网络说明](/docs/integrations/providers#wsl2-networking-windows-users) - 参考来源:阿里云文章《[Windows 也能跑 Hermes Agent!完整安装教程 + 飞书接入,全程避坑](https://developer.aliyun.com/article/1725007)》 --- ### 使用 Cron 自动化任何任务 - URL: https://hermesagent.org.cn/docs/guides/automate-with-cron - Path: guides/automate-with-cron.md - Category: guides - Description: 使用 Hermes cron 的真实世界自动化模式 —— 监控、报告、流水线和多技能工作流 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/automate-with-cron.md - Translated At: 2026-04-11T03:26:34.068Z - Headings: 模式 1:网站变更监控器 | 模式 2:每周报告 | 模式 3:GitHub 仓库监视器 | 模式 4:数据收集流水线 | 模式 5:多技能工作流 | 管理您的任务 | 交付目标 | 技巧 # 使用 Cron 自动化任何任务 {#automate-anything-with-cron} [每日简报机器人教程](/docs/guides/daily-briefing-bot) 涵盖了基础知识。本指南更进一步——介绍五个可应用于您自身工作流的真实世界自动化模式。 如需完整功能参考,请参阅 [计划任务(Cron)](/docs/user-guide/features/cron)。 :::info 关键概念 Cron 任务在全新的 Agent 会话中运行,不会保留您当前聊天的记忆。提示必须是**完全自包含的**——包含 Agent 所需的一切信息。 ::: --- ## 模式 1:网站变更监控器 {#pattern-1-website-change-monitor} 监控指定 URL 的变更,并仅在内容发生变化时收到通知。 `script` 参数是此模式的关键。每次执行前都会运行一段 Python 脚本,其标准输出将作为 Agent 的上下文。脚本负责机械性工作(获取网页内容、对比差异);Agent 则负责推理判断(此变更是否值得关注?)。 创建监控脚本: ```bash mkdir -p ~/.hermes/scripts ``` ```python title="~/.hermes/scripts/watch-site.py" import hashlib, json, os, urllib.request URL = "https://example.com/pricing" STATE_FILE = os.path.expanduser("~/.hermes/scripts/.watch-site-state.json") # 获取当前内容 req = urllib.request.Request(URL, headers={"User-Agent": "Hermes-Monitor/1.0"}) content = urllib.request.urlopen(req, timeout=30).read().decode() current_hash = hashlib.sha256(content.encode()).hexdigest() # 加载之前的状态 prev_hash = None if os.path.exists(STATE_FILE): with open(STATE_FILE) as f: prev_hash = json.load(f).get("hash") # 保存当前状态 with open(STATE_FILE, "w") as f: json.dump({"hash": current_hash, "url": URL}, f) # 输出给 Agent if prev_hash and prev_hash != current_hash: print(f"CHANGE DETECTED on {URL}") print(f"Previous hash: {prev_hash}") print(f"Current hash: {current_hash}") print(f"\nCurrent content (first 2000 chars):\n{content[:2000]}") else: print("NO_CHANGE") ``` 设置 Cron 任务: ```bash /cron add "every 1h" "If the script output says CHANGE DETECTED, summarize what changed on the page and why it might matter. If it says NO_CHANGE, respond with just [SILENT]." --script ~/.hermes/scripts/watch-site.py --name "Pricing monitor" --deliver telegram ``` :::tip [SILENT] 技巧 当 Agent 的最终响应包含 `[SILENT]` 时,将抑制通知发送。这意味着只有真正发生变更时才会收到提醒——在无变化时段不会产生通知噪音。 ::: --- ## 模式 2:每周报告 {#pattern-2-weekly-report} 从多个信息源汇总数据,生成格式化的摘要报告。该任务每周运行一次,并发送至您的主频道。 ```bash /cron add "0 9 * * 1" "Generate a weekly report covering: 1. Search the web for the top 5 AI news stories from the past week 2. Search GitHub for trending repositories in the 'machine-learning' topic 3. Check Hacker News for the most discussed AI/ML posts Format as a clean summary with sections for each source. Include links. Keep it under 500 words — highlight only what matters." --name "Weekly AI digest" --deliver telegram ``` 通过 CLI 执行: ```bash hermes cron create "0 9 * * 1" \ "Generate a weekly report covering the top AI news, trending ML GitHub repos, and most-discussed HN posts. Format with sections, include links, keep under 500 words." \ --name "Weekly AI digest" \ --deliver telegram ``` `0 9 * * 1` 是标准的 Cron 表达式:每周一上午 9:00。 --- ## 模式 3:GitHub 仓库监视器 {#pattern-3-github-repository-watcher} 监视仓库中是否有新问题、拉取请求或发布版本。 ```bash /cron add "every 6h" "Check the GitHub repository NousResearch/hermes-agent for: - New issues opened in the last 6 hours - New PRs opened or merged in the last 6 hours - Any new releases Use the terminal to run gh commands: gh issue list --repo NousResearch/hermes-agent --state open --json number,title,author,createdAt --limit 10 gh pr list --repo NousResearch/hermes-agent --state all --json number,title,author,createdAt,mergedAt --limit 10 Filter to only items from the last 6 hours. If nothing new, respond with [SILENT]. Otherwise, provide a concise summary of the activity." --name "Repo watcher" --deliver discord ``` :::warning 完全自包含的提示 请注意提示中如何明确包含 `gh` 命令。Cron Agent 没有记忆前次运行或您的偏好的能力——必须完整写出所有指令。 ::: --- ## 模式 4:数据收集流水线 {#pattern-4-data-collection-pipeline} 定期抓取数据,保存到文件,并随时间检测趋势。该模式结合脚本(用于收集)与 Agent(用于分析)。 ```python title="~/.hermes/scripts/collect-prices.py" import json, os, urllib.request from datetime import datetime DATA_DIR = os.path.expanduser("~/.hermes/data/prices") os.makedirs(DATA_DIR, exist_ok=True) # 获取当前数据(例如:加密货币价格) url = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum&vs_currencies=usd" data = json.loads(urllib.request.urlopen(url, timeout=30).read()) # 追加到历史文件 entry = {"timestamp": datetime.now().isoformat(), "prices": data} history_file = os.path.join(DATA_DIR, "history.jsonl") with open(history_file, "a") as f: f.write(json.dumps(entry) + "\n") # 加载最近的历史记录进行分析 lines = open(history_file).readlines() recent = [json.loads(l) for l in lines[-24:]] # 最后 24 个数据点 # 输出给 Agent print(f"Current: BTC=${data['bitcoin']['usd']}, ETH=${data['ethereum']['usd']}") print(f"Data points collected: {len(lines)} total, showing last {len(recent)}") print(f"\nRecent history:") for r in recent[-6:]: print(f" {r['timestamp']}: BTC=${r['prices']['bitcoin']['usd']}, ETH=${r['prices']['ethereum']['usd']}") ``` ```bash /cron add "every 1h" "Analyze the price data from the script output. Report: 1. Current prices 2. Trend direction over the last 6 data points (up/down/flat) 3. Any notable movements (>5% change) If prices are flat and nothing notable, respond with [SILENT]. If there's a significant move, explain what happened." \ --script ~/.hermes/scripts/collect-prices.py \ --name "Price tracker" \ --deliver telegram ``` 脚本负责机械性数据收集;Agent 则添加推理分析层。 --- ## 模式 5:多技能工作流 {#pattern-5-multi-skill-workflow} 将多个技能串联起来,完成复杂的计划任务。技能在提示执行前按顺序加载。 ```bash # 使用arxiv skill查找论文,然后使用黑曜石skill保存笔记 /cron add "0 8 * * *" "Search arXiv for the 3 most interesting papers on 'language model reasoning' from the past day. For each paper, create an Obsidian note with the title, authors, abstract summary, and key contribution." \ --skill arxiv \ --skill obsidian \ --name "Paper digest" ``` 通过工具直接执行: ```python cronjob( action="create", skills=["arxiv", "obsidian"], prompt="Search arXiv for papers on 'language model reasoning' from the past day. Save the top 3 as Obsidian notes.", schedule="0 8 * * *", name="Paper digest", deliver="local" ) ``` 技能按顺序加载——首先是 `arxiv`(教会 Agent 如何搜索论文),然后是 `obsidian`(教会 Agent 如何撰写笔记)。提示将它们串联起来。 --- ## 管理您的任务 {#managing-your-jobs} ```bash # 列出所有活动作业 /cron list # 立即触发作业(用于测试) /cron run # 暂停作业而不删除它 /cron pause # 编辑正在运行的作业的计划或 prompt /cron edit --schedule "every 4h" /cron edit --prompt "Updated task description" # 在现有作业中添加或删除 skills /cron edit --skill arxiv --skill obsidian /cron edit --clear-skills # 永久删除职位 /cron remove ``` --- ## 交付目标 {#delivery-targets} `--deliver` 标志控制结果的发送位置: | 目标 | 示例 | 使用场景 | |------|------|----------| | `origin` | `--deliver origin` | 创建任务的原始聊天(默认) | | `local` | `--deliver local` | 仅保存到本地文件 | | `telegram` | `--deliver telegram` | 您的 Telegram 主频道 | | `discord` | `--deliver discord` | 您的 Discord 主频道 | | `slack` | `--deliver slack` | 您的 Slack 主频道 | | 特定聊天 | `--deliver telegram:-1001234567890` | 指定的 Telegram 群组 | | 线程 | `--deliver telegram:-1001234567890:17585` | 指定的 Telegram 主题线程 | --- ## 技巧 {#tips} **使提示完全自包含。** Cron 任务中的 Agent 没有记忆您对话的能力。请在提示中直接包含 URL、仓库名称、格式偏好和交付指令。 **广泛使用 `[SILENT]`。** 对于监控类任务,始终包含类似“若无变化,请回复 `[SILENT]`”的指令。这可防止通知噪音。 **使用脚本进行数据收集。** `script` 参数允许 Python 脚本处理繁琐部分(HTTP 请求、文件 I/O、状态追踪)。Agent 仅看到脚本的标准输出,并基于此进行推理。相比让 Agent 自行执行获取操作,这种方式更经济且更可靠。 **使用 `/cron run` 测试。** 在等待计划触发前,可使用 `/cron run ` 立即执行任务,验证输出是否正确。 **调度表达式。** 人类可读格式如 `every 2h`、`30m` 和 `daily at 9am` 均支持,同时兼容标准 Cron 表达式如 `0 9 * * *`。 --- *如需完整的 Cron 参考——包含所有参数、边缘情况和内部机制——请参阅 [计划任务(Cron)](/docs/user-guide/features/cron)。* --- ### 自动化蓝图 - URL: https://hermesagent.org.cn/docs/guides/automation-blueprints - Path: guides/automation-blueprints.md - Category: guides - Description: 开箱即用的自动化蓝图 — 计划任务、GitHub 事件触发器、API Webhook 以及多技能工作流 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/automation-blueprints.md - Translated At: 2026-06-16T00:43:48.555Z - Headings: 开发工作流 | 夜间待办事项分类 | 自动 PR 代码审查 | 文档漂移检测 | 依赖安全审计 | DevOps 与监控 | 部署验证 | 告警分类 | 正常运行时间监控 | 研究与情报 | 竞争对手仓库侦察 | AI 新闻摘要 # 自动化蓝图 {#automation-blueprints} 常见自动化模式的复制粘贴式蓝图。每个蓝图都使用 Hermes 内置的 [cron 调度器](/docs/user-guide/features/cron) 进行基于时间的触发,以及 [Webhook 平台](/docs/user-guide/messaging/webhooks) 进行事件驱动的触发。 每个蓝图都适用于**任何模型**——不锁定于单一提供商。 对于使用表单而非 cron 语法的参数化蓝图,请参阅 [自动化蓝图目录](/docs/reference/automation-blueprints-catalog)。 :::tip 三种触发类型 | 触发器 | 方式 | 工具 | |---------|-----|------| | **计划任务** | 按节奏运行(每小时、每晚、每周) | `cronjob` 工具或 `/cron` 斜杠命令 | | **GitHub 事件** | 在 PR 打开、推送、Issues、CI 结果时触发 | Webhook 平台 (`hermes webhook subscribe`) | | **API 调用** | 外部服务向你的端点 POST JSON | Webhook 平台 (config.yaml 路由或 `hermes webhook subscribe`) | 所有这三种方式都支持交付到 Telegram、Discord、Slack、SMS、电子邮件、GitHub 评论或本地文件。 ::: --- ## 开发工作流 {#development-workflow} ### 夜间待办事项分类 {#nightly-backlog-triage} 每晚对新 Issue 进行标记、优先级排序和总结。将摘要发送到你的团队频道。 **触发器:** 计划任务(每晚) ```bash hermes cron create "0 2 * * *" \ "You are a project manager triaging the NousResearch/hermes-agent GitHub repo. 1. Run: gh issue list --repo NousResearch/hermes-agent --state open --json number,title,labels,author,createdAt --limit 30 2. Identify issues opened in the last 24 hours 3. For each new issue: - Suggest a priority label (P0-critical, P1-high, P2-medium, P3-low) - Suggest a category label (bug, feature, docs, security) - Write a one-line triage note 4. Summarize: total open issues, new today, breakdown by priority Format as a clean digest. If no new issues, respond with [SILENT]." \ --name "Nightly backlog triage" \ --deliver telegram ``` ### 自动 PR 代码审查 {#automatic-pr-code-review} 在每次拉取请求打开时自动进行审查。直接在 PR 上发布审查评论。 **触发器:** GitHub Webhook **选项 A — 动态订阅(CLI):** ```bash hermes webhook subscribe github-pr-review \ --events "pull_request" \ --prompt "Review this pull request: Repository: {repository.full_name} PR #{pull_request.number}: {pull_request.title} Author: {pull_request.user.login} Action: {action} Diff URL: {pull_request.diff_url} Fetch the diff with: curl -sL {pull_request.diff_url} Review for: - Security issues (injection, auth bypass, secrets in code) - Performance concerns (N+1 queries, unbounded loops, memory leaks) - Code quality (naming, duplication, error handling) - Missing tests for new behavior Post a concise review. If the PR is a trivial docs/typo change, say so briefly." \ --skill github-code-review \ --deliver github_comment ``` **选项 B — 静态路由(config.yaml):** ```yaml platforms: webhook: enabled: true extra: port: 8644 secret: "your-global-secret" routes: github-pr-review: events: ["pull_request"] secret: "github-webhook-secret" prompt: | Review PR #{pull_request.number}: {pull_request.title} Repository: {repository.full_name} Author: {pull_request.user.login} Diff URL: {pull_request.diff_url} Review for security, performance, and code quality. skills: ["github-code-review"] deliver: "github_comment" deliver_extra: repo: "{repository.full_name}" pr_number: "{pull_request.number}" ``` 然后在 GitHub 中:**Settings → Webhooks → Add webhook** → Payload URL: `http://your-server:8644/webhooks/github-pr-review`, Content type: `application/json`, Secret: `github-webhook-secret`, Events: **Pull requests**。 ### 文档漂移检测 {#docs-drift-detection} 每周扫描已合并的 PR,以查找需要更新文档的 API 变更。 **触发器:** 计划任务(每周) ```bash hermes cron create "0 9 * * 1" \ "Scan the NousResearch/hermes-agent repo for documentation drift. 1. Run: gh pr list --repo NousResearch/hermes-agent --state merged --json number,title,files,mergedAt --limit 30 2. Filter to PRs merged in the last 7 days 3. For each merged PR, check if it modified: - Tool schemas (tools/*.py) — may need docs/reference/tools-reference.md update - CLI commands (hermes_cli/commands.py, hermes_cli/main.py) — may need docs/reference/cli-commands.md update - Config options (hermes_cli/config.py) — may need docs/user-guide/configuration.md update - Environment variables — may need docs/reference/environment-variables.md update 4. Cross-reference: for each code change, check if the corresponding docs page was also updated in the same PR Report any gaps where code changed but docs didn't. If everything is in sync, respond with [SILENT]." \ --name "Docs drift detection" \ --deliver telegram ``` ### 依赖安全审计 {#dependency-security-audit} 每天扫描项目依赖项中的已知漏洞。 **触发器:** 计划任务(每天) ```bash hermes cron create "0 6 * * *" \ "Run a dependency security audit on the hermes-agent project. 1. cd ~/.hermes/hermes-agent && source .venv/bin/activate 2. Run: pip audit --format json 2>/dev/null || pip audit 2>&1 3. Run: npm audit --json 2>/dev/null (in website/ directory if it exists) 4. Check for any CVEs with CVSS score >= 7.0 If vulnerabilities found: - List each one with package name, version, CVE ID, severity - Check if an upgrade is available - Note if it's a direct dependency or transitive If no vulnerabilities, respond with [SILENT]." \ --name "Dependency audit" \ --deliver telegram ``` --- ## DevOps 与监控 {#devops--monitoring} ### 部署验证 {#deploy-verification} 在每次部署后触发冒烟测试。当部署完成时,你的 CI/CD 流水线向 Webhook 发送 POST 请求。 **触发器:** API 调用(Webhook) ```bash hermes webhook subscribe deploy-verify \ --events "deployment" \ --prompt "A deployment just completed: Service: {service} Environment: {environment} Version: {version} Deployed by: {deployer} Run these verification steps: 1. Check if the service is responding: curl -s -o /dev/null -w '%{http_code}' {health_url} 2. Search recent logs for errors: check the deployment payload for any error indicators 3. Verify the version matches: curl -s {health_url}/version Report: deployment status (healthy/degraded/failed), response time, any errors found. If healthy, keep it brief. If degraded or failed, provide detailed diagnostics." \ --deliver telegram ``` 你的 CI/CD 流水线触发它: ```bash curl -X POST http://your-server:8644/webhooks/deploy-verify \ -H "Content-Type: application/json" \ -H "X-Hub-Signature-256: sha256=$(echo -n '{"service":"api","environment":"prod","version":"2.1.0","deployer":"ci","health_url":"https://api.example.com/health"}' | openssl dgst -sha256 -hmac 'your-secret' | cut -d' ' -f2)" \ -d '{"service":"api","environment":"prod","version":"2.1.0","deployer":"ci","health_url":"https://api.example.com/health"}' ``` ### 告警分类 {#alert-triage} 将监控告警与最近的变更关联起来,以起草响应。适用于 Datadog、PagerDuty、Grafana 或任何可以 POST JSON 的告警系统。 **触发器:** API 调用(Webhook) ```bash hermes webhook subscribe alert-triage \ --prompt "Monitoring alert received: Alert: {alert.name} Severity: {alert.severity} Service: {alert.service} Message: {alert.message} Timestamp: {alert.timestamp} Investigate: 1. Search the web for known issues with this error pattern 2. Check if this correlates with any recent deployments or config changes 3. Draft a triage summary with: - Likely root cause - Suggested first response steps - Escalation recommendation (P1-P4) Be concise. This goes to the on-call channel." \ --deliver slack ``` ### 正常运行时间监控 {#uptime-monitor} 每 30 分钟检查一次端点。仅在出现故障时通知。 **触发器:** 计划任务(每 30 分钟) ```python title="~/.hermes/scripts/check-uptime.py" import urllib.request, json, time ENDPOINTS = [ {"name": "API", "url": "https://api.example.com/health"}, {"name": "Web", "url": "https://www.example.com"}, {"name": "Docs", "url": "https://docs.example.com"}, ] results = [] for ep in ENDPOINTS: try: start = time.time() req = urllib.request.Request(ep["url"], headers={"User-Agent": "Hermes-Monitor/1.0"}) resp = urllib.request.urlopen(req, timeout=10) elapsed = round((time.time() - start) * 1000) results.append({"name": ep["name"], "status": resp.getcode(), "ms": elapsed}) except Exception as e: results.append({"name": ep["name"], "status": "DOWN", "error": str(e)}) down = [r for r in results if r.get("status") == "DOWN" or (isinstance(r.get("status"), int) and r["status"] >= 500)] if down: print("OUTAGE DETECTED") for r in down: print(f" {r['name']}: {r.get('error', f'HTTP {r[\"status\"]}')} ") print(f"\nAll results: {json.dumps(results, indent=2)}") else: print("NO_ISSUES") ``` ```bash hermes cron create "every 30m" \ "If the script reports OUTAGE DETECTED, summarize which services are down and suggest likely causes. If NO_ISSUES, respond with [SILENT]." \ --script ~/.hermes/scripts/check-uptime.py \ --name "Uptime monitor" \ --deliver telegram ``` --- ## 研究与情报 {#research--intelligence} ### 竞争对手仓库侦察 {#competitive-repository-scout} 监控竞争对手的仓库,了解有趣的 PR、功能和架构决策。 **触发器:** 计划任务(每天) ```bash hermes cron create "0 8 * * *" \ "Scout these AI agent repositories for notable activity in the last 24 hours: Repos to check: - anthropics/claude-code - openai/codex - All-Hands-AI/OpenHands - Aider-AI/aider For each repo: 1. gh pr list --repo --state all --json number,title,author,createdAt,mergedAt --limit 15 2. gh issue list --repo --state open --json number,title,labels,createdAt --limit 10 Focus on: - New features being developed - Architectural changes - Integration patterns we could learn from - Security fixes that might affect us too Skip routine dependency bumps and CI fixes. If nothing notable, respond with [SILENT]. If there are findings, organize by repo with brief analysis of each item." \ --skill competitive-pr-scout \ --name "Competitor scout" \ --deliver telegram ``` ### AI 新闻摘要 {#ai-news-digest} 每周汇总 AI/ML 发展动态。 **触发器:** 计划任务(每周) ```bash hermes cron create "0 9 * * 1" \ "Generate a weekly AI news digest covering the past 7 days: 1. Search the web for major AI announcements, model releases, and research breakthroughs 2. Search for trending ML repositories on GitHub 3. Check arXiv for highly-cited papers on language models and agents Structure: ## Headlines (3-5 major stories) ## Notable Papers (2-3 papers with one-sentence summaries) ## Open Source (interesting new repos or major releases) ## Industry Moves (funding, acquisitions, launches) Keep each item to 1-2 sentences. Include links. Total under 600 words." \ --name "Weekly AI digest" \ --deliver telegram ``` ### 带笔记的论文摘要 {#paper-digest-with-notes} 每日扫描 arXiv,将摘要保存到你的笔记系统中。 **触发器:** 计划任务(每天) ```bash hermes cron create "0 8 * * *" \ "Search arXiv for the 3 most interesting papers on 'language model reasoning' OR 'tool-use agents' from the past day. For each paper, create an Obsidian note with the title, authors, abstract summary, key contribution, and potential relevance to Hermes Agent development." \ --skill arxiv --skill obsidian \ --name "Paper digest" \ --deliver local ``` --- ## GitHub 事件自动化 {#github-event-automations} ### Issue 自动标记 {#issue-auto-labeling} 自动标记并回复新 Issue。 **触发器:** GitHub Webhook ```bash hermes webhook subscribe github-issues \ --events "issues" \ --prompt "New GitHub issue received: Repository: {repository.full_name} Issue #{issue.number}: {issue.title} Author: {issue.user.login} Action: {action} Body: {issue.body} Labels: {issue.labels} If this is a new issue (action=opened): 1. Read the issue title and body carefully 2. Suggest appropriate labels (bug, feature, docs, security, question) 3. If it's a bug report, check if you can identify the affected component from the description 4. Post a helpful initial response acknowledging the issue If this is a label or assignment change, respond with [SILENT]." \ --deliver github_comment ``` ### CI 失败分析 {#ci-failure-analysis} 分析 CI 失败并在 PR 上发布诊断信息。 **触发器:** GitHub Webhook ```yaml # config.yaml route platforms: webhook: enabled: true extra: routes: ci-failure: events: ["check_run"] secret: "ci-secret" prompt: | CI check failed: Repository: {repository.full_name} Check: {check_run.name} Status: {check_run.conclusion} PR: #{check_run.pull_requests.0.number} Details URL: {check_run.details_url} If conclusion is "failure": 1. Fetch the log from the details URL if accessible 2. Identify the likely cause of failure 3. Suggest a fix If conclusion is "success", respond with [SILENT]. deliver: "github_comment" deliver_extra: repo: "{repository.full_name}" pr_number: "{check_run.pull_requests.0.number}" ``` ### 跨仓库自动移植变更 {#auto-port-changes-across-repos} 当一个 PR 在一个仓库中合并时,自动将等效变更移植到另一个仓库。 **触发器:** GitHub Webhook ```bash hermes webhook subscribe auto-port \ --events "pull_request" \ --prompt "PR merged in the source repository: Repository: {repository.full_name} PR #{pull_request.number}: {pull_request.title} Author: {pull_request.user.login} Action: {action} Merge commit: {pull_request.merge_commit_sha} If action is 'closed' and pull_request.merged is true: 1. Fetch the diff: curl -sL {pull_request.diff_url} 2. Analyze what changed 3. Determine if this change needs to be ported to the Go SDK equivalent 4. If yes, create a branch, apply the equivalent changes, and open a PR on the target repo 5. Reference the original PR in the new PR description If action is not 'closed' or not merged, respond with [SILENT]." \ --skill github-pr-workflow \ --deliver log ``` --- ## 业务运营 {#business-operations} ### Stripe 支付监控 {#stripe-payment-monitoring} 跟踪支付事件并获取失败摘要。 **触发器:** API 调用(Webhook) ```bash hermes webhook subscribe stripe-payments \ --events "payment_intent.succeeded,payment_intent.payment_failed,charge.dispute.created" \ --prompt "Stripe event received: Event type: {type} Amount: {data.object.amount} cents ({data.object.currency}) Customer: {data.object.customer} Status: {data.object.status} For payment_intent.payment_failed: - Identify the failure reason from {data.object.last_payment_error} - Suggest whether this is a transient issue (retry) or permanent (contact customer) For charge.dispute.created: - Flag as urgent - Summarize the dispute details For payment_intent.succeeded: - Brief confirmation only Keep responses concise for the ops channel." \ --deliver slack ``` ### 每日收入摘要 {#daily-revenue-summary} 每天早上编译关键业务指标。 **触发器:** 计划任务(每天) ```bash hermes cron create "0 8 * * *" \ "Generate a morning business metrics summary. Search the web for: 1. Current Bitcoin and Ethereum prices 2. S&P 500 status (pre-market or previous close) 3. Any major tech/AI industry news from the last 12 hours Format as a brief morning briefing, 3-4 bullet points max. Deliver as a clean, scannable message." \ --name "Morning briefing" \ --deliver telegram ``` --- ## 多技能工作流 {#multi-skill-workflows} ### 安全审计流水线 {#security-audit-pipeline} 结合多种技能进行全面的每周安全审查。 **触发器:** 计划任务(每周) ```bash hermes cron create "0 3 * * 0" \ "Run a comprehensive security audit of the hermes-agent codebase. 1. Check for dependency vulnerabilities (pip audit, npm audit) 2. Search the codebase for common security anti-patterns: - Hardcoded secrets or API keys - SQL injection vectors (string formatting in queries) - Path traversal risks (user input in file paths without validation) - Unsafe deserialization (pickle.loads, yaml.load without SafeLoader) 3. Review recent commits (last 7 days) for security-relevant changes 4. Check if any new environment variables were added without being documented Write a security report with findings categorized by severity (Critical, High, Medium, Low). If nothing found, report a clean bill of health." \ --skill codebase-security-audit \ --name "Weekly security audit" \ --deliver telegram ``` ### 内容流水线 {#content-pipeline} 按计划研究、起草和准备内容。 **触发器:** 计划任务(每周) ```bash hermes cron create "0 10 * * 3" \ "Research and draft a technical blog post outline about a trending topic in AI agents. 1. Search the web for the most discussed AI agent topics this week 2. Pick the most interesting one that's relevant to open-source AI agents 3. Create an outline with: - Hook/intro angle - 3-4 key sections - Technical depth appropriate for developers - Conclusion with actionable takeaway 4. Save the outline to ~/drafts/blog-$(date +%Y%m%d).md Keep the outline to ~300 words. This is a starting point, not a finished post." \ --name "Blog outline" \ --deliver local ``` --- ## 快速参考 {#quick-reference} ### Cron 调度语法 {#cron-schedule-syntax} | 表达式 | 含义 | |-----------|---------| | `every 30m` | 每 30 分钟 | | `every 2h` | 每 2 小时 | | `0 2 * * *` | 每天凌晨 2:00 | | `0 9 * * 1` | 每周一上午 9:00 | | `0 9 * * 1-5` | 工作日早上 9:00 | | `0 3 * * 0` | 每周日凌晨 3:00 | | `0 */6 * * *` | 每 6 小时 | ### 交付目标 {#delivery-targets} | 目标 | 标志 | 说明 | |--------|------|-------| | 相同聊天 | `--deliver origin` | 默认 — 投递到任务创建的位置 | | 本地文件 | `--deliver local` | 保存输出,不发送通知 | | Telegram | `--deliver telegram` | 主频道,或使用 `telegram:CHAT_ID` 指定特定频道 | | Discord | `--deliver discord` | 主频道,或使用 `discord:CHANNEL_ID` | | Slack | `--deliver slack` | 主频道 | | SMS | `--deliver sms:+15551234567` | 直接发送至电话号码 | | 特定主题帖 | `--deliver telegram:-100123:456` | Telegram 论坛主题 | ### Webhook 模板变量 {#webhook-template-variables} | 变量 | 描述 | |----------|-------------| | `{pull_request.title}` | PR 标题 | | `{issue.number}` | Issue 编号 | | `{repository.full_name}` | `owner/repo` | | `{action}` | 事件操作(opened、closed 等) | | `{__raw__}` | 完整 JSON 负载(截断至 4000 字符) | | `{sender.login}` | 触发事件的 GitHub 用户 | ### [SILENT] 模式 {#the-silent-pattern} 当定时任务的响应包含 `[SILENT]` 时,将抑制投递。使用此功能可避免在静默运行时产生通知垃圾信息: ``` If nothing noteworthy happened, respond with [SILENT]. ``` 这意味着只有当代理有内容需要报告时,你才会收到通知。 --- ### AWS Bedrock - URL: https://hermesagent.org.cn/docs/guides/aws-bedrock - Path: guides/aws-bedrock.md - Category: guides - Description: 将 Hermes Agent 与 Amazon Bedrock 结合使用 — 原生 Converse API、IAM 身份验证、护栏以及跨区域推理 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/aws-bedrock.md - Translated At: 2026-05-03T17:15:32.919Z - Headings: 前提条件 | 快速开始 | 配置 | 区域 (Region) | Guardrails(护栏) | 模型发现 | 可用模型 | 会话中切换模型 | 诊断 | 网关(消息平台) | 故障排除 | “No API key found” / “No AWS credentials” # AWS Bedrock {#aws-bedrock} Hermes Agent 通过 **Converse API**(而非 OpenAI 兼容端点)原生支持 Amazon Bedrock 作为提供商。这使您可以完全访问 Bedrock 生态系统:IAM 身份验证、Guardrails(护栏)、跨区域推理配置文件以及所有基础模型。 ## 前提条件 {#prerequisites} - **AWS 凭证** — [boto3 凭证链](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html) 支持的任何来源: - IAM 实例角色(EC2、ECS、Lambda — 零配置) - `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` 环境变量 - 用于 SSO 或命名配置文件的 `AWS_PROFILE` - 用于本地开发的 `aws configure` - **boto3** — 使用 `pip install hermes-agent[bedrock]` 安装 - **IAM 权限** — 至少需要: - `bedrock:InvokeModel` 和 `bedrock:InvokeModelWithResponseStream`(用于推理) - `bedrock:ListFoundationModels` 和 `bedrock:ListInferenceProfiles`(用于模型发现) :::tip EC2 / ECS / Lambda 在 AWS 计算环境中,附加具有 `AmazonBedrockFullAccess` 权限的 IAM 角色即可。无需 API 密钥,无需 `.env` 配置 — Hermes 会自动检测实例角色。 ::: ## 快速开始 {#quick-start} ```bash # Install with Bedrock support pip install hermes-agent[bedrock] # Select Bedrock as your provider hermes model # → Choose "More providers..." → "AWS Bedrock" # → Select your region and model # Start chatting hermes chat ``` ## 配置 {#configuration} 运行 `hermes model` 后,您的 `~/.hermes/config.yaml` 将包含: ```yaml model: default: us.anthropic.claude-sonnet-4-6 provider: bedrock base_url: https://bedrock-runtime.us-east-2.amazonaws.com bedrock: region: us-east-2 ``` ### 区域 (Region) {#region} 通过以下任一方式设置 AWS 区域(优先级从高到低): 1. `config.yaml` 中的 `bedrock.region` 2. `AWS_REGION` 环境变量 3. `AWS_DEFAULT_REGION` 环境变量 4. 默认值:`us-east-1` ### Guardrails(护栏) {#guardrails} 要将 [Amazon Bedrock Guardrails](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) 应用于所有模型调用: ```yaml bedrock: region: us-east-2 guardrail: guardrail_identifier: "abc123def456" # From the Bedrock console guardrail_version: "1" # Version number or "DRAFT" stream_processing_mode: "async" # "sync" or "async" trace: "disabled" # "enabled", "disabled", or "enabled_full" ``` ### 模型发现 {#model-discovery} Hermes 通过 Bedrock 控制平面自动发现可用模型。您可以自定义发现行为: ```yaml bedrock: discovery: enabled: true provider_filter: ["anthropic", "amazon"] # Only show these providers refresh_interval: 3600 # Cache for 1 hour ``` ## 可用模型 {#available-models} Bedrock 模型使用**推理配置文件 ID** 进行按需调用。`hermes model` 选择器会自动显示这些模型,并将推荐模型置于顶部: | 模型 | ID | 说明 | |-------|-----|-------| | Claude Sonnet 4.6 | `us.anthropic.claude-sonnet-4-6` | 推荐 — 速度与能力的最佳平衡 | | Claude Opus 4.6 | `us.anthropic.claude-opus-4-6-v1` | 能力最强 | | Claude Haiku 4.5 | `us.anthropic.claude-haiku-4-5-20251001-v1:0` | 最快的 Claude 模型 | | Amazon Nova Pro | `us.amazon.nova-pro-v1:0` | Amazon 的旗舰模型 | | Amazon Nova Micro | `us.amazon.nova-micro-v1:0` | 最快、最便宜 | | DeepSeek V3.2 | `deepseek.v3.2` | 强大的开源模型 | | Llama 4 Scout 17B | `us.meta.llama4-scout-17b-instruct-v1:0` | Meta 的最新模型 | :::info 跨区域推理 以 `us.` 为前缀的模型使用跨区域推理配置文件,可在 AWS 区域之间提供更好的容量和自动故障转移。以 `global.` 为前缀的模型在全球所有可用区域之间路由。 ::: ## 会话中切换模型 {#switching-models-mid-session} 在对话期间使用 `/model` 命令: ``` /model us.amazon.nova-pro-v1:0 /model deepseek.v3.2 /model us.anthropic.claude-opus-4-6-v1 ``` ## 诊断 {#diagnostics} ```bash hermes doctor ``` Doctor 检查以下内容: - AWS 凭证是否可用(环境变量、IAM 角色、SSO) - 是否安装了 `boto3` - Bedrock API 是否可达(ListFoundationModels) - 您所在区域的可用模型数量 ## 网关(消息平台) {#gateway-messaging-platforms} Bedrock 适用于所有 Hermes 网关平台(Telegram、Discord、Slack、飞书等)。将 Bedrock 配置为您的提供商,然后正常启动网关: ```bash hermes gateway setup hermes gateway start ``` 网关读取 `config.yaml` 并使用相同的 Bedrock 提供商配置。 ## 故障排除 {#troubleshooting} ### “No API key found” / “No AWS credentials” {#no-api-key-found--no-aws-credentials} Hermes 按以下顺序检查凭证: 1. `AWS_BEARER_TOKEN_BEDROCK` 2. `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` 3. `AWS_PROFILE` 4. EC2 实例元数据 (IMDS) 5. ECS 容器凭证 6. Lambda 执行角色 如果未找到任何凭证,请运行 `aws configure` 或将 IAM 角色附加到您的计算实例。 ### “Invocation of model ID ... with on-demand throughput isn't supported” {#invocation-of-model-id--with-on-demand-throughput-isnt-supported} 请使用**推理配置文件 ID**(以 `us.` 或 `global.` 为前缀),而不是裸基础模型 ID。例如: - ❌ `anthropic.claude-sonnet-4-6` - ✅ `us.anthropic.claude-sonnet-4-6` ### “ThrottlingException” {#throttlingexception} 您已达到 Bedrock 每模型的速率限制。Hermes 会自动使用退避策略重试。要提高限制,请在 [AWS Service Quotas 控制台](https://console.aws.amazon.com/servicequotas/) 中请求配额增加。 --- ### Microsoft Foundry - URL: https://hermesagent.org.cn/docs/guides/azure-foundry - Path: guides/azure-foundry.md - Category: guides - Description: 将 Hermes Agent 与 Microsoft Foundry 结合使用 — OpenAI 风格和 Anthropic 风格的端点,自动检测传输协议和已部署的模型 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/azure-foundry.md - Translated At: 2026-06-16T00:44:51.858Z - Headings: 前提条件 | 快速入门 | Microsoft Entra ID(无密钥,RBAC)— 推荐 | 为什么使用 Entra ID? | 一次性设置(Azure 端) | 一次性设置(Hermes 端) | 写入 config.yaml 的配置 | 凭据解析顺序 | 部署模式 | 主权云(政府云、中国云) | 健康检查 | 限制 # Microsoft Foundry {#microsoft-foundry} Hermes Agent 的 `azure-foundry` 提供程序支持 Microsoft Foundry(前身为 Azure AI Foundry)和 Azure OpenAI。单个 Foundry 资源可以托管具有两种不同线路格式(wire formats)的模型: - **OpenAI 风格** — 在类似 `https://.openai.azure.com/openai/v1` 的端点上使用 `POST /v1/chat/completions`。用于 GPT-4.x、GPT-5.x、Llama、Mistral 以及大多数开放权重模型。 - **Anthropic 风格** — 在类似 `https://.services.ai.azure.com/anthropic` 的端点上使用 `POST /v1/messages`。当 Microsoft Foundry 通过 Anthropic Messages API 格式提供 Claude 模型时使用。 设置向导会探测你的端点,并自动检测其使用的传输协议、可用的部署以及每个模型的上下文长度。 ## 前提条件 {#prerequisites} - 一个至少包含一个部署的 Microsoft Foundry 或 Azure OpenAI 资源 - 该部署的端点 URL - **要么**是 API 密钥(在 Azure 门户的“Keys and Endpoint”下获取),**要么**如果你计划使用 Microsoft Entra ID(微软推荐的无密钥路径),则需要拥有该 Foundry 资源上的 **Azure AI User** RBAC 角色。在微软的重命名推广期间,某些租户可能将该角色显示为 **Foundry User**。 ## 快速入门 {#quick-start} ```bash hermes model # → Select "Azure Foundry" # → Enter your endpoint URL # → Choose Authentication: # 1. API key # 2. Microsoft Entra ID (managed identity / workload identity / az login) # → (Entra) Hermes probes DefaultAzureCredential; on success it never asks for a key # → (API key) Enter your API key # Hermes probes the endpoint and auto-detects transport + models # → Pick a model from the list (or type a deployment name manually) ``` 向导将执行以下操作: 1. **嗅探 URL 路径** — 以 `/anthropic` 结尾的 URL 被识别为 Microsoft Foundry Claude 路由。 2. **探测 `GET /models`** — 如果端点返回 OpenAI 风格的模型列表,Hermes 将切换到 `chat_completions` 并用返回的部署 ID 预填充选择器。 3. **探测 Anthropic Messages 结构** — 针对不暴露 `/models` 但接受 Anthropic Messages 格式的端点的回退方案。 4. **回退到手动输入** — 拒绝所有探测的私有/受限端点仍然可以使用;你需要手动选择 API 模式并输入部署名称。 所选模型的上下文长度通过 Hermes 的标准元数据链(`models.dev`、提供程序元数据和硬编码的家庭回退值)解析,并存储在 `config.yaml` 中,以便模型能够正确调整其上下文窗口的大小。 ## Microsoft Entra ID(无密钥,RBAC)— 推荐 {#microsoft-entra-id-keyless-rbac-—-recommended} 微软建议在生产环境的 Foundry 工作负载中使用[基于 Microsoft Entra ID 的无密钥身份验证](https://learn.microsoft.com/azure/ai-foundry/foundry-models/how-to/configure-entra-id)。Hermes 支持**两种** API 接口的 Entra ID: - **OpenAI 风格**(`api_mode: chat_completions` / `codex_responses`)— GPT-4/5、Llama、Mistral、DeepSeek 等。 - **Anthropic 风格**(`api_mode: anthropic_messages`)— Microsoft Foundry 上的 Claude 模型。 Foundry 的 RBAC 是基于资源的(`Azure AI User` 授予两种接口的权限;某些租户可能显示为 `Foundry User`),并且微软为两者记录了相同的推理范围(`https://ai.azure.com/.default`)。在底层: - OpenAI 风格使用 OpenAI Python SDK 原生的可调用 `api_key=` 契约 — SDK 会自动为每个请求生成一个新的 JWT。 - Anthropic 风格使用带有由 `agent.azure_identity_adapter.build_bearer_http_client` 安装的请求事件钩子的 `httpx.Client`,因为 Anthropic SDK 原生不支持可调用 `auth_token`。该钩子会在每个出站请求中重写 `Authorization: Bearer `。相同的微软 RBAC,相同的 Foundry 范围 — 唯一的区别在于 SDK 契约。 ### 为什么使用 Entra ID? {#why-use-entra-id} - 无需轮换或撤销长期有效的 API 密钥。 - 基于 RBAC 的访问控制 — 在 Foundry 资源上授予或移除 `Azure AI User`,无需重写配置。 - 访问和审计日志按受让人细分,而不是所有调用者共享一个静态密钥。 - 通过托管身份,为 Azure VM、AKS Pod、App Service、Functions、Container Apps 和 Foundry Agent Service 提供统一的身份验证表面。 - 适用于 CI/CD 管道的工作负载身份和服务主体流程。 ### 一次性设置(Azure 端) {#one-time-setup-azure-side} 1. 在 Azure 门户中,打开你的 Foundry 资源 → **Access control (IAM)** → **Add → Add role assignment**。 2. 选择 **Azure AI User** 角色(如果你的租户已重命名角色,则选择 **Foundry User**)。 3. 将其分配给: - **你的用户账户**,用于通过 `az login进行本地开发。 - **托管身份或工作负载身份**,用于 Azure 托管的计算资源(生产环境推荐)。 - **Foundry Agent Service 托管代理的代理身份**,当 Hermes 在托管代理内部运行时。 - **服务主体**,用于在不具备工作负载身份时的 CI/CD 管道。 4. 等待约 5 分钟以便角色传播。 Azure CLI 等效命令: ```bash az role assignment create \ --assignee \ --role "Azure AI User" \ --scope ``` ### 一次性设置(Hermes 端) {#one-time-setup-hermes-side} ```bash hermes model # → Select "Azure Foundry" # → Enter your endpoint URL # → Authentication: 2 (Microsoft Entra ID) # → (optional) user-assigned managed identity client ID # → (optional) Azure tenant ID # → Hermes probes DefaultAzureCredential() and reports which inner # credential succeeded (e.g. AzureCliCredential, ManagedIdentityCredential) ``` 向导运行有界的前置探测(10 秒超时)。如果失败,它会提供“仍然保存,稍后验证”的选项 — 这在尚未拥有凭据但将在运行时拥有凭据的机器上进行配置时非常有用(例如,为托管身份部署准备配置)。 `azure-identity` 会在首次使用时通过 Hermes 的延迟安装路径自动安装。若要预先安装: ```bash pip install azure-identity ``` ### 写入 `config.yaml` 的配置 {#configuration-written-to-configyaml} ```yaml model: provider: azure-foundry base_url: https://my-resource.openai.azure.com/openai/v1 api_mode: chat_completions auth_mode: entra_id default: gpt-4o context_length: 128000 entra: scope: https://ai.azure.com/.default # only when overriding the default ``` Hermes 仅在 `config.yaml` 中管理一个特定于 Entra 的选项: - **`scope`** — OAuth 资源范围。默认为 Microsoft 文档中记录的推理范围(`https://ai.azure.com/.default`)。仅当你的资源是针对非标准受众配置时,才需要覆盖此值。 其他所有内容(租户、服务主体密钥、联合令牌文件、主权云权威机构、代理偏好)均由 `azure-identity` 直接从标准的 `AZURE_*` 环境变量中读取——请参阅下方的[凭据解析顺序](#credential-resolution-order)。请按照 Microsoft SDK 参考文档的描述,在 `~/.hermes/.env` 或你的部署环境中设置这些变量。 在 Entra 模式下,`~/.hermes/.env` 中不会存储任何机密信息——`azure-identity` 会在进程内缓存令牌(如果可用,还会缓存在操作系统密钥链或 `~/.IdentityService` 中)。 ### 凭据解析顺序 {#credential-resolution-order} `azure-identity` 的 `DefaultAzureCredential` 在每次令牌请求时会遍历以下链,并在第一个返回令牌的凭据处停止: 1. **环境变量凭据** — `AZURE_TENANT_ID` + `AZURE_CLIENT_ID` + `AZURE_CLIENT_SECRET`(或 `AZURE_CLIENT_CERTIFICATE_PATH` / `AZURE_FEDERATED_TOKEN_FILE`)。 2. **工作负载标识 (Workload Identity)** — `AZURE_FEDERATED_TOKEN_FILE`(AKS 联合令牌 / OIDC)。 3. **托管标识 (Managed Identity)** — 虚拟机的 IMDS 端点(`169.254.169.254`);App Service / Functions / Container Apps 的 `IDENTITY_ENDPOINT`。Foundry Agent Service 托管代理使用托管代理的代理标识。 4. **Visual Studio Code** — Azure 账户扩展。 5. **Azure CLI** — `az login` 会话。 6. **Azure Developer CLI** — `azd auth login`。 7. **Azure PowerShell** — `Connect-AzAccount`。 8. **代理 (Broker)**(仅限 Windows / WSL)— Web Account Manager。 默认情况下,无人值守的 Hermes 运行排除交互式浏览器凭据;请改用 Azure CLI、Azure Developer CLI、托管标识、工作负载标识或服务主体凭据。 ### 部署模式 {#deployment-patterns} **本地开发:** ```bash az login hermes model # pick Azure Foundry → Entra ID hermes # uses your az login token ``` **Azure VM / Functions / App Service / Container Apps(系统分配的托管标识):** 1. 在计算资源上启用系统分配标识。 2. 在 Foundry 资源上授予该标识 `Azure AI User`(或 `Foundry User`)角色。 3. 在 config.yaml 中设置 `model.auth_mode: entra_id` — 无需环境变量。 **Azure VM / Functions / App Service / Container Apps(用户分配的托管标识):** - 将 `AZURE_CLIENT_ID` 设置为用户分配标识的客户端 ID,以便 `DefaultAzureCredential` 选择正确的标识。 **Foundry Agent Service 托管代理:** - 创建托管代理,并在 Foundry 资源上授予该代理标识 `Azure AI User`(或 `Foundry User`)角色。Hermes 在托管代理内部使用 `ManagedIdentityCredential`;角色分配应属于代理标识,而不仅仅是父项目或你的用户。 **AKS 工作负载标识(取代 AAD Pod Identity):** - 使用工作负载标识客户端 ID 注解 Pod 的服务账户。 - Pod 的联合令牌文件通过 `AZURE_FEDERATED_TOKEN_FILE` 自动检测。 - `model.auth_mode: entra_id` 无需进一步配置更改即可工作。 **CI 中的服务主体:** - 在运行器环境中设置 `AZURE_TENANT_ID`、`AZURE_CLIENT_ID`、`AZURE_CLIENT_SECRET`。 #### 主权云(政府云、中国云) {#sovereign-clouds-government-china} 导出 `AZURE_AUTHORITY_HOST`(例如,Azure Government 为 `https://login.microsoftonline.us`,Azure China 为 `https://login.partner.microsoftonline.cn`)。`azure-identity` 会直接读取该变量。 ### 健康检查 {#health-checks} 当 `model.auth_mode: entra_id` 时,`hermes doctor` 会对 `DefaultAzureCredential` 运行 10 秒探测,报告哪个内部凭据胜出(是否存在环境变量、托管标识端点是否可达等)。 `hermes auth` 显示结构化的状态块: ``` azure-foundry (Microsoft Entra ID): Endpoint: https://my-resource.openai.azure.com/openai/v1 Scope: https://ai.azure.com/.default Status: configured; live token probe is skipped here ``` ### 限制 {#limitations} - **Anthropic 风格的端点使用 httpx 事件钩子。** Anthropic Python SDK 原生不接受可调用的 `auth_token`(≤ 0.86.0 版本)。Hermes 在自定义 `httpx.Client` 上安装了一个请求事件钩子,该钩子为每个出站请求生成一个新的 JWT 并重写 `Authorization: Bearer `。这在功能上等同于 OpenAI SDK 原生的 `Callable[[], str]` 契约,但增加了一层间接调用。如果 Anthropic SDK 在未来版本中添加了一流的可调用身份验证支持,Hermes 将透明地切换到该支持。 - **批处理作业和 `multiprocessing.Pool`。** Entra 令牌提供者是一个闭包,无法跨进程边界进行 pickle 序列化。`batch_runner.py` 会自动从工作器配置中删除该可调用对象,并让每个工作器进程从 `config.yaml` 重建其自己的提供者——无需用户操作,但每个工作器在启动时会执行一次链遍历。 - **`auth.json` 中不持久保存 bearer JWT。** Hermes 不会复制 `azure-identity` 的内部令牌缓存;冷启动时在首次推理时会遍历凭据链。 ## 配置(写入 `config.yaml`) {#configuration-written-to-configyaml-1} 运行向导后,你将看到类似以下内容: ```yaml model: provider: azure-foundry base_url: https://my-resource.openai.azure.com/openai/v1 api_mode: chat_completions # or "anthropic_messages" default: gpt-5.4-mini # your deployment / model name context_length: 400000 # auto-detected ``` 以及在 `~/.hermes/.env` 中: ``` AZURE_FOUNDRY_API_KEY= ``` ## OpenAI 风格端点(GPT、Llama 等) {#openai-style-endpoints-gpt-llama-etc} Azure OpenAI 的 v1 GA 端点接受标准的 `openai` Python 客户端,只需极少更改: ```yaml model: provider: azure-foundry base_url: https://my-resource.openai.azure.com/openai/v1 api_mode: chat_completions default: gpt-5.4 ``` 重要行为: - **GPT-5.x、Codex 和 o 系列模型自动路由至 Responses API。** Microsoft Foundry 将 GPT-5 / Codex / o1 / o3 / o4 模型部署为仅支持 Responses API —— 针对这些模型调用 `/chat/completions` 会返回 `400 "The requested operation is unsupported."`。Hermes 通过名称检测这些模型系列,并透明地将 `api_mode` 升级为 `codex_responses`,即使 `config.yaml` 中仍显示 `api_mode: chat_completions`。GPT-4、GPT-4o、Llama、Mistral 和其他部署则继续使用 `/chat/completions`。 - **自动使用 `max_completion_tokens`。** Azure OpenAI(与直接 OpenAI 类似)要求 gpt-4o、o 系列和 gpt-5.x 模型使用 `max_completion_tokens`。Hermes 会根据端点发送正确的参数。 - **需要 `api-version` 的 v1 之前版本的端点。** 如果你拥有类似 `https://.openai.azure.com/openai?api-version=2025-04-01-preview` 的旧版基础 URL,Hermes 会提取查询字符串,并通过每个请求上的 `default_query` 转发它(否则 OpenAI SDK 在拼接路径时会丢弃该查询字符串)。 ## Anthropic 风格端点(通过 Microsoft Foundry 使用 Claude) {#anthropic-style-endpoints-claude-via-microsoft-foundry} 对于 Claude 部署,请使用 Anthropic 风格的路由: ```yaml model: provider: azure-foundry base_url: https://my-resource.services.ai.azure.com/anthropic api_mode: anthropic_messages default: claude-sonnet-4-6 ``` 重要行为: - **从基础 URL 中剥离 `/v1`。** Anthropic SDK 会将 `/v1/messages` 附加到每个请求 URL 后面 —— Hermes 在将 URL 交给 SDK 之前会移除任何尾随的 `/v1`,以避免出现双重 `/v1` 路径。 - **`api-version` 通过 `default_query` 发送,而不是附加到 URL 上。** Azure Anthropic 需要 `api-version` 查询字符串。将其硬编码到基础 URL 中会产生格式错误的路径,如 `/anthropic?api-version=.../v1/messages`,并返回 404。Hermes 改为通过 Anthropic SDK 的 `default_query` 传递 `api-version=2025-04-15`。 - **使用 Bearer 认证而非 `x-api-key`。** Azure 的 Anthropic 兼容路由要求使用 `Authorization: Bearer `,而不是 Anthropic 原生的 `x-api-key` 标头。Hermes 检测到基础 URL 中包含 `azure.com` 时,会将 API 密钥通过 SDK 的 `auth_token` 字段进行路由,以确保正确的标头到达上游。 - **保留 1M 上下文窗口 Beta 标头。** Azure 仍然通过 `anthropic-beta: context-1m-2025-08-07` 标头对 1M token 的 Claude 上下文(Opus 4.6/4.7、Sonnet 4.6)进行 gating。Hermes 在 Azure 路径上保留该 Beta 标头(由于某些订阅会拒绝该标头,因此它在原生 Anthropic OAuth 请求中被剥离,但 Azure 需要它)。 - **禁用 OAuth 令牌刷新。** Azure 部署使用静态 API 密钥。适用于 Anthropic Console 的 `~/.claude/.credentials.json` OAuth 令牌刷新循环会针对 Azure 端点显式跳过,以防止 Claude Code OAuth 令牌在会话期间覆盖你的 Azure 密钥。 ## 替代方案:`provider: anthropic` + Azure 基础 URL {#alternative-provider-anthropic--azure-base-url} 如果你已经配置了 `provider: anthropic`,并且只想将其指向 Microsoft Foundry 以使用 Claude,则可以完全跳过 `azure-foundry` 提供商: ```yaml model: provider: anthropic base_url: https://my-resource.services.ai.azure.com/anthropic key_env: AZURE_ANTHROPIC_KEY default: claude-sonnet-4-6 ``` 需在 `~/.hermes/.env` 中设置 `AZURE_ANTHROPIC_KEY`。Hermes 检测到基础 URL 中包含 `azure.com` 时,会绕过 Claude Code OAuth 令牌链,直接使用 `x-api-key` 认证方式使用 Azure 密钥。 `key_env` 是规范的 snake_case 字段名称;`api_key_env`(以及 camelCase 形式的 `keyEnv` / `apiKeyEnv`)作为别名被接受。如果同时设置了 `key_env` 和 `AZURE_ANTHROPIC_KEY`/`ANTHROPIC_API_KEY`,则以 `key_env` 命名的环境变量优先。 ## 模型发现 {#model-discovery} Azure **不** 暴露仅使用 API 密钥即可列出已*部署*模型的端点。枚举部署需要通过 Azure AD 主体进行 Azure Resource Manager 身份验证(`az cognitiveservices account deployment list`),而不是使用推理 API 密钥。 Hermes 可以执行的操作: - Azure OpenAI v1 端点(`.openai.azure.com/openai/v1`)暴露 `GET /models`,提供资源的**可用**模型目录。Hermes 使用此列表预填充模型选择器。 - Microsoft Foundry `/anthropic` 路由:通过 URL 路径检测,手动输入模型名称。 - 私有/防火墙后的端点:手动输入,并显示友好的“无法探测”消息。 你可以始终直接输入部署名称 —— Hermes 不会根据返回的列表进行验证。 ## 环境变量 {#environment-variables} | 变量 | 用途 | |----------|---------| | `AZURE_FOUNDRY_API_KEY` | Microsoft Foundry / Azure OpenAI 的主要 API 密钥(api_key 模式) | | `AZURE_FOUNDRY_BASE_URL` | 端点 URL(通过 `hermes model` 设置;环境变量用作回退) | | `AZURE_ANTHROPIC_KEY` | 由 `provider: anthropic` + Azure 基础 URL 使用(`ANTHROPIC_API_KEY` 的替代方案) | | `AZURE_TENANT_ID` | 用于服务主体流程的 Entra ID 租户 | | `AZURE_CLIENT_ID` | Entra ID 客户端 ID(服务主体、工作负载标识或用户分配的托管标识) | | `AZURE_CLIENT_SECRET` | 服务主体密钥 | | `AZURE_CLIENT_CERTIFICATE_PATH` | 服务主体证书(密钥的替代方案) | | `AZURE_FEDERATED_TOKEN_FILE` | 工作负载标识联合令牌路径(AKS) | | `AZURE_AUTHORITY_HOST` | 主权云权威主机覆盖 | | `IDENTITY_ENDPOINT` / `MSI_ENDPOINT` | App Service、Functions 和 Container Apps 的托管标识端点;VM 通常改用 IMDS | Azure SDK 直接读取 `AZURE_*` 环境变量。Hermes 除了报告 `hermes doctor` 输出中存在哪些源之外,从不检查这些变量。 ## 故障排除 {#troubleshooting} **gpt-5.x 部署出现 401 Unauthorized。** Azure 在 `/chat/completions` 上提供 gpt-5.x 服务,而不是 `/responses`。当 URL 包含 `openai.azure.com` 时,Hermes 会自动处理此问题,但如果你看到带有 `Invalid API key` 正文的 401 错误,请检查 `config.yaml` 中的 `api_mode` 是否为 `chat_completions`。 **`/v1/messages?api-version=.../v1/messages` 出现 404。** 这是修复前 Azure Anthropic 设置中的 malformed-URL(URL 格式错误)bug。升级 Hermes — `api-version` 参数现在通过 `default_query` 传递,而不是硬编码到基础 URL 中,因此 SDK 在连接 URL 时不会破坏它。 **向导显示“自动检测不完整。”** 端点拒绝了 `/models` 探测和 Anthropic Messages 探测。对于位于防火墙后或具有 IP 允许列表的私有端点,这是正常现象。回退到手动 API 模式选择并输入你的部署名称 — 一切仍然有效,只是 Hermes 无法预填充选择器。 **选择了错误的传输方式。** 再次运行 `hermes model`,向导将重新探测。如果探测仍然选择错误的模式,你可以直接编辑 `config.yaml`: ```yaml model: provider: azure-foundry api_mode: anthropic_messages # or chat_completions ``` **Entra ID:切换到 `auth_mode: entra_id` 后出现“credential chain exhausted”(凭据链耗尽)或 401 Unauthorized。** - 运行 `az login` 以刷新你的开发者会话(缓存的令牌可能已过期)。 - 验证 `Azure AI User`(或 `Foundry User`)角色分配是否生效:`az role assignment list --assignee ` 应在你的 Foundry 资源上列出该角色。角色传播最多可能需要 5 分钟。 - 对于用户分配的托管标识,仔细检查 `AZURE_CLIENT_ID` 是否与附加到计算资源的标识匹配。 - 运行 `hermes doctor` — Azure Entra 探测会报告令牌获取是否成功,并包含补救提示。 **Entra ID:向导预检挂起或超时。** 10 秒预检是一项软检查。选择“无论如何保存并稍后验证”,然后在部署到目标环境后运行 `hermes doctor`。常见原因包括令牌服务不可达或本地登录状态过时 — 在 CI 中首选工作负载标识,在使用服务主体时设置 `AZURE_TENANT_ID`+`AZURE_CLIENT_ID`+`AZURE_CLIENT_SECRET`,或在本地开发时运行 `az login`。 **带有 Entra ID 的 Anthropic 风格端点出现 401。** 验证 Foundry 资源上是否分配了相同的 `Azure AI User`(或 `Foundry User`)角色(它涵盖 `/openai/v1` 和 `/anthropic` 路径)。如果向导期间 OpenAI 风格探测成功,但 `claude-*` 请求在运行时失败,最常见的原因是早期向导运行留下的过时 `model.entra.scope` — 从 `config.yaml` 中删除 `entra.scope` 行,以便运行时回退到默认的 `https://ai.azure.com/.default` 范围。 ## 相关 {#related} - [环境变量](/docs/reference/environment-variables) - [配置](/docs/user-guide/configuration) - [AWS Bedrock](/docs/guides/aws-bedrock) — 另一个主要的云提供商集成 - [Microsoft: Configure Entra ID for Foundry](https://learn.microsoft.com/azure/ai-foundry/foundry-models/how-to/configure-entra-id) — 无密钥路径的上游文档 --- ### 构建一个 Hermes 插件 - URL: https://hermesagent.org.cn/docs/guides/build-a-hermes-plugin - Path: guides/build-a-hermes-plugin.md - Category: guides - Description: 使用工具、钩子、数据文件和技能构建完整 Hermes 插件的逐步指南 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/build-a-hermes-plugin.md - Translated At: 2026-04-11T03:27:06.343Z - Headings: 你将构建的内容 | 第一步:创建插件目录 | 第二步:编写清单文件 | 第三步:编写工具 Schema | 第四步:编写工具处理器 | 第五步:编写注册逻辑 | 第六步:测试插件 | 你的插件最终结构 | 插件还能做什么? | 打包数据文件 | 打包一个技能文件 | 基于环境变量启用/禁用 # 构建一个 Hermes 插件 {#build-a-hermes-plugin} 本指南将带你从零开始构建一个完整的 Hermes 插件。完成之后,你将拥有一个功能齐全的插件,包含多个工具、生命周期钩子、已打包的数据文件以及一个内置技能文件——涵盖了插件系统支持的所有功能。 ## 你将构建的内容 {#what-youre-building} 一个 **计算器** 插件,包含两个工具: - `calculate` —— 计算数学表达式(`2**16`,`sqrt(144)`,`pi * 5**2`) - `unit_convert` —— 单位转换(`100 F → 37.78 C`,`5 km → 3.11 mi`) 此外还包括一个在每次工具调用时记录日志的钩子,以及一个打包的技能文件。 ## 第一步:创建插件目录 {#step-1-create-the-plugin-directory} ```bash mkdir -p ~/.hermes/plugins/calculator cd ~/.hermes/plugins/calculator ``` ## 第二步:编写清单文件 {#step-2-write-the-manifest} 创建 `plugin.yaml`: ```yaml name: calculator version: 1.0.0 description: Math calculator — evaluate expressions and convert units provides_tools: - calculate - unit_convert provides_hooks: - post_tool_call ``` 这告诉 Hermes:“我是一个名为 calculator 的插件,我提供工具和钩子。”`provides_tools` 和 `provides_hooks` 字段列出了插件注册的内容。 可选字段(你可以添加): ```yaml author: Your Name requires_env: # 环境变量的门加载;安装时提示 - SOME_API_KEY # 简单格式 - 如果缺少插件则禁用 - name: OTHER_KEY # rich 格式 — 安装期间显示说明 /url description: "Key for the Other service" url: "https://other.com/keys" secret: true ``` ## 第三步:编写工具 Schema {#step-3-write-the-tool-schemas} 创建 `schemas.py` —— 这是 LLM 用来决定何时调用你的工具的依据: ```python """Tool schemas — what the LLM sees.""" CALCULATE = { "name": "calculate", "description": ( "Evaluate a mathematical expression and return the result. " "Supports arithmetic (+, -, *, /, **), functions (sqrt, sin, cos, " "log, abs, round, floor, ceil), and constants (pi, e). " "Use this for any math the user asks about." ), "parameters": { "type": "object", "properties": { "expression": { "type": "string", "description": "Math expression to evaluate (e.g., '2**10', 'sqrt(144)')", }, }, "required": ["expression"], }, } UNIT_CONVERT = { "name": "unit_convert", "description": ( "Convert a value between units. Supports length (m, km, mi, ft, in), " "weight (kg, lb, oz, g), temperature (C, F, K), data (B, KB, MB, GB, TB), " "and time (s, min, hr, day)." ), "parameters": { "type": "object", "properties": { "value": { "type": "number", "description": "The numeric value to convert", }, "from_unit": { "type": "string", "description": "Source unit (e.g., 'km', 'lb', 'F', 'GB')", }, "to_unit": { "type": "string", "description": "Target unit (e.g., 'mi', 'kg', 'C', 'MB')", }, }, "required": ["value", "from_unit", "to_unit"], }, } ``` **Schema 为何重要:** `description` 字段是 LLM 决定是否使用你的工具的关键。请明确描述其功能以及使用场景。`parameters` 定义了 LLM 传递给工具的参数。 ## 第四步:编写工具处理器 {#step-4-write-the-tool-handlers} 创建 `tools.py` —— 这是当 LLM 调用工具时实际执行的代码: ```python """Tool handlers — the code that runs when the LLM calls each tool.""" import json import math # 用于表达式求值的安全全局变量 — 无 file/network 访问权限 _SAFE_MATH = { "abs": abs, "round": round, "min": min, "max": max, "pow": pow, "sqrt": math.sqrt, "sin": math.sin, "cos": math.cos, "tan": math.tan, "log": math.log, "log2": math.log2, "log10": math.log10, "floor": math.floor, "ceil": math.ceil, "pi": math.pi, "e": math.e, "factorial": math.factorial, } def calculate(args: dict, **kwargs) -> str: """Evaluate a math expression safely. Rules for handlers: 1. Receive args (dict) — the parameters the LLM passed 2. Do the work 3. Return a JSON string — ALWAYS, even on error 4. Accept **kwargs for forward compatibility """ expression = args.get("expression", "").strip() if not expression: return json.dumps({"error": "No expression provided"}) try: result = eval(expression, {"__builtins__": {}}, _SAFE_MATH) return json.dumps({"expression": expression, "result": result}) except ZeroDivisionError: return json.dumps({"expression": expression, "error": "Division by zero"}) except Exception as e: return json.dumps({"expression": expression, "error": f"Invalid: {e}"}) # 换算表 — 值采用基本单位 _LENGTH = {"m": 1, "km": 1000, "mi": 1609.34, "ft": 0.3048, "in": 0.0254, "cm": 0.01} _WEIGHT = {"kg": 1, "g": 0.001, "lb": 0.453592, "oz": 0.0283495} _DATA = {"B": 1, "KB": 1024, "MB": 1024**2, "GB": 1024**3, "TB": 1024**4} _TIME = {"s": 1, "ms": 0.001, "min": 60, "hr": 3600, "day": 86400} def _convert_temp(value, from_u, to_u): # 标准化为摄氏度 c = {"F": (value - 32) * 5/9, "K": value - 273.15}.get(from_u, value) # 转换为目标 return {"F": c * 9/5 + 32, "K": c + 273.15}.get(to_u, c) def unit_convert(args: dict, **kwargs) -> str: """Convert between units.""" value = args.get("value") from_unit = args.get("from_unit", "").strip() to_unit = args.get("to_unit", "").strip() if value is None or not from_unit or not to_unit: return json.dumps({"error": "Need value, from_unit, and to_unit"}) try: # 温度 if from_unit.upper() in {"C","F","K"} and to_unit.upper() in {"C","F","K"}: result = _convert_temp(float(value), from_unit.upper(), to_unit.upper()) return json.dumps({"input": f"{value} {from_unit}", "result": round(result, 4), "output": f"{round(result, 4)} {to_unit}"}) # 基于比率的转换 for table in (_LENGTH, _WEIGHT, _DATA, _TIME): lc = {k.lower(): v for k, v in table.items()} if from_unit.lower() in lc and to_unit.lower() in lc: result = float(value) * lc[from_unit.lower()] / lc[to_unit.lower()] return json.dumps({"input": f"{value} {from_unit}", "result": round(result, 6), "output": f"{round(result, 6)} {to_unit}"}) return json.dumps({"error": f"Cannot convert {from_unit} → {to_unit}"}) except Exception as e: return json.dumps({"error": f"Conversion failed: {e}"}) ``` **处理器的关键规则:** 1. **签名:** `def my_handler(args: dict, **kwargs) -> str` 2. **返回值:** 始终返回 JSON 字符串。无论成功或失败都如此。 3. **绝不抛出异常:** 捕获所有异常,返回错误的 JSON 而非抛出。 4. **接受 `**kwargs`:** Hermes 未来可能会传递额外上下文。 ## 第五步:编写注册逻辑 {#step-5-write-the-registration} 创建 `__init__.py` —— 这是将 Schema 与处理器连接起来的文件: ```python """Calculator plugin — registration.""" import logging from . import schemas, tools logger = logging.getLogger(__name__) # 通过钩子跟踪 tool 使用情况 _call_log = [] def _on_post_tool_call(tool_name, args, result, task_id, **kwargs): """Hook: runs after every tool call (not just ours).""" _call_log.append({"tool": tool_name, "session": task_id}) if len(_call_log) > 100: _call_log.pop(0) logger.debug("Tool called: %s (session %s)", tool_name, task_id) def register(ctx): """Wire schemas to handlers and register hooks.""" ctx.register_tool(name="calculate", toolset="calculator", schema=schemas.CALCULATE, handler=tools.calculate) ctx.register_tool(name="unit_convert", toolset="calculator", schema=schemas.UNIT_CONVERT, handler=tools.unit_convert) # 此钩子会针对 ALL tool 调用触发,而不仅仅是我们的调用 ctx.register_hook("post_tool_call", _on_post_tool_call) ``` **`register()` 的作用:** - 在启动时仅调用一次 - `ctx.register_tool()` 将你的工具注册到系统中——模型会立即看到它 - `ctx.register_hook()` 订阅生命周期事件 - `ctx.register_cli_command()` 注册一个 CLI 子命令(例如 `hermes my-plugin `) - 如果此函数崩溃,插件将被禁用,但 Hermes 仍能正常运行 ## 第六步:测试插件 {#step-6-test-it} 启动 Hermes: ```bash hermes ``` 你应该在启动横幅的工具列表中看到 `calculator: calculate, unit_convert`。 尝试以下提示: ``` What's 2 to the power of 16? Convert 100 fahrenheit to celsius What's the square root of 2 times pi? How many gigabytes is 1.5 terabytes? ``` 检查插件状态: ``` /plugins ``` 输出结果: ``` Plugins (1): ✓ calculator v1.0.0 (2 tools, 1 hooks) ``` ## 你的插件最终结构 {#your-plugins-final-structure} ``` ~/.hermes/plugins/calculator/ ├── plugin.yaml # "I'm calculator, I provide tools and hooks" ├── __init__.py # 连线:模式 → 处理程序、注册挂钩 ├── schemas.py # LLM 读取的内容(描述 + 参数规格) └── tools.py # 运行什么(计算、unit_convert 函数) ``` 四个文件,职责清晰分离: - **清单文件**:声明插件的身份 - **Schema 文件**:向 LLM 描述工具 - **处理器文件**:实现实际逻辑 - **注册文件**:连接所有组件 ## 插件还能做什么? {#what-else-can-plugins-do} ### 打包数据文件 {#ship-data-files} 将任意文件放入插件目录,并在导入时读取: ```python # 在 tools.py 或 __init__.py 中 from pathlib import Path _PLUGIN_DIR = Path(__file__).parent _DATA_FILE = _PLUGIN_DIR / "data" / "languages.yaml" with open(_DATA_FILE) as f: _DATA = yaml.safe_load(f) ``` ### 打包一个技能文件 {#bundle-a-skill} 包含一个 `skill.md` 文件,并在注册时安装: ```python import shutil from pathlib import Path def _install_skill(): """Copy our skill to ~/.hermes/skills/ on first load.""" try: from hermes_cli.config import get_hermes_home dest = get_hermes_home() / "skills" / "my-plugin" / "SKILL.md" except Exception: dest = Path.home() / ".hermes" / "skills" / "my-plugin" / "SKILL.md" if dest.exists(): return # 不要覆盖用户编辑 source = Path(__file__).parent / "skill.md" if source.exists(): dest.parent.mkdir(parents=True, exist_ok=True) shutil.copy2(source, dest) def register(ctx): ctx.register_tool(...) _install_skill() ``` ### 基于环境变量启用/禁用 {#gate-on-environment-variables} 如果插件需要 API 密钥: ```yaml # plugin.yaml — 简单格式(向后兼容) requires_env: - WEATHER_API_KEY ``` 如果未设置 `WEATHER_API_KEY`,插件将被禁用,并显示清晰提示。不会崩溃,也不会导致 Agent 出错——只会显示“Plugin weather disabled (missing: WEATHER_API_KEY)”。 当用户运行 `hermes plugins install` 时,系统会 **交互式提示** 输入任何缺失的 `requires_env` 变量。值会自动保存到 `.env` 文件中。 为了获得更好的安装体验,可以使用带描述和注册链接的丰富格式: ```yaml # plugin.yaml — rich 格式 requires_env: - name: WEATHER_API_KEY description: "API key for OpenWeather" url: "https://openweathermap.org/api" secret: true ``` | 字段 | 是否必需 | 描述 | |------|----------|------| | `name` | 是 | 环境变量名称 | | `description` | 否 | 安装提示时向用户显示 | | `url` | 否 | 获取凭证的地址 | | `secret` | 否 | 若为 `true`,输入将隐藏(如密码字段) | 两种格式可在同一列表中混合使用。已设置的变量会静默跳过。 ### 条件性工具可用性 {#conditional-tool-availability} 对于依赖可选库的工具: ```python ctx.register_tool( name="my_tool", schema={...}, handler=my_handler, check_fn=lambda: _has_optional_lib(), # False = Tool 对 模型 隐藏 ) ``` ### 注册多个钩子 {#register-multiple-hooks} ```python def register(ctx): ctx.register_hook("pre_tool_call", before_any_tool) ctx.register_hook("post_tool_call", after_any_tool) ctx.register_hook("pre_llm_call", inject_memory) ctx.register_hook("on_session_start", on_new_session) ctx.register_hook("on_session_end", on_session_end) ``` ### 钩子参考 {#hook-reference} 每个钩子的完整文档请参见 **[事件钩子参考](/docs/user-guide/features/hooks#plugin-hooks)** —— 包括回调签名、参数表、触发时机以及示例。以下是摘要: | 钩子 | 触发时机 | 回调签名 | 返回值 | |------|-----------|-------------------|---------| | [`pre_tool_call`](/docs/user-guide/features/hooks#pre_tool_call) | 任何工具执行前 | `tool_name: str, args: dict, task_id: str` | 忽略 | | [`post_tool_call`](/docs/user-guide/features/hooks#post_tool_call) | 任何工具返回后 | `tool_name: str, args: dict, result: str, task_id: str` | 忽略 | | [`pre_llm_call`](/docs/user-guide/features/hooks#pre_llm_call) | 每轮一次,在工具调用循环之前 | `session_id: str, user_message: str, conversation_history: list, is_first_turn: bool, model: str, platform: str` | [上下文注入](#pre_llm_call-context-injection) | | [`post_llm_call`](/docs/user-guide/features/hooks#post_llm_call) | 每轮一次,在工具调用循环之后(仅成功轮次) | `session_id: str, user_message: str, assistant_response: str, conversation_history: list, model: str, platform: str` | 忽略 | | [`on_session_start`](/docs/user-guide/features/hooks#on_session_start) | 新会话创建时(仅第一轮) | `session_id: str, model: str, platform: str` | 忽略 | | [`on_session_end`](/docs/user-guide/features/hooks#on_session_end) | 每次 `run_conversation` 调用结束 + CLI 退出时 | `session_id: str, completed: bool, interrupted: bool, model: str, platform: str` | 忽略 | | [`pre_api_request`](/docs/user-guide/features/hooks#plugin-hooks) | 每次向 LLM 提供商发起 HTTP 请求前 | `method: str, url: str, headers: dict, body: dict` | 忽略 | | [`post_api_request`](/docs/user-guide/features/hooks#plugin-hooks) | 每次从 LLM 提供商收到 HTTP 响应后 | `method: str, url: str, status_code: int, response: dict` | 忽略 | 大多数钩子都是“触发即丢弃”的观察者——它们的返回值被忽略。例外是 `pre_llm_call`,它可以向对话中注入上下文。 所有回调都应接受 `**kwargs` 以保证向前兼容性。如果某个钩子回调崩溃,它会被记录并跳过,其他钩子和 Agent 将继续正常运行。 ### `pre_llm_call` 上下文注入 {#pre_llm_call-context-injection} 这是唯一一个返回值有意义的钩子。当 `pre_llm_call` 回调返回一个包含 `"context"` 键的字典(或一个非空字符串)时,Hermes 会将该文本注入到**当前轮次的用户消息**中。这是实现记忆插件、RAG 集成、安全护栏以及任何需要向模型提供额外上下文的插件的机制。 #### 返回格式 {#return-format} ```python # 带 context 键的字典 return {"context": "Recalled memories:\n- User prefers dark mode\n- Last project: hermes-agent"} # 纯字符串(相当于上面的字典形式) return "Recalled memories:\n- User prefers dark mode" # 返回 None 或不返回 → 不注入(仅限观察者) return None ``` 任何非 None、非空的返回值,若包含 `"context"` 键(或为非空字符串),都会被收集并附加到当前轮次的用户消息中。 #### 注入机制说明 {#how-injection-works} 注入的上下文是附加到**用户消息**,而非系统提示。这是有意为之的设计选择: - **提示缓存保留** —— 系统提示在各轮次中保持一致。Anthropic 和 OpenRouter 会缓存系统提示前缀,保持其稳定可节省多轮对话中 75% 以上的输入 token。如果插件修改了系统提示,每轮都会导致缓存未命中。 - **瞬时性** —— 注入仅在 API 调用时发生。对话历史中的原始用户消息永远不会被修改,也不会持久化到会话数据库。 - **系统提示属于 Hermes 的领域** —— 系统提示包含模型特定的指导、工具强制规则、人格指令和缓存的技能内容。插件应与用户输入一同提供上下文,而非通过修改 Agent 的核心指令。 #### 示例:记忆召回插件 {#example-memory-recall-plugin} ```python """Memory plugin — recalls relevant context from a vector store.""" import httpx MEMORY_API = "https://your-memory-api.example.com" def recall_context(session_id, user_message, is_first_turn, **kwargs): """Called before each LLM turn. Returns recalled memories.""" try: resp = httpx.post(f"{MEMORY_API}/recall", json={ "session_id": session_id, "query": user_message, }, timeout=3) memories = resp.json().get("results", []) if not memories: return None # 没有什么可注射的 text = "Recalled context from previous sessions:\n" text += "\n".join(f"- {m['text']}" for m in memories) return {"context": text} except Exception: return None # 默默地失败,不要破坏agent def register(ctx): ctx.register_hook("pre_llm_call", recall_context) ``` #### 示例:安全护栏插件 {#example-guardrails-plugin} ```python """Guardrails plugin — enforces content policies.""" POLICY = """You MUST follow these content policies for this session: - Never generate code that accesses the filesystem outside the working directory - Always warn before executing destructive operations - Refuse requests involving personal data extraction""" def inject_guardrails(**kwargs): """Injects policy text into every turn.""" return {"context": POLICY} def register(ctx): ctx.register_hook("pre_llm_call", inject_guardrails) ``` #### 示例:仅观察型钩子(无注入) {#example-observer-only-hook-no-injection} ```python """Analytics plugin — tracks turn metadata without injecting context.""" import logging logger = logging.getLogger(__name__) def log_turn(session_id, user_message, model, is_first_turn, **kwargs): """Fires before each LLM call. Returns None — no context injected.""" logger.info("Turn: session=%s model=%s first=%s msg_len=%d", session_id, model, is_first_turn, len(user_message or "")) # 无返回→无注入 def register(ctx): ctx.register_hook("pre_llm_call", log_turn) ``` #### 多个插件同时返回上下文 {#multiple-plugins-returning-context} 当多个插件从 `pre_llm_call` 返回上下文时,它们的输出将通过双换行符连接,并一同附加到用户消息中。顺序遵循插件发现顺序(按插件目录名称的字母顺序)。 ### 注册 CLI 命令 {#register-cli-commands} 插件可以添加自己的 `hermes ` 子命令树: ```python def _my_command(args): """Handler for hermes my-plugin .""" sub = getattr(args, "my_command", None) if sub == "status": print("All good!") elif sub == "config": print("Current config: ...") else: print("Usage: hermes my-plugin ") def _setup_argparse(subparser): """Build the argparse tree for hermes my-plugin.""" subs = subparser.add_subparsers(dest="my_command") subs.add_parser("status", help="Show plugin status") subs.add_parser("config", help="Show plugin config") subparser.set_defaults(func=_my_command) def register(ctx): ctx.register_tool(...) ctx.register_cli_command( name="my-plugin", help="Manage my plugin", setup_fn=_setup_argparse, handler_fn=_my_command, ) ``` 注册后,用户可以运行 `hermes my-plugin status`、`hermes my-plugin config` 等命令。 **记忆提供者插件**采用基于约定的方式:在插件的 `cli.py` 文件中添加 `register_cli(subparser)` 函数。记忆插件发现系统会自动找到它——无需调用 `ctx.register_cli_command()`。详情请参见 [记忆提供者插件指南](/docs/developer-guide/memory-provider-plugin#adding-cli-commands)。 **激活提供者控制**:记忆插件的 CLI 命令仅在配置中设置为活动 `memory.provider` 时才会显示。如果用户未配置你的提供者,你的 CLI 命令不会出现在帮助输出中,避免干扰。 :::tip 本指南涵盖**通用插件**(工具、钩子、CLI 命令)。对于特定类型的插件,请参阅: - [记忆提供者插件](/docs/developer-guide/memory-provider-plugin) —— 跨会话知识后端 - [上下文引擎插件](/docs/developer-guide/context-engine-plugin) —— 替代上下文管理策略 ::: ### 通过 pip 发布 {#distribute-via-pip} 对于公开共享插件,请在您的 Python 包中添加入口点: ```toml # pyproject.toml [project.entry-points."hermes_agent.plugins"] my-plugin = "my_plugin_package" ``` ```bash pip install hermes-plugin-calculator # 下次 hermes 启动时自动发现插件 ``` ## 常见错误 {#common-mistakes} **处理器未返回 JSON 字符串:** ```python # 错误——返回一个字典 def handler(args, **kwargs): return {"result": 42} # 右 — 返回 JSON 字符串 def handler(args, **kwargs): return json.dumps({"result": 42}) ``` **处理器签名中缺少 `**kwargs`:** ```python # 错误 — 如果 Hermes 通过额外的 context 将中断 def handler(args): ... # 正确的 def handler(args, **kwargs): ... ``` **处理器抛出异常:** ```python # 错误 — 异常传播,tool 调用失败 def handler(args, **kwargs): result = 1 / int(args["value"]) # 零除法错误! return json.dumps({"result": result}) # 右 — 捕获并返回错误 JSON def handler(args, **kwargs): try: result = 1 / int(args.get("value", 0)) return json.dumps({"result": result}) except Exception as e: return json.dumps({"error": str(e)}) ``` **模式描述过于模糊:** ```python # 不好——model 不知道什么时候使用它 "description": "Does stuff" # 好 — model 确切地知道何时以及如何 "description": "Evaluate a mathematical expression. Use for arithmetic, trig, logarithms. Supports: +, -, *, /, **, sqrt, sin, cos, log, pi, e." ``` --- ### 仅脚本的 Cron 作业(无 LLM) - URL: https://hermesagent.org.cn/docs/guides/cron-script-only - Path: guides/cron-script-only.md - Category: guides - Description: 完全绕过 LLM 的经典看门狗 cron 任务——脚本按计划运行,其标准输出(stdout)会被发送到你的消息平台。包括内存警报、磁盘警报、CI 心跳信号、定期健康检查。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/cron-script-only.md - Translated At: 2026-06-16T00:43:56.302Z - Headings: 何时使用 | 从聊天中创建 | 示例对话 | 代理为你做出的决定 | 从聊天中管理看门狗 | 从 CLI 创建 | 脚本输出如何映射到投递 | 脚本规则 | 调度语法 | 投递目标 | 编辑与生命周期 | 实际示例:磁盘空间警报 # 仅脚本的 Cron 任务 {#script-only-cron-jobs} 有时你已经确切知道想要发送的消息内容。你不需要代理(agent)来进行推理——你只需要一个按定时器运行的脚本,并将其输出(如果有)发送到 Telegram / Discord / Slack / Signal。 Hermes 将此称为**无代理模式**(no-agent mode)。它是去除了大语言模型(LLM)的 cron 系统。 ``` ┌──────────────────┐ ┌──────────────────┐ │ scheduler tick │ every │ run script │ │ (every N minutes)│ ──────▶ │ (bash or python) │ └──────────────────┘ └──────────────────┘ │ │ stdout ▼ ┌──────────────────┐ │ delivery router │ │ (telegram/disc…) │ └──────────────────┘ ``` - **无 LLM 调用。**零 Token,零代理循环,零模型花费。 - **脚本即任务。**脚本决定是否发出警报。产生输出 → 发送消息。不产生输出 → 静默心跳。 - **Bash 或 Python。**`.sh` / `.bash` 文件在 `/bin/bash` 下运行;任何其他扩展名的文件在当前 Python 解释器下运行。`~/.hermes/scripts/` 中的任何文件均被接受。 - **相同的调度器。**与 LLM 任务一起存在于 `cronjob` 中——暂停、恢复、列出、日志记录和投递目标的工作方式完全相同。 ## 何时使用 {#when-to-use-it} 在以下场景中使用无代理模式: - **内存/磁盘/GPU 看门狗。**每 5 分钟运行一次,仅在超过阈值时发出警报。 - **CI 钩子。**部署完成 → 发布 commit SHA。构建失败 → 发送日志的最后 100 行。 - **定期指标。**“每天早上 9 点的 Stripe 收入”,通过简单的 API 调用 + 美化打印实现。 - **外部事件轮询器。**检查 API,在状态变更时发出警报。 - **心跳检测。**每 N 分钟 ping 一次仪表板以证明主机存活。 当需要代理**决定**说什么时使用常规(LLM 驱动)的 cron 任务——例如总结长文档、从 feed 中挑选有趣的项目、起草人性化的消息。无代理路径适用于脚本的 stdout 本身**就是**消息的情况。 ## 从聊天中创建 {#create-one-from-chat} 无代理模式的真正优势在于,代理本身可以为你设置看门狗——无需编辑器,无需 shell,无需记忆 CLI 标志。你描述所需内容,Hermes 编写脚本、安排调度,并告知你何时触发。 ### 示例对话 {#example-transcript} > **你:**如果 RAM 超过 85%,每 5 分钟在 Telegram 上提醒我 > > **Hermes:***(写入 `~/.hermes/scripts/memory-watchdog.sh`,然后使用 `no_agent=true` 调用 `cronjob(...)`)* > > 已设置。每 5 分钟运行一次,仅在 RAM 超过 85% 时向 Telegram 发出警报。脚本:`memory-watchdog.sh`。任务 ID:`abc123`。 在底层,代理进行了两次工具调用: ```python # 1. Write the check script write_file( path="~/.hermes/scripts/memory-watchdog.sh", content='''#!/usr/bin/env bash ram_pct=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}') if [ "$ram_pct" -ge 85 ]; then echo "RAM ${ram_pct}% on $(hostname)" fi # Empty stdout = silent tick; no message sent. ''', ) # 2. Schedule it — no_agent=True skips the LLM on every tick cronjob( action="create", schedule="every 5m", script="memory-watchdog.sh", no_agent=True, deliver="telegram", name="memory-watchdog", ) ``` 从那一刻起,每次心跳都是免费的:调度器运行脚本,如果 stdout 非空则将其管道传输到 Telegram,并且绝不接触模型。 ### 代理为你做出的决定 {#what-the-agent-decides-for-you} 当你提出类似“当 X 发生时提醒我”或“每 N 分钟检查 Y 并在 Z 发生时告诉我”这样的请求时,Hermes 的 `cronjob` 工具描述会指示它在消息内容完全由脚本确定时使用 `no_agent=True`。当请求需要推理时(*“总结新问题”*、*“挑选最有趣的头条新闻”*、*“起草友好的提醒”*),它会回退到正常的 LLM 驱动路径。 你不必自己指定 `--no-agent`。只需描述行为即可。 ### 从聊天中管理看门狗 {#managing-watchdogs-from-chat} 代理可以像创建任务一样暂停、恢复、编辑和删除任务: > **你:**今晚停止内存看门狗 > > **Hermes:***(调用 `cronjob(action='pause', job_id='abc123')`)* > > 已暂停。通过说“重新开启它”或使用 `hermes cron resume abc123` 来恢复。 > **你:**改为每 15 分钟一次 > > **Hermes:***(调用 `cronjob(action='update', job_id='abc123', schedule='every 15m')`)* 完整的生命周期(创建/列出/更新/暂停/恢复/立即运行/删除)对代理可用,而你无需学习任何 CLI 命令。 ## 从 CLI 创建 {#create-one-from-the-cli} 更喜欢使用 shell?CLI 路径通过三个命令提供相同的结果: ```bash # 1. Write your script cat > ~/.hermes/scripts/memory-watchdog.sh <<'EOF' #!/usr/bin/env bash # Alert when RAM usage is over 85%. Silent otherwise. RAM_PCT=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}') if [ "$RAM_PCT" -ge 85 ]; then echo "⚠ RAM ${RAM_PCT}% on $(hostname)" fi # Empty stdout = silent run; no message sent. EOF chmod +x ~/.hermes/scripts/memory-watchdog.sh # 2. Schedule it hermes cron create "every 5m" \ --no-agent \ --script memory-watchdog.sh \ --deliver telegram \ --name "memory-watchdog" # 3. Verify hermes cron list hermes cron run # fire it once to test ``` 这就是全部。无需提示,无需技能,无需模型。 ## 脚本输出如何映射到投递 {#how-script-output-maps-to-delivery} | 脚本行为 | 结果 | |-----------------|--------| | 退出码 0,stdout 非空 | 原样投递 stdout | | 退出码 0,stdout 为空 | 静默心跳 — 无投递 | | 退出码 0,stdout 最后一行包含 `{"wakeAgent": false}` | 静默心跳(与 LLM 任务共享的门控机制) | | 非零退出码 | 投递错误警报(因此损坏的看门狗不会静默失败) | | 脚本超时 | 投递错误警报 | “为空时静默”的行为是经典看门狗模式的关键:脚本可以自由地每分钟运行,但通道仅在确实需要注意时才看到消息。 ## 脚本规则 {#script-rules} 脚本必须位于 `~/.hermes/scripts/` 中。这在任务创建时和运行时都会强制执行——绝对路径、`~/` 展开和路径遍历模式(`../`)会被拒绝。该目录与 LLM 任务使用的预检查脚本门控共享。 解释器的选择取决于文件扩展名: | 扩展名 | 解释器 | |-----------|-------------| | `.sh`, `.bash` | `/bin/bash` | | 其他任何扩展名 | `sys.executable`(当前 Python) | 我们故意不遵循 `#!/...` shebang——保持解释器集明确且精简,可以减少调度器信任的攻击面。 ## 调度语法 {#schedule-syntax} 与其他所有 cron 任务相同: ```bash hermes cron create "every 5m" # interval hermes cron create "every 2h" hermes cron create "0 9 * * *" # standard cron: 9am daily hermes cron create "30m" # one-shot: run once in 30 minutes ``` 请参阅 [cron 功能参考](/docs/user-guide/features/cron) 了解完整语法。 ## 投递目标 {#delivery-targets} `--deliver` 接受网关所知的一切内容。一些常见的形式: ```bash --deliver telegram # platform home channel --deliver telegram:-1001234567890 # specific chat --deliver telegram:-1001234567890:17585 # specific Telegram forum topic --deliver discord:#ops --deliver slack:#engineering --deliver signal:+15551234567 --deliver local # just save to ~/.hermes/cron/output/ ``` 对于机器人令牌平台(Telegram、Discord、Slack、Signal、SMS、WhatsApp),在脚本运行时不需要运行中的网关——该工具使用 `~/.hermes/.env` / `~/.hermes/config.yaml` 中已有的凭据直接调用每个平台的 REST 端点。 ## 编辑与生命周期 {#editing-and-lifecycle} ```bash hermes cron list # see all jobs hermes cron pause # stop firing, keep definition hermes cron resume hermes cron edit --schedule "every 10m" # adjust cadence hermes cron edit --agent # flip to LLM mode hermes cron edit --no-agent --script … # flip back hermes cron remove # delete it ``` 所有适用于 LLM 作业的操作(暂停、恢复、手动触发、更改投递目标)也适用于无代理作业。 ## 实际示例:磁盘空间警报 {#worked-example-disk-space-alert} ```bash cat > ~/.hermes/scripts/disk-alert.sh <<'EOF' #!/usr/bin/env bash # Alert when / or /home is over 90% full. THRESHOLD=90 df -h / /home 2>/dev/null | awk -v t="$THRESHOLD" ' NR > 1 && $5+0 >= t { printf "⚠ Disk %s full on %s\n", $5, $6 } ' EOF chmod +x ~/.hermes/scripts/disk-alert.sh hermes cron create "*/15 * * * *" \ --no-agent \ --script disk-alert.sh \ --deliver telegram \ --name "disk-alert" ``` 当两个文件系统的使用率均低于 90% 时保持静默;当某个文件系统超出阈值时,每个超标的文件系统恰好触发一行输出。 ## 与其他模式的比较 {#comparison-with-other-patterns} | 方法 | 运行内容 | 何时使用 | |----------|-----------|-------------| | `cronjob --no-agent`(本页) | 按 Hermes 的计划运行你的脚本 | 不需要推理的周期性看门狗/警报/指标 | | `cronjob`(默认,LLM) | 带有可选预检查脚本的代理 | 当消息内容需要对数据进行推理时 | | OS cron + 向 [webhook 订阅](/docs/user-guide/messaging/webhooks) 发送 `curl` | 按 OS 计划运行你的脚本 | 当 Hermes 可能不健康时(即你正在监控的对象) | 对于必须在 *即使网关宕机时* 也能触发的关键系统健康看门狗,请使用操作系统级别的 cron 并通过普通的 `curl` 向 Hermes webhook 订阅(或任何外部警报端点)发送请求——这些作为独立的操作系统进程运行,不依赖于 Hermes 是否处于运行状态。当被监控的对象是外部系统时,网关内调度器是正确的选择。 ## 相关 {#related} - [使用 Cron 自动化一切](/docs/guides/automate-with-cron) — LLM 驱动的 cron 模式。 - [计划任务 (Cron) 参考](/docs/user-guide/features/cron) — 完整的调度语法、生命周期、投递路由。 - [Webhook 订阅](/docs/user-guide/messaging/webhooks) — 用于外部调度器的即发即弃 HTTP 入口点。 - [网关内部原理](/docs/developer-guide/gateway-internals) — 投递路由器内部原理。 --- ### Cron 故障排除 - URL: https://hermesagent.org.cn/docs/guides/cron-troubleshooting - Path: guides/cron-troubleshooting.md - Category: guides - Description: 诊断并修复常见的 Hermes Cron 问题 —— 作业未触发、交付失败、技能加载错误以及性能问题 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/cron-troubleshooting.md - Translated At: 2026-04-11T03:27:07.868Z - Headings: 任务未触发 | 检查 1:确认任务存在且处于激活状态 | 检查 2:确认调度表达式正确 | 检查 3:网关是否正在运行? | 检查 4:检查系统时钟和时区 | 交付失败 | 检查 1:确认交付目标正确 | 检查 2:检查 [SILENT] 的使用 | 检查 3:平台令牌权限 | 检查 4:响应包装 | 技能加载失败 | 检查 1:确认技能已安装 # Cron 故障排除 {#cron-troubleshooting} 当 Cron 任务未按预期运行时,请按顺序执行以下检查。大多数问题都属于四类之一:时间安排、交付、权限或技能加载。 --- ## 任务未触发 {#jobs-not-firing} ### 检查 1:确认任务存在且处于激活状态 {#check-1-verify-the-job-exists-and-is-active} ```bash hermes cron list ``` 查找该任务并确认其状态为 `[active]`(而非 `[paused]` 或 `[completed]`)。如果显示为 `[completed]`,可能是重复次数已耗尽——请编辑任务以重置。 ### 检查 2:确认调度表达式正确 {#check-2-confirm-the-schedule-is-correct} 格式错误的调度表达式会静默默认为一次性任务,或直接被拒绝。请测试您的表达式: | 您的表达式 | 应该解析为 | |------------|-----------| | `0 9 * * *` | 每天上午 9:00 | | `0 9 * * 1` | 每周一上午 9:00 | | `every 2h` | 从现在起每 2 小时一次 | | `30m` | 从现在起 30 分钟后 | | `2025-06-01T09:00:00` | 2025 年 6 月 1 日上午 9:00 UTC | 如果任务只触发一次后就从列表中消失,说明这是一个一次性调度(如 `30m`、`1d` 或 ISO 时间戳)——这是预期行为。 ### 检查 3:网关是否正在运行? {#check-3-is-the-gateway-running} Cron 任务由网关的后台计时器线程触发,该线程每 60 秒触发一次。常规 CLI 聊天会话**不会**自动触发 Cron 任务。 如果您期望任务自动触发,需要运行网关(`hermes gateway` 或 `hermes serve`)。对于一次性调试,您可以手动触发一次计时器:`hermes cron tick`。 ### 检查 4:检查系统时钟和时区 {#check-4-check-the-system-clock-and-timezone} 任务使用本地时区。如果您的机器时钟错误或时区与预期不符,任务将在错误的时间触发。请验证: ```bash date hermes cron list # 将 next_run 时间与本地时间进行比较 ``` --- ## 交付失败 {#delivery-failures} ### 检查 1:确认交付目标正确 {#check-1-verify-the-deliver-target-is-correct} 交付目标区分大小写,且需要正确配置对应平台。配置错误的目标会静默丢弃响应。 | 目标 | 所需配置 | |------|--------| | `telegram` | `~/.hermes/.env` 中设置 `TELEGRAM_BOT_TOKEN` | | `discord` | `~/.hermes/.env` 中设置 `DISCORD_BOT_TOKEN` | | `slack` | `~/.hermes/.env` 中设置 `SLACK_BOT_TOKEN` | | `whatsapp` | 已配置 WhatsApp 网关 | | `signal` | 已配置 Signal 网关 | | `matrix` | 已配置 Matrix homeserver | | `email` | `config.yaml` 中配置了 SMTP | | `sms` | 已配置 SMS 服务商 | | `local` | 对 `~/.hermes/cron/output/` 有写入权限 | | `origin` | 交付到创建任务的聊天中 | 其他支持的平台包括 `mattermost`、`homeassistant`、`dingtalk`、`feishu`、`wecom`、`weixin`、`bluebubbles` 和 `webhook`。您也可以使用 `platform:chat_id` 语法指定特定聊天(例如 `telegram:-1001234567890`)。 如果交付失败,任务仍会运行——只是不会发送任何内容。请通过 `hermes cron list` 检查更新后的 `last_error` 字段(如果可用)。 ### 检查 2:检查 `[SILENT]` 的使用 {#check-2-check-silent-usage} 如果您的 Cron 任务无输出,或 Agent 返回 `[SILENT]`,则交付被抑制。这是监控任务的有意行为——但请确保您的提示语没有意外抑制所有输出。 提示语中若包含“如果没有变化,请返回 [SILENT]”,也会静默吞没非空响应。请检查您的条件逻辑。 ### 检查 3:平台令牌权限 {#check-3-platform-token-permissions} 每个消息平台的机器人需要特定权限才能接收消息。如果交付静默失败: - **Telegram**:机器人必须是目标群组/频道的管理员 - **Discord**:机器人必须在目标频道有发送权限 - **Slack**:机器人必须加入工作区,并具有 `chat:write` 权限 ### 检查 4:响应包装 {#check-4-response-wrapping} 默认情况下,Cron 响应会被头部和尾部包裹(`config.yaml` 中 `cron.wrap_response: true`)。某些平台或集成可能无法良好处理此包装。如需禁用: ```yaml cron: wrap_response: false ``` --- ## 技能加载失败 {#skill-loading-failures} ### 检查 1:确认技能已安装 {#check-1-verify-skills-are-installed} ```bash hermes skills list ``` 技能必须在附加到 Cron 任务前先安装。如果缺少技能,请先使用 `hermes skills install ` 安装,或通过 CLI 中的 `/skills` 命令安装。 ### 检查 2:检查技能名称与技能文件夹名称是否一致 {#check-2-check-skill-name-vs-skill-folder-name} 技能名称区分大小写,且必须与已安装技能的文件夹名称完全匹配。如果任务中指定 `ai-funding-daily-report`,但技能文件夹名为 `ai-funding-daily-report`,请通过 `hermes skills list` 确认确切名称。 ### 检查 3:依赖交互式工具的技能 {#check-3-skills-that-require-interactive-tools} Cron 任务运行时禁用了 `cronjob`、`messaging` 和 `clarify` 工具集。这可防止递归创建 Cron 任务、直接发送消息(交付由调度器处理)以及交互式提示。如果某技能依赖这些工具集,则在 Cron 环境中无法运行。 请查阅该技能文档,确认其是否支持非交互式(无头)模式。 ### 检查 4:多技能加载顺序 {#check-4-multi-skill-ordering} 使用多个技能时,它们按顺序加载。如果技能 A 依赖技能 B 的上下文,请确保 B 先加载: ```bash /cron add "0 9 * * *" "..." --skill context-skill --skill target-skill ``` 在此示例中,`context-skill` 在 `target-skill` 之前加载。 --- ## 任务错误与失败 {#job-errors-and-failures} ### 检查 1:查看最近的任务输出 {#check-1-review-recent-job-output} 如果任务已运行但失败,您可能在以下位置看到错误上下文: 1. 作业成功交付时的聊天记录(若交付成功) 2. `~/.hermes/logs/agent.log` 中的调度器消息(或 `errors.log` 中的警告信息) 3. 通过 `hermes cron list` 命令查看作业的 `last_run` 元数据 ### 检查项 2:常见错误模式 {#check-2-common-error-patterns} **脚本报“没有这样的文件或目录”** `script` 路径必须是绝对路径(或相对于 Hermes 配置目录的相对路径)。请确认: ```bash ls ~/.hermes/scripts/your-script.py # 必须存在 hermes cron edit --script ~/.hermes/scripts/your-script.py ``` **作业执行时提示“技能未找到”** 该技能必须安装在运行调度器的机器上。若在不同机器间切换,技能不会自动同步——请使用 `hermes skills install ` 重新安装。 **作业运行但未交付任何内容** 很可能是交付目标存在问题(参见上方“交付失败”部分),或响应被静默抑制(`[SILENT]`)。 **作业卡住或超时** 调度器使用基于非活动状态的超时机制(默认 600 秒,可通过 `HERMES_CRON_TIMEOUT` 环境变量配置,设为 `0` 表示无限制)。只要 Agent 持续调用工具,其运行时间就不会受限制——计时器仅在长时间无活动后触发。对于长时间运行的任务,应使用脚本处理数据收集,仅交付最终结果。 ### 检查项 3:锁竞争 {#check-3-lock-contention} 调度器使用基于文件的锁机制,防止任务周期重叠。如果运行了两个网关实例(或 CLI 会话与网关冲突),作业可能会被延迟或跳过。 终止重复的网关进程: ```bash ps aux | grep hermes # 杀死重复的进程,只保留一个 ``` ### 检查项 4:jobs.json 的权限问题 {#check-4-permissions-on-jobsjson} 作业存储在 `~/.hermes/cron/jobs.json`。如果该文件对当前用户不可读或不可写,调度器将静默失败: ```bash ls -la ~/.hermes/cron/jobs.json chmod 600 ~/.hermes/cron/jobs.json # 您的用户应该拥有它 ``` --- ## 性能问题 {#performance-issues} ### 作业启动缓慢 {#slow-job-startup} 每个 Cron 作业都会创建一个全新的 AIAgent 会话,可能涉及提供方认证和模型加载。对于时间敏感的调度任务,建议增加缓冲时间(例如使用 `0 8 * * *` 而非 `0 9 * * *`)。 ### 重叠作业过多 {#too-many-overlapping-jobs} 调度器在每个周期内按顺序执行作业。如果多个作业在同一时间触发,它们将依次运行。建议错开调度时间(例如使用 `0 9 * * *` 和 `5 9 * * *`,而非都设为 `0 9 * * *`),以避免延迟。 ### 脚本输出过大 {#large-script-output} 输出量达到数兆字节的脚本会拖慢 Agent 运行速度,并可能触及 token 限制。应在脚本层面进行过滤或摘要处理——仅输出 Agent 推理所需的内容。 --- ## 诊断命令 {#diagnostic-commands} ```bash hermes cron list # 显示所有作业、状态、next_run 时间 hermes cron run # 下一个报价的时间表(用于测试) hermes cron edit # 修复配置问题 hermes logs # 查看最近的Hermes日志 hermes skills list # 验证已安装的 skills ``` --- ## 获取更多帮助 {#getting-more-help} 如果您已按本指南排查问题但问题仍然存在: 1. 使用 `hermes cron run ` 运行作业(将在下一个网关周期触发),并观察聊天输出中的错误信息 2. 检查 `~/.hermes/logs/agent.log` 中的调度器消息,以及 `~/.hermes/logs/errors.log` 中的警告信息 3. 在 [github.com/NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent) 提交问题,内容包括: - 作业 ID 和调度时间 - 交付目标 - 您期望的结果与实际发生的情况 - 日志中的相关错误信息 --- *有关完整的 Cron 参考文档,请参阅 [使用 Cron 自动化任何任务](/docs/guides/automate-with-cron) 和 [计划任务(Cron)](/docs/user-guide/features/cron)。* --- ### 教程:每日简报机器人 - URL: https://hermesagent.org.cn/docs/guides/daily-briefing-bot - Path: guides/daily-briefing-bot.md - Category: guides - Description: 构建一个自动化每日简报机器人,该机器人会研究主题、总结发现,并每天早上通过 Telegram 或 Discord 发送简报。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/daily-briefing-bot.md - Translated At: 2026-04-11T03:27:27.582Z - Headings: 我们将构建什么 | 前提条件 | 第一步:手动测试工作流 | 第二步:创建定时任务 | 选项 A:自然语言(在聊天中) | 选项 B:CLI 斜杠命令 | 黄金法则:自包含的提示 | 第三步:自定义简报内容 | 多主题简报 | 使用委派实现并行研究 | 仅工作日调度 | 每日两次简报 # 教程:构建每日简报机器人 {#tutorial-build-a-daily-briefing-bot} 在本教程中,你将创建一个个人简报机器人,它每天早晨自动唤醒,研究你关心的主题,总结发现内容,并将简洁的简报直接发送到你的 Telegram 或 Discord。 最终,你将拥有一个完全自动化的流程,结合了 **网络搜索**、**定时调度**、**任务委派** 和 **消息发送** —— 无需编写任何代码。 ## 我们将构建什么 {#what-were-building} 以下是整个流程: 1. **早上 8:00** —— 定时调度器触发你的任务 2. **Hermes 启动** 一个全新的 Agent 会话,加载你的提示(prompt) 3. **网络搜索** 获取你关注主题的最新资讯 4. **内容摘要** 将信息提炼为清晰的简报格式 5. **消息发送** 将简报推送到你的 Telegram 或 Discord 整个过程全自动运行。你只需在喝早咖啡时阅读你的简报即可。 ## 前提条件 {#prerequisites} 开始之前,请确保你已具备以下条件: - **已安装 Hermes Agent** —— 参见 [安装指南](/docs/getting-started/installation) - **已运行网关(Gateway)** —— 网关守护进程负责执行定时任务: ```bash hermes gateway install # Install as a user service sudo hermes gateway install --system # Linux servers: boot-time system service # or hermes gateway # Run in foreground ``` - **Firecrawl API 密钥** —— 在环境变量中设置 `FIRECRAWL_API_KEY` 以启用网络搜索 - **消息系统配置**(可选但推荐)—— [Telegram](/docs/user-guide/messaging/telegram) 或 Discord 已设置好主频道 :::tip 没有消息系统?没关系 你仍然可以使用 `deliver: "local"` 完成本教程。简报将保存至 `~/.hermes/cron/output/`,你可以随时阅读。 ::: ## 第一步:手动测试工作流 {#step-1-test-the-workflow-manually} 在自动化之前,先确保简报功能正常。启动一个聊天会话: ```bash hermes ``` 然后输入以下提示: ``` Search for the latest news about AI agents and open source LLMs. Summarize the top 3 stories in a concise briefing format with links. ``` Hermes 将执行网络搜索,阅读搜索结果,并生成类似如下内容的输出: ``` ☀️ Your AI Briefing — March 8, 2026 1. Qwen 3 Released with 235B Parameters Alibaba's latest open-weight model matches GPT-4.5 on several benchmarks while remaining fully open source. → https://qwenlm.github.io/blog/qwen3/ 2. LangChain Launches Agent Protocol Standard A new open standard for agent-to-agent communication gains adoption from 15 major frameworks in its first week. → https://blog.langchain.dev/agent-protocol/ 3. EU AI Act Enforcement Begins for General-Purpose Models The first compliance deadlines hit, with open source models receiving exemptions under the 10M parameter threshold. → https://artificialintelligenceact.eu/updates/ --- 3 stories • Sources searched: 8 • Generated by Hermes Agent ``` 如果成功,说明你已准备好进入自动化阶段。 :::tip 迭代优化输出格式 尝试不同的提示,直到获得你满意的输出效果。可以加入如“使用表情符号标题”或“每段摘要控制在两句话以内”等指令。最终确定的提示将用于定时任务。 ::: ## 第二步:创建定时任务 {#step-2-create-the-cron-job} 现在让我们将此流程设置为每天早晨自动运行。你可以通过两种方式实现。 ### 选项 A:自然语言(在聊天中) {#option-a-natural-language-in-chat} 只需告诉 Hermes 你的需求即可: ``` Every morning at 8am, search the web for the latest news about AI agents and open source LLMs. Summarize the top 3 stories in a concise briefing with links. Use a friendly, professional tone. Deliver to telegram. ``` Hermes 将使用统一的 `cronjob` 工具为你创建定时任务。 ### 选项 B:CLI 斜杠命令 {#option-b-cli-slash-command} 使用 `/cron` 命令获得更精细的控制: ``` /cron add "0 8 * * *" "Search the web for the latest news about AI agents and open source LLMs. Find at least 5 recent articles from the past 24 hours. Summarize the top 3 most important stories in a concise daily briefing format. For each story include: a clear headline, a 2-sentence summary, and the source URL. Use a friendly, professional tone. Format with emoji bullet points and end with a total story count." ``` ### 黄金法则:自包含的提示 {#the-golden-rule-self-contained-prompts} :::warning 关键概念 定时任务在 **完全全新的会话** 中运行 —— 不会保留你之前对话的记忆,也不会了解你“之前设置过什么”。你的提示必须包含 **执行任务所需的一切信息**。 ::: **糟糕的提示:** ``` Do my usual morning briefing. ``` **良好的提示:** ``` Search the web for the latest news about AI agents and open source LLMs. Find at least 5 recent articles from the past 24 hours. Summarize the top 3 most important stories in a concise daily briefing format. For each story include: a clear headline, a 2-sentence summary, and the source URL. Use a friendly, professional tone. Format with emoji bullet points. ``` 良好提示明确指定了 **搜索内容**、**文章数量**、**输出格式** 和 **语气风格**。它将 Agent 完成任务所需的所有信息整合在一句话中。 ## 第三步:自定义简报内容 {#step-3-customize-the-briefing} 一旦基础简报功能正常,你就可以开始创意发挥了。 ### 多主题简报 {#multi-topic-briefings} 在一个简报中涵盖多个领域: ``` /cron add "0 8 * * *" "Create a morning briefing covering three topics. For each topic, search the web for recent news from the past 24 hours and summarize the top 2 stories with links. Topics: 1. AI and machine learning — focus on open source models and agent frameworks 2. Cryptocurrency — focus on Bitcoin, Ethereum, and regulatory news 3. Space exploration — focus on SpaceX, NASA, and commercial space Format as a clean briefing with section headers and emoji. End with today's date and a motivational quote." ``` ### 使用委派实现并行研究 {#using-delegation-for-parallel-research} 为了加快简报生成速度,可指示 Hermes 将每个主题委派给子 Agent: ``` /cron add "0 8 * * *" "Create a morning briefing by delegating research to sub-agents. Delegate three parallel tasks: 1. Delegate: Search for the top 2 AI/ML news stories from the past 24 hours with links 2. Delegate: Search for the top 2 cryptocurrency news stories from the past 24 hours with links 3. Delegate: Search for the top 2 space exploration news stories from the past 24 hours with links Collect all results and combine them into a single clean briefing with section headers, emoji formatting, and source links. Add today's date as a header." ``` 每个子 Agent 独立并行搜索,主 Agent 随后将所有结果整合为一份精炼的简报。更多细节请参见 [委派文档](/docs/user-guide/features/delegation)。 ### 仅工作日调度 {#weekday-only-schedule} 不需要周末简报?使用仅匹配周一至周五的 cron 表达式: ``` /cron add "0 8 * * 1-5" "Search for the latest AI and tech news..." ``` ### 每日两次简报 {#twice-daily-briefings} 获取早间概览和晚间回顾: ``` /cron add "0 8 * * *" "Morning briefing: search for AI news from the past 12 hours..." /cron add "0 18 * * *" "Evening recap: search for AI news from the past 12 hours..." ``` ### 通过记忆添加个人上下文 {#adding-personal-context-with-memory} 如果你启用了 [记忆功能](/docs/user-guide/features/memory),可以存储跨会话持久化的偏好设置。但请记住 —— 定时任务在全新会话中运行,不包含对话记忆。要添加个人上下文,需直接将信息嵌入提示中: ``` /cron add "0 8 * * *" "You are creating a briefing for a senior ML engineer who cares about: PyTorch ecosystem, transformer architectures, open-weight models, and AI regulation in the EU. Skip stories about product launches or funding rounds unless they involve open source. Search for the latest news on these topics. Summarize the top 3 stories with links. Be concise and technical — this reader doesn't need basic explanations." ``` :::tip 个性化角色设定 在提示中明确说明简报是为谁准备的,能显著提升相关性。告诉 Agent 你的角色、兴趣点以及哪些内容可以跳过。 ::: ## 第四步:管理你的任务 {#step-4-manage-your-jobs} ### 列出所有已调度任务 {#list-all-scheduled-jobs} 在聊天中输入: ``` /cron list ``` 或从终端执行: ```bash hermes cron list ``` 你将看到类似如下输出: ``` ID | Name | Schedule | Next Run | Deliver ------------|-------------------|-------------|--------------------|-------- a1b2c3d4 | Morning Briefing | 0 8 * * * | 2026-03-09 08:00 | telegram e5f6g7h8 | Evening Recap | 0 18 * * * | 2026-03-08 18:00 | telegram ``` ### 删除一个任务 {#remove-a-job} 在聊天中输入: ``` /cron remove a1b2c3d4 ``` 或用自然语言提问: ``` Remove my morning briefing cron job. ``` Hermes 将使用 `cronjob(action="list")` 查找任务,并通过 `cronjob(action="remove")` 删除它。 ### 检查网关状态 {#check-gateway-status} 确保调度器正在运行: ```bash hermes cron status ``` 如果网关未运行,你的任务将无法执行。建议将其安装为后台服务以保证可靠性: ```bash hermes gateway install # 或在 Linux 服务器上 sudo hermes gateway install --system ``` ## 更进一步 {#going-further} 你已经成功构建了一个可用的每日简报机器人。以下是你可以继续探索的方向: - **[计划任务(Cron)](/docs/user-guide/features/cron)** — 有关调度格式、重复限制和交付选项的完整参考 - **[委托](/docs/user-guide/features/delegation)** — 深入探讨并行子 Agent 工作流 - **[消息平台](/docs/user-guide/messaging)** — 配置 Telegram、Discord 或其他交付目标 - **[记忆](/docs/user-guide/features/memory)** — 跨会话的持久化上下文 - **[技巧与最佳实践](/docs/guides/tips)** — 更多提示工程建议 :::tip 还能调度什么? 简报机器人模式适用于任何任务:竞争对手监控、GitHub 仓库摘要、天气预报、投资组合跟踪、服务器健康检查,甚至每日笑话。只要您能用提示描述它,就可以将其安排执行。 ::: --- ### 委托与并行工作 - URL: https://hermesagent.org.cn/docs/guides/delegation-patterns - Path: guides/delegation-patterns.md - Category: guides - Description: 何时以及如何使用子 Agent 委派 — 并行研究、代码审查和多文件工作的模式 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/delegation-patterns.md - Translated At: 2026-04-11T03:27:24.867Z - Headings: 何时进行委托 | 模式:并行研究 | 模式:代码审查 | 模式:比较备选方案 | 模式:多文件重构 | 模式:收集后分析 | 工具集选择 | 约束条件 | 使用技巧 # 委托与并行工作 {#delegation--parallel-work} Hermes 可以启动独立的子 Agent,以并行方式处理任务。每个子 Agent 都拥有自己的对话、终端会话和工具集。只有最终的总结会返回——中间的工具调用永远不会进入你的上下文窗口。 有关完整功能参考,请参阅 [子 Agent 委托](/docs/user-guide/features/delegation)。 --- ## 何时进行委托 {#when-to-delegate} **适合委托的良好候选任务:** - 需要大量推理的子任务(调试、代码审查、研究综合) - 会用中间数据填满你上下文窗口的任务 - 可并行独立执行的工作流(同时进行研究 A 和研究 B) - 需要全新上下文的任务,希望 Agent 以无偏见的方式处理 **应使用其他方式:** - 单个工具调用 → 直接使用工具 - 步骤间存在逻辑的机械式多步任务 → 使用 `execute_code` - 需要用户交互的任务 → 子 Agent 无法使用 `clarify` - 快速文件编辑 → 直接完成即可 --- ## 模式:并行研究 {#pattern-parallel-research} 同时研究三个主题,并获取结构化的总结结果: ``` Research these three topics in parallel: 1. Current state of WebAssembly outside the browser 2. RISC-V server chip adoption in 2025 3. Practical quantum computing applications Focus on recent developments and key players. ``` 幕后,Hermes 使用: ```python delegate_task(tasks=[ { "goal": "Research WebAssembly outside the browser in 2025", "context": "Focus on: runtimes (Wasmtime, Wasmer), cloud/edge use cases, WASI progress", "toolsets": ["web"] }, { "goal": "Research RISC-V server chip adoption", "context": "Focus on: server chips shipping, cloud providers adopting, software ecosystem", "toolsets": ["web"] }, { "goal": "Research practical quantum computing applications", "context": "Focus on: error correction breakthroughs, real-world use cases, key companies", "toolsets": ["web"] } ]) ``` 三个任务并发执行。每个子 Agent 独立进行网络搜索并返回摘要。父 Agent 随后将这些摘要整合为一份连贯的简报。 --- ## 模式:代码审查 {#pattern-code-review} 将安全审查任务委托给一个全新上下文的子 Agent,使其以无先入为主观念的方式处理代码: ``` Review the authentication module at src/auth/ for security issues. Check for SQL injection, JWT validation problems, password handling, and session management. Fix anything you find and run the tests. ``` 关键在于 `context` 字段——必须包含子 Agent 所需的一切信息: ```python delegate_task( goal="Review src/auth/ for security issues and fix any found", context="""Project at /home/user/webapp. Python 3.11, Flask, PyJWT, bcrypt. Auth files: src/auth/login.py, src/auth/jwt.py, src/auth/middleware.py Test command: pytest tests/auth/ -v Focus on: SQL injection, JWT validation, password hashing, session management. Fix issues found and verify tests pass.""", toolsets=["terminal", "file"] ) ``` :::warning 上下文问题 子 Agent 对你的对话**完全一无所知**。它们从零开始。如果你委托“修复我们之前讨论的 bug”,子 Agent 根本不知道你指的是哪个 bug。请始终显式传递文件路径、错误信息、项目结构和约束条件。 ::: --- ## 模式:比较备选方案 {#pattern-compare-alternatives} 并行评估同一问题的多种解决方案,然后选择最佳方案: ``` I need to add full-text search to our Django app. Evaluate three approaches in parallel: 1. PostgreSQL tsvector (built-in) 2. Elasticsearch via django-elasticsearch-dsl 3. Meilisearch via meilisearch-python For each: setup complexity, query capabilities, resource requirements, and maintenance overhead. Compare them and recommend one. ``` 每个子 Agent 独立研究一个选项。由于它们彼此隔离,不存在相互干扰——每项评估都基于自身独立的合理性。父 Agent 获取全部三个摘要后,再进行对比分析。 --- ## 模式:多文件重构 {#pattern-multi-file-refactoring} 将大型重构任务拆分为多个并行子 Agent,每个 Agent 负责代码库的不同部分: ```python delegate_task(tasks=[ { "goal": "Refactor all API endpoint handlers to use the new response format", "context": """Project at /home/user/api-server. Files: src/handlers/users.py, src/handlers/auth.py, src/handlers/billing.py Old format: return {"data": result, "status": "ok"} New format: return APIResponse(data=result, status=200).to_dict() Import: from src.responses import APIResponse Run tests after: pytest tests/handlers/ -v""", "toolsets": ["terminal", "file"] }, { "goal": "Update all client SDK methods to handle the new response format", "context": """Project at /home/user/api-server. Files: sdk/python/client.py, sdk/python/models.py Old parsing: result = response.json()["data"] New parsing: result = response.json()["data"] (same key, but add status code checking) Also update sdk/python/tests/test_client.py""", "toolsets": ["terminal", "file"] }, { "goal": "Update API documentation to reflect the new response format", "context": """Project at /home/user/api-server. Docs at: docs/api/. Format: Markdown with code examples. Update all response examples from old format to new format. Add a 'Response Format' section to docs/api/overview.md explaining the schema.""", "toolsets": ["terminal", "file"] } ]) ``` :::tip 每个子 Agent 都有自己的终端会话。它们可以在同一项目目录中工作而互不干扰——只要它们编辑的是不同文件。如果两个子 Agent 可能修改同一文件,请在并行工作完成后自行处理该文件。 ::: --- ## 模式:收集后分析 {#pattern-gather-then-analyze} 使用 `execute_code` 完成机械式数据收集,然后将推理密集型分析任务委托出去: ```python # 第 1 步:机械收集(这里的execute_code 更好——无需推理) execute_code(""" from hermes_tools import web_search, web_extract results = [] for query in ["AI funding Q1 2026", "AI startup acquisitions 2026", "AI IPOs 2026"]: r = web_search(query, limit=5) for item in r["data"]["web"]: results.append({"title": item["title"], "url": item["url"], "desc": item["description"]}) # 从最相关的 5 个内容中提取完整内容 urls = [r["url"] for r in results[:5]] content = web_extract(urls) # 保存分析步骤 import json with open("/tmp/ai-funding-data.json", "w") as f: json.dump({"search_results": results, "extracted": content["results"]}, f) print(f"Collected {len(results)} results, extracted {len(content['results'])} pages") """) # 第 2 步:大量推理分析(这里委托更好) delegate_task( goal="Analyze AI funding data and write a market report", context="""Raw data at /tmp/ai-funding-data.json contains search results and extracted web pages about AI funding, acquisitions, and IPOs in Q1 2026. Write a structured market report: key deals, trends, notable players, and outlook. Focus on deals over $100M.""", toolsets=["terminal", "file"] ) ``` 这通常是效率最高的模式:`execute_code` 以低成本处理 10+ 个连续的工具调用,然后由一个子 Agent 在干净的上下文中完成单一高成本的推理任务。 --- ## 工具集选择 {#toolset-selection} 根据子 Agent 的需求选择合适的工具集: | 任务类型 | 工具集 | 原因 | |----------|--------|------| | 网络研究 | `["web"]` | 仅使用 web_search + web_extract | | 代码工作 | `["terminal", "file"]` | 提供 shell 访问 + 文件操作 | | 全栈任务 | `["terminal", "file", "web"]` | 除消息通信外,具备全部能力 | | 只读分析 | `["file"]` | 仅能读取文件,无法执行 shell 命令 | 限制工具集可使子 Agent 保持专注,并防止意外副作用(例如研究子 Agent 意外运行 shell 命令)。 --- ## 约束条件 {#constraints} - **最多 3 个并行任务** —— 批处理最多支持 3 个并发子 Agent - **不允许嵌套** —— 子 Agent 无法调用 `delegate_task`、`clarify`、`memory`、`send_message` 或 `execute_code` - **独立终端** —— 每个子 Agent 拥有独立的终端会话,工作目录和状态相互隔离 - **无对话历史** —— 子 Agent 仅能看到你传入的 `goal` 和 `context` - **默认 50 次迭代** —— 对简单任务可将 `max_iterations` 设置得更低以节省成本 --- ## 使用技巧 {#tips} **在目标中尽量具体。** “修复 bug” 太模糊。应明确为“修复 api/handlers.py 第 47 行的 TypeError,该错误发生在 process_request() 从 parse_body() 接收 None 时”,这样子 Agent 才能获得足够的信息开展工作。 **包含文件路径。** 子 Agent 不了解你的项目结构。请始终提供相关文件的绝对路径、项目根目录以及测试命令。 **利用委托实现上下文隔离。** 有时你希望获得全新视角。委托强制你清晰地表达问题,而子 Agent 则不会受到你对话中积累的假设影响。 **检查结果。** 子 Agent 的摘要仅是摘要。如果子 Agent 说“已修复 bug 且测试通过”,请自行运行测试或查看 diff 以验证。 --- *如需完整的委托参考——包含所有参数、ACP 集成及高级配置,请参阅 [子 Agent 委托](/docs/user-guide/features/delegation)。* --- ### 教程:GitHub PR 审查代理 - URL: https://hermesagent.org.cn/docs/guides/github-pr-review-agent - Path: guides/github-pr-review-agent.md - Category: guides - Description: 构建一个自动化的 AI 代码审查器,监控你的仓库、审查拉取请求并提供反馈——全程无需人工干预 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/github-pr-review-agent.md - Translated At: 2026-05-03T17:16:01.187Z - Headings: 前提条件 | 步骤 1:验证设置 | 步骤 2:尝试手动审查 | 步骤 3:创建审查 Skill | What to Check | Output Format | Rules | 步骤 4:教它你的规范 | 步骤 5:创建自动化 Cron Job | PR Reviews — today | [repo] [number]: [title] | 其他有用的调度计划 # 教程:构建 GitHub PR 审查 Agent {#tutorial-build-a-github-pr-review-agent} **问题:** 你的团队创建 PR 的速度快于你审查的速度。PR 往往需要等待数天才能有人查看。初级开发人员因为没人有时间检查而合并了包含 bug 的代码。你不得不把早晨的时间花在追赶差异(diffs)上,而不是进行开发工作。 **解决方案:** 一个全天候监控你的仓库的 AI agent,审查每个新 PR 中的 bug、安全问题和代码质量,并发送摘要给你——这样你只需将时间花在真正需要人工判断的 PR 上。 **你将构建的内容:** ``` ┌───────────────────────────────────────────────────────────────────┐ │ │ │ Cron Timer ──▶ Hermes Agent ──▶ GitHub API ──▶ Review │ │ (every 2h) + gh CLI (PR diffs) delivery │ │ + skill (Telegram, │ │ + memory Discord, │ │ local) │ │ │ └───────────────────────────────────────────────────────────────────┘ ``` 本指南使用 **cron jobs** 按计划轮询 PR——无需服务器或公共端点。可在 NAT 和防火墙后方运行。 :::tip 想要实时审查? 如果你有可用的公共端点,请查看 [使用 Webhook 自动评论 GitHub PR](webhook-github-pr-review)——当 PR 被打开或更新时,GitHub 会立即将事件推送到 Hermes。 ::: --- ## 前提条件 {#prerequisites} - **已安装 Hermes Agent**——参见 [安装指南](/docs/getting-started/installation) - **为 cron jobs 运行 Gateway**: ```bash hermes gateway install # Install as a service # or hermes gateway # Run in foreground ``` - **已安装并认证 GitHub CLI (`gh`)**: ```bash # Install brew install gh # macOS sudo apt install gh # Ubuntu/Debian # Authenticate gh auth login ``` - **已配置消息传递**(可选)— [Telegram](/docs/user-guide/messaging/telegram) 或 [Discord](/docs/user-guide/messaging/discord) :::tip 没有消息传递?没问题 使用 `deliver: "local"` 将审查结果保存到 `~/.hermes/cron/output/`。这在配置通知之前进行测试非常有用。 ::: --- ## 步骤 1:验证设置 {#step-1-verify-the-setup} 确保 Hermes 可以访问 GitHub。启动聊天: ```bash hermes ``` 使用简单命令进行测试: ``` Run: gh pr list --repo NousResearch/hermes-agent --state open --limit 3 ``` 你应该能看到一个开放 PR 的列表。如果成功,说明已准备就绪。 --- ## 步骤 2:尝试手动审查 {#step-2-try-a-manual-review} 仍在聊天中,要求 Hermes 审查一个真实的 PR: ``` Review this pull request. Read the diff, check for bugs, security issues, and code quality. Be specific about line numbers and quote problematic code. Run: gh pr diff 3888 --repo NousResearch/hermes-agent ``` Hermes 将: 1. 执行 `gh pr diff` 以获取代码变更 2. 阅读整个 diff 3. 生成包含具体发现的结构化审查报告 如果你对质量满意,就可以将其自动化了。 --- ## 步骤 3:创建审查 Skill {#step-3-create-a-review-skill} Skill 为 Hermes 提供一致的审查指南,这些指南在会话和 cron 运行之间持久存在。如果没有 Skill,审查质量会有波动。 ```bash mkdir -p ~/.hermes/skills/code-review ``` 创建 `~/.hermes/skills/code-review/SKILL.md`: ```markdown --- name: code-review description: Review pull requests for bugs, security issues, and code quality --- # Code Review Guidelines When reviewing a pull request: ## What to Check 1. **Bugs** — Logic errors, off-by-one, null/undefined handling 2. **Security** — Injection, auth bypass, secrets in code, SSRF 3. **Performance** — N+1 queries, unbounded loops, memory leaks 4. **Style** — Naming conventions, dead code, missing error handling 5. **Tests** — Are changes tested? Do tests cover edge cases? ## Output Format For each finding: - **File:Line** — exact location - **Severity** — Critical / Warning / Suggestion - **What's wrong** — one sentence - **Fix** — how to fix it ## Rules - Be specific. Quote the problematic code. - Don't flag style nitpicks unless they affect readability. - If the PR looks good, say so. Don't invent problems. - End with: APPROVE / REQUEST_CHANGES / COMMENT ``` 验证其已加载——启动 `hermes`,你应该能在启动时的 skills 列表中看到 `code-review`。 --- ## 步骤 4:教它你的规范 {#step-4-teach-it-your-conventions} 这是让审查者真正有用的关键。启动一个会话并教导 Hermes 你团队的标准: ``` Remember: In our backend repo, we use Python with FastAPI. All endpoints must have type annotations and Pydantic models. We don't allow raw SQL — only SQLAlchemy ORM. Test files go in tests/ and must use pytest fixtures. ``` ``` Remember: In our frontend repo, we use TypeScript with React. No `any` types allowed. All components must have props interfaces. We use React Query for data fetching, never useEffect for API calls. ``` 这些记忆将永久保存——审查者将在无需每次告知的情况下执行你的规范。 --- ## 步骤 5:创建自动化 Cron Job {#step-5-create-the-automated-cron-job} 现在将所有内容连接起来。创建一个每 2 小时运行一次的 cron job: ```bash hermes cron create "0 */2 * * *" \ "Check for new open PRs and review them. Repos to monitor: - myorg/backend-api - myorg/frontend-app Steps: 1. Run: gh pr list --repo REPO --state open --limit 5 --json number,title,author,createdAt 2. For each PR created or updated in the last 4 hours: - Run: gh pr diff NUMBER --repo REPO - Review the diff using the code-review guidelines 3. Format output as: ## PR Reviews — today ### [repo] #[number]: [title] **Author:** [name] | **Verdict:** APPROVE/REQUEST_CHANGES/COMMENT [findings] If no new PRs found, say: No new PRs to review." \ --name "pr-review" \ --deliver telegram \ --skill code-review ``` 验证其已调度: ```bash hermes cron list ``` ### 其他有用的调度计划 {#other-useful-schedules} | 调度计划 | 何时运行 | |----------|------| | `0 */2 * * *` | 每 2 小时 | | `0 9,13,17 * * 1-5` | 每天三次,仅限工作日 | | `0 9 * * 1` | 每周一早晨汇总 | | `30m` | 每 30 分钟(高流量仓库) | --- ## 步骤 6:按需运行 {#step-6-run-it-on-demand} 不想等待调度?手动触发它: ```bash hermes cron run pr-review ``` 或者在聊天会话中: ``` /cron run pr-review ``` --- ## 进阶使用 {#going-further} ### 直接将审查发布到 GitHub {#post-reviews-directly-to-github} 与其发送到 Telegram,不如让 agent 直接在 PR 上评论: 将此添加到你的 cron prompt 中: ``` After reviewing, post your review: - For issues: gh pr review NUMBER --repo REPO --comment --body "YOUR_REVIEW" - For critical issues: gh pr review NUMBER --repo REPO --request-changes --body "YOUR_REVIEW" - For clean PRs: gh pr review NUMBER --repo REPO --approve --body "Looks good" ``` :::caution 确保 `gh`拥有具有 `repo` 范围的 token。审查将以 `gh` 认证的身份发布。 ::: ### 每周 PR 仪表板 {#weekly-pr-dashboard} 创建所有仓库的周一早晨概览: ```bash hermes cron create "0 9 * * 1" \ "Generate a weekly PR dashboard: - myorg/backend-api - myorg/frontend-app - myorg/infra For each repo show: 1. Open PR count and oldest PR age 2. PRs merged this week 3. Stale PRs (older than 5 days) 4. PRs with no reviewer assigned Format as a clean summary." \ --name "weekly-dashboard" \ --deliver telegram ``` ### 多仓库监控 {#multi-repo-monitoring} 通过在 prompt 中添加更多仓库来扩展规模。Agent 会按顺序处理它们——无需额外设置。 --- ## 故障排除 {#troubleshooting} ### "gh: command not found" {#gh-command-not-found} Gateway 在最小化环境中运行。确保 `gh` 在系统 PATH 中,并重启 gateway。 ### 审查过于通用 {#reviews-are-too-generic} 1. 添加 `code-review` skill(步骤 3) 2. 通过记忆教导 Hermes 你的规范(步骤 4) 3. 它对你的技术栈了解越多,审查效果越好 ### Cron job 未运行 {#cron-job-doesnt-run} ```bash hermes gateway status # Is the gateway running? hermes cron list # Is the job enabled? ``` ### 速率限制 {#rate-limits} GitHub 允许认证用户每小时发起 5,000 次 API 请求。每次 PR 审查使用约 3-5 次请求(列表 + diff + 可选评论)。即使每天审查 100 个 PR,也远低于限制。 --- ## 下一步? {#whats-next} - **[基于 Webhook 的 PR 审查](webhook-github-pr-review)** — 在 PR 打开时获得即时审查(需要公共端点) - **[每日简报 Bot](/docs/guides/daily-briefing-bot)** — 将 PR 审查与你的晨间新闻摘要结合 - **[构建插件](/docs/guides/build-a-hermes-plugin)** — 将审查逻辑封装为可共享的插件 - **[配置文件 (Profiles)](/docs/user-guide/profiles)** — 运行具有独立记忆和配置的专用审查者配置文件 - **[备用提供商 (Fallback Providers)](/docs/user-guide/features/fallback-providers)** — 确保即使某个提供商宕机,审查仍能运行 --- ### Google Gemini - URL: https://hermesagent.org.cn/docs/guides/google-gemini - Path: guides/google-gemini.md - Category: guides - Description: 将 Hermes Agent 与 Google Gemini 结合使用 — 原生 AI Studio API、API 密钥设置、OAuth 选项、工具调用、流式传输及配额指南 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/google-gemini.md - Translated At: 2026-06-16T00:44:20.865Z - Headings: 前提条件 | 快速开始 | 配置 | 原生 Gemini API | 优先使用原生端点 | OAuth 提供商 | 可用模型 | 最新别名 | 通过 Gemini API 使用 Gemma | 在会话中途切换模型 | 诊断 | 网关(消息平台) # Google Gemini {#google-gemini} Hermes Agent 支持将 Google Gemini 作为原生提供商,使用 **Google AI Studio / Gemini API**——而非 OpenAI 兼容端点。这使得 Hermes 能够将其内部 OpenAI 格式的消息和工具循环转换为 Gemini 原生的 `generateContent` API,同时保留工具调用、流式传输、多模态输入以及 Gemini 特定的响应元数据。 Hermes 还支持一个独立的 **Google Gemini (OAuth)** 提供商,该提供商使用与 Google 的 Gemini CLI 相同的 Cloud Code Assist 后端。对于风险最低的官方 API 路径,请使用 API 密钥提供商(`gemini`)。 ## 前提条件 {#prerequisites} - **Google AI Studio API 密钥** — 在 [aistudio.google.com/apikey](https://aistudio.google.com/apikey) 创建一个 - **已启用计费的 Google Cloud 项目** — 建议用于 Agent 使用。Gemini 的免费层级对于长时间运行的 Agent 会话来说太小了,因为 Hermes 可能在每个用户回合中进行多次模型调用。 - **已安装 Hermes** — 原生 Gemini 提供商不需要额外的 Python 包。 :::tip API 密钥路径 设置 `GOOGLE_API_KEY` 或 `GEMINI_API_KEY`。Hermes 会检查 `gemini` 提供商的这两个名称。 ::: ## 快速开始 {#quick-start} ```bash # Add your Gemini API key echo "GOOGLE_API_KEY=..." >> ~/.hermes/.env # Select Gemini as your provider hermes model # → Choose "More providers..." → "Google AI Studio" # → Hermes checks your key tier and shows Gemini models # → Select a model # Start chatting hermes chat ``` 如果您更喜欢直接编辑配置,请使用原生 Gemini API 基础 URL: ```yaml model: default: gemini-3-flash-preview provider: gemini base_url: https://generativelanguage.googleapis.com/v1beta ``` ## 配置 {#configuration} 运行 `hermes model` 后,您的 `~/.hermes/config.yaml` 将包含: ```yaml model: default: gemini-3-flash-preview provider: gemini base_url: https://generativelanguage.googleapis.com/v1beta ``` 并且在 `~/.hermes/.env` 中: ```bash GOOGLE_API_KEY=... ``` ### 原生 Gemini API {#native-gemini-api} 推荐的端点是: ```text https://generativelanguage.googleapis.com/v1beta ``` Hermes 检测到此端点并创建其原生 Gemini 适配器。在内部,Hermes 仍然保持 Agent 循环使用 OpenAI 格式的消息,然后将每个请求转换为 Gemini 的原生架构: - `messages[]` → Gemini `contents[]` - 系统提示词 → Gemini `systemInstruction` - 工具架构 → Gemini `functionDeclarations` - 工具结果 → Gemini `functionResponse` 部分 - 流式响应 → 适用于 Hermes 循环的 OpenAI 格式流块 :::note Gemini 3 思维签名 对于 Gemini 3 的工具使用,Hermes 会保留附加到函数调用部分的 `thoughtSignature` 值,并在下一个工具回合中重放它们。这涵盖了多步 Agent 工作流中验证关键路径的需求。 Gemini 3 还可能将思维签名附加到其他响应部分。Hermes 的原生适配器目前针对 Agent 工具循环进行了优化,因此尚未以完整的部分级保真度重放每个非工具调用的签名。 ::: ### 优先使用原生端点 {#prefer-the-native-endpoint} Google 还提供了一个 OpenAI 兼容端点: ```text https://generativelanguage.googleapis.com/v1beta/openai/ ``` 对于 Hermes Agent 会话,请优先使用上述原生 Gemini 端点。Hermes 包含一个原生 Gemini 适配器,因此它可以将多轮工具使用、工具调用结果、流式传输、多模态输入和 Gemini 响应元数据直接映射到 Gemini 的 `generateContent` API。当您特别需要 OpenAI API 兼容性时,OpenAI 兼容端点仍然很有用。 如果您之前将 `GEMINI_BASE_URL` 设置为 `/openai` URL,请将其删除或更改: ```bash GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta ``` ### OAuth 提供商 {#oauth-provider} Hermes 还有一个 `google-gemini-cli` 提供商: ```bash hermes model # → Choose "Google Gemini (OAuth)" ``` 这使用浏览器 PKCE 登录和 Cloud Code Assist 后端。这对于想要 Gemini CLI 风格 OAuth 的用户可能很有用,但 Hermes 会显示明确警告,因为 Google 可能会将第三方软件使用 Gemini CLI OAuth 客户端视为违反政策。对于生产环境或最低风险的使用,请优先使用上述 API 密钥提供商。 ## 可用模型 {#available-models} `hermes model` 选择器显示 Hermes 提供商注册表中维护的 Gemini 模型。常见选择包括: | 模型 | ID | 备注 | |-------|----|-------| | Gemini 3.1 Pro Preview | `gemini-3.1-pro-preview` | 可用时功能最强大的预览模型 | | Gemini 3 Pro Preview | `gemini-3-pro-preview` | 强大的推理和编码模型 | | Gemini 3 Flash Preview | `gemini-3-flash-preview` | 推荐的速度与能力平衡默认选项 | | Gemini 3.1 Flash Lite Preview | `gemini-3.1-flash-lite-preview` | 可用时最快/最低成本选项 | 模型可用性会随时间变化。如果模型消失或未为您的密钥启用,请再次运行 `hermes model` 并从当前列表中选择一个。 :::info 模型 ID 当 `provider: gemini` 时,请使用 Gemini 的原生模型 ID,例如 `gemini-3-flash-preview`,而不是 OpenRouter 风格的 ID,如 `google/gemini-3-flash-preview`。 ::: ### 最新别名 {#latest-aliases} Google 为 Pro 和 Flash Gemini 系列发布动态别名。当您希望 Google 自动升级模型而无需更改 Hermes 配置时,`gemini-pro-latest` 和 `gemini-flash-latest` 非常有用。 | 别名 | 当前跟踪 | 备注 | |-------|------------------|-------| | `gemini-pro-latest` | 最新 Gemini Pro 模型 | 当您希望使用 Google 当前的 Pro 默认模型时的最佳选择 | | `gemini-flash-latest` | 最新 Gemini Flash 模型 | 当您希望使用 Google 当前的 Flash 默认模型时的最佳选择 | ```yaml model: default: gemini-pro-latest provider: gemini base_url: https://generativelanguage.googleapis.com/v1beta ``` 如果您需要严格的可复现性,请优先使用明确的模型 ID,例如 `gemini-3.1-pro-preview` 或 `gemini-3-flash-preview`。 ### 通过 Gemini API 使用 Gemma {#gemma-via-the-gemini-api} Google 还通过 Gemini API 提供 Gemma 模型。Hermes 将这些模型识别为 Google 模型,但会在默认模型选择器中隐藏吞吐量极低的 Gemma 条目,以免新用户为长时间运行的代理会话意外选择评估层级的模型。 常用的评估 ID 包括: | 模型 | ID | 备注 | |-------|----|-------| | Gemma 4 31B IT | `gemma-4-31b-it` | 较大的 Gemma 模型;适用于兼容性和质量评估 | | Gemma 4 26B A4B IT | `gemma-4-26b-a4b-it` | 可用时较小的激活参数变体 | 这些模型最好被视为 Gemini API 密钥上的评估选项。Google 的 Gemma API 定价仅限免费层级,且与生产级 Gemini 模型相比,其使用上限较低,因此持续的 Hermes 代理使用通常应转向付费 Gemini 模型、自托管部署或具有适当配额的其他提供商。 要使用在选择器中隐藏的 Gemma 模型,请直接设置: ```yaml model: default: gemma-4-31b-it provider: gemini base_url: https://generativelanguage.googleapis.com/v1beta ``` ## 在会话中途切换模型 {#switching-models-mid-session} 在对话期间使用 `/model` 命令: ```text /model gemini-3-flash-preview /model gemini-flash-latest /model gemini-3-pro-preview /model gemini-pro-latest /model gemma-4-31b-it /model gemini-3.1-flash-lite-preview ``` 如果你尚未配置 Gemini,请先退出会话并运行 `hermes model`。`/model` 仅在已配置的提供商和模型之间切换;它不会收集新的 API 密钥。 ## 诊断 {#diagnostics} ```bash hermes doctor ``` doctor 检查以下内容: - `GOOGLE_API_KEY` 或 `GEMINI_API_KEY` 是否可用 - 是否存在用于 `google-gemini-cli` 的 Gemini OAuth 凭据 - 已配置的提供商凭据是否可以解析 对于 OAuth 配额使用情况,请在 Hermes 会话中运行以下命令: ```text /gquota ``` `/gquota` 适用于 `google-gemini-cli` OAuth 提供商,而不适用于 AI Studio API 密钥提供商。 ## 网关(消息平台) {#gateway-messaging-platforms} Gemini 适用于所有 Hermes 网关平台(Telegram、Discord、Slack、WhatsApp、LINE、飞书等)。将 Gemini 配置为你的提供商,然后正常启动网关: ```bash hermes gateway setup hermes gateway start ``` 网关读取 `config.yaml` 并使用相同的 Gemini 提供商配置。 ## 故障排除 {#troubleshooting} ### "Gemini native client requires an API key"(Gemini 原生客户端需要 API 密钥) {#gemini-native-client-requires-an-api-key} Hermes 找不到可用的 API 密钥。将以下其中之一添加到 `~/.hermes/.env`: ```bash GOOGLE_API_KEY=... # or GEMINI_API_KEY=... ``` 然后再次运行 `hermes model`。 ### "This Google API key is on the free tier"(此 Google API 密钥处于免费层级) {#this-google-api-key-is-on-the-free-tier} Hermes 在设置过程中会探测 Gemini API 密钥。由于工具使用、重试、压缩和辅助任务可能需要多次模型调用,免费层级的配额可能在几次代理交互后耗尽。 在与你的密钥关联的 Google Cloud 项目上启用计费,必要时重新生成密钥,然后运行: ```bash hermes model ``` ### "404 model not found"(404 模型未找到) {#404-model-not-found} 所选模型对你的账户、区域或密钥不可用。再次运行 `hermes model` 并从当前列表中选择另一个 Gemini 模型。 ### Gemma 模型未显示在 `hermes model` 中 {#gemma-model-is-not-shown-in-hermes-model} Hermes 默认可能会在选择器中隐藏低吞吐量的 Gemma 模型。如果你有意要评估其中一个,请在 `~/.hermes/config.yaml` 中直接设置模型 ID。 ### Gemma 出现 "429 quota exceeded"(429 超出配额) {#429-quota-exceeded-on-gemma} 通过 Gemini API 提供的 Gemma 模型适用于评估,但其 Gemini API 免费层级的上限较低。将它们用于兼容性测试,然后切换到付费 Gemini 模型或其他提供商以进行持续的代理会话。 ### 已配置 OpenAI 兼容端点 {#openai-compatible-endpoint-is-configured} 检查 `~/.hermes/.env` 中是否有: ```bash GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta/openai/ ``` 将其更改为原生端点或移除覆盖: ```bash GEMINI_BASE_URL=https://generativelanguage.googleapis.com/v1beta ``` ### OAuth 登录警告 {#oauth-login-warning} `google-gemini-cli` 提供商使用 Gemini CLI / Cloud Code Assist OAuth 流程。Hermes 在启动之前会发出警告,因为这不同于官方的 AI Studio API 密钥路径。对于官方 API 密钥集成,请将 `provider` 设置为 `gemini` 并使用 `GOOGLE_API_KEY`。 ### 工具调用因架构错误而失败 {#tool-calling-fails-with-schema-errors} 升级 Hermes 并重新运行 `hermes model`。原生 Gemini 适配器会对工具架构进行清理,以符合 Gemini 更严格的函数声明格式;旧版本构建或自定义端点可能不具备此功能。 ## 相关资源 {#related} - [AI 提供商](/docs/integrations/providers) - [配置](/docs/user-guide/configuration) - [回退提供商](/docs/user-guide/features/fallback-providers) - [AWS Bedrock](/docs/guides/aws-bedrock) — 使用 AWS 凭据的原生云提供商集成 --- ### 在 Mac 上运行本地 LLM - URL: https://hermesagent.org.cn/docs/guides/local-llm-on-mac - Path: guides/local-llm-on-mac.md - Category: guides - Description: 在 macOS 上使用 llama.cpp 或 MLX 搭建本地 OpenAI 兼容的 LLM 服务器,包括模型选择、内存优化以及在 Apple Silicon 上的真实性能基准测试。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/local-llm-on-mac.md - Translated At: 2026-04-11T03:28:22.640Z - Headings: 选择模型 | 选项 A:llama.cpp | 安装 | 下载模型 | 启动服务器 | 内存受限系统的优化策略 | 测试 | 获取模型名称 | 选项 B:通过 omlx 使用 MLX | 安装 | 下载模型 | 启动服务器 # 在 Mac 上运行本地 LLM {#run-local-llms-on-mac} 本指南将引导您在 macOS 上使用兼容 OpenAI 的 API 运行本地 LLM 服务器。您将获得完全的隐私保护、零 API 成本,并在 Apple Silicon 芯片上实现令人惊讶的出色性能。 我们涵盖两种后端: | 后端 | 安装方式 | 优势 | 格式 | |------|--------|------|------| | **llama.cpp** | `brew install llama.cpp` | 首个 token 生成速度最快,量化 KV 缓存可降低内存占用 | GGUF | | **omlx** | [omlx.ai](https://omlx.ai) | 最快的 token 生成速度,原生 Metal 优化 | MLX (safetensors) | 两者均提供兼容 OpenAI 的 `/v1/chat/completions` 端点。Hermes 可与任一后端配合使用——只需将其指向 `http://localhost:8080` 或 `http://localhost:8000` 即可。 :::info 仅限 Apple Silicon 本指南针对搭载 Apple Silicon(M1 及更新型号)的 Mac。Intel Mac 可使用 llama.cpp,但无法获得 GPU 加速——性能将显著降低。 ::: --- ## 选择模型 {#choosing-a-model} 开始使用时,我们推荐 **Qwen3.5-9B** —— 这是一个强大的推理模型,经过量化后可在 8GB 及以上统一内存中舒适运行。 | 变体 | 磁盘占用大小 | 内存需求(128K 上下文) | 后端 | |------|--------------|--------------------------|------| | Qwen3.5-9B-Q4_K_M (GGUF) | 5.3 GB | ~10 GB(含量化 KV 缓存) | llama.cpp | | Qwen3.5-9B-mlx-lm-mxfp4 (MLX) | ~5 GB | ~12 GB | omlx | **内存使用经验法则:** 模型大小 + KV 缓存。一个 9B 的 Q4 模型约为 5 GB。在 128K 上下文且 Q4 量化的情况下,KV 缓存增加约 4–5 GB。若使用默认的 f16 KV 缓存,内存需求将飙升至约 16 GB。llama.cpp 中的量化 KV 缓存标志是内存受限系统的关键优化手段。 对于更大模型(27B、35B),您需要 32 GB 及以上统一内存。9B 模型是 8–16 GB 设备的最佳选择。 --- ## 选项 A:llama.cpp {#option-a-llamacpp} llama.cpp 是最通用的本地 LLM 运行时。在 macOS 上,它可原生使用 Metal 实现 GPU 加速。 ### 安装 {#install} ```bash brew install llama.cpp ``` 这将全局安装 `llama-server` 命令。 ### 下载模型 {#download-the-model} 您需要一个 GGUF 格式的模型。最简单的来源是通过 `huggingface-cli` 从 Hugging Face 获取: ```bash brew install huggingface-cli ``` 然后下载: ```bash huggingface-cli download unsloth/Qwen3.5-9B-GGUF Qwen3.5-9B-Q4_K_M.gguf --local-dir ~/models ``` :::tip 受限模型 Hugging Face 上的一些模型需要身份验证。如果遇到 401 或 404 错误,请先运行 `huggingface-cli login`。 ::: ### 启动服务器 {#start-the-server} ```bash llama-server -m ~/models/Qwen3.5-9B-Q4_K_M.gguf \ -ngl 99 \ -c 131072 \ -np 1 \ -fa on \ --cache-type-k q4_0 \ --cache-type-v q4_0 \ --host 0.0.0.0 ``` 以下是各标志的含义: | 标志 | 用途 | |------|------| | `-ngl 99` | 将所有层卸载到 GPU(Metal)。使用高数值以确保无任何内容留在 CPU 上。 | | `-c 131072` | 上下文窗口大小(128K tokens)。内存不足时可减小此值。 | | `-np 1` | 并行槽位数量。单用户使用时保持为 1——更多槽位会分割您的内存预算。 | | `-fa on` | 启用 Flash Attention。可减少内存占用并加快长上下文推理速度。 | | `--cache-type-k q4_0` | 将键缓存量化为 4 位。**这是节省内存的关键。** | | `--cache-type-v q4_0` | 将值缓存量化为 4 位。与上一项结合使用,相比 f16 可将 KV 缓存内存减少约 75%。 | | `--host 0.0.0.0` | 监听所有网络接口。如无需网络访问,可使用 `127.0.0.1`。 | 当您看到以下输出时,服务器即已准备就绪: ``` main: server is listening on http://0.0.0.0:8080 srv update_slots: all slots are idle ``` ### 内存受限系统的优化策略 {#memory-optimization-for-constrained-systems} `--cache-type-k q4_0 --cache-type-v q4_0` 标志是内存受限系统最重要的优化手段。在 128K 上下文下的效果如下: | KV 缓存类型 | KV 缓存内存(128K 上下文,9B 模型) | |-------------|--------------------------------------| | f16(默认) | ~16 GB | | q8_0 | ~8 GB | | **q4_0** | **~4 GB** | 在 8 GB 的 Mac 上,使用 `q4_0` KV 缓存并将上下文减小至 `-c 32768`(32K)。在 16 GB 上,可轻松支持 128K 上下文。在 32 GB 及以上设备上,可运行更大模型或多个并行槽位。 如果仍出现内存不足,优先减小上下文大小(`-c`),然后尝试更小的量化级别(如 Q3_K_M 而非 Q4_K_M)。 ### 测试 {#test-it} ```bash curl -s http://localhost:8080/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen3.5-9B-Q4_K_M.gguf", "messages": [{"role": "user", "content": "Hello!"}], "max_tokens": 50 }' | jq .choices[0].message.content ``` ### 获取模型名称 {#get-the-model-name} 若忘记模型名称,可通过查询模型端点获取: ```bash curl -s http://localhost:8080/v1/models | jq '.data[].id' ``` --- ## 选项 B:通过 omlx 使用 MLX {#option-b-mlx-via-omlx} [omlx](https://omlx.ai) 是一款专为 macOS 设计的应用程序,用于管理并提供 MLX 模型服务。MLX 是 Apple 自研的机器学习框架,专为 Apple Silicon 的统一内存架构进行了优化。 ### 安装 {#install-1} 从 [omlx.ai](https://omlx.ai) 下载并安装。该应用提供模型管理的图形界面和内置服务器。 ### 下载模型 {#download-the-model-1} 使用 omlx 应用程序浏览并下载模型。搜索 `Qwen3.5-9B-mlx-lm-mxfp4` 并下载。模型将本地存储(通常位于 `~/.omlx/models/` 目录下)。 ### 启动服务器 {#start-the-server-1} omlx 默认在 `http://127.0.0.1:8000` 提供模型服务。可通过应用界面启动服务,或使用可用的 CLI 工具。 ### 测试 {#test-it-1} ```bash curl -s http://127.0.0.1:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen3.5-9B-mlx-lm-mxfp4", "messages": [{"role": "user", "content": "Hello!"}], "max_tokens": 50 }' | jq .choices[0].message.content ``` ### 列出可用模型 {#list-available-models} omlx 可同时服务多个模型: ```bash curl -s http://127.0.0.1:8000/v1/models | jq '.data[].id' ``` --- ## 基准测试:llama.cpp 与 MLX {#benchmarks-llamacpp-vs-mlx} 在相同机器(Apple M5 Max,128 GB 统一内存)上对两个后端进行了测试,运行相同的模型(Qwen3.5-9B),量化级别相近(GGUF 使用 Q4_K_M,MLX 使用 mxfp4)。共使用五个不同提示,每种情况运行三次,后端依次测试以避免资源争用。 ### 结果 {#results} | 指标 | llama.cpp (Q4_K_M) | MLX (mxfp4) | 胜出方 | |------|-------------------|-------------|--------| | **TTFT(平均)** | **67 ms** | 289 ms | llama.cpp(快 4.3 倍) | | **TTFT(p50)** | **66 ms** | 286 ms | llama.cpp(快 4.3 倍) | | **生成速度(平均)** | 70 tok/s | **96 tok/s** | MLX(快 37%) | | **生成速度(p50)** | 70 tok/s | **96 tok/s** | MLX(快 37%) | | **总耗时(512 tokens)** | 7.3s | **5.5s** | MLX(快 25%) | ### 这意味着什么 {#what-this-means} - **llama.cpp** 在提示处理方面表现卓越——其 flash attention + 量化 KV 缓存流水线可在约 66ms 内输出第一个 token。如果你正在构建对感知响应速度敏感的交互式应用(如聊天机器人、自动补全),这将带来显著优势。 - **MLX** 在开始生成后,token 生成速度比 llama.cpp 快约 37%。对于批量任务、长文本生成,或任何更关注总完成时间而非初始延迟的场景,MLX 能更快完成任务。 - 两个后端均表现出**极高的稳定性**——各次运行间的差异可忽略不计。你可以完全信赖这些数据。 ### 你应该选择哪一个? {#which-one-should-you-pick} | 使用场景 | 推荐方案 | |----------|----------| | 交互式聊天、低延迟工具 | llama.cpp | | 长文本生成、批量处理 | MLX(omlx) | | 内存受限(8-16 GB) | llama.cpp(量化 KV 缓存表现无与伦比) | | 同时服务多个模型 | omlx(内置多模型支持) | | 最大兼容性(支持 Linux) | llama.cpp | --- ## 连接到 Hermes {#connect-to-hermes} 本地服务器启动后: ```bash hermes model ``` 选择 **自定义端点** 并按提示操作。系统将要求输入基础 URL 和模型名称——请使用你在上文设置的后端对应的值。 --- ## 超时设置 {#timeouts} Hermes 会自动检测本地端点(localhost、局域网 IP),并自动放宽流式传输超时时间。大多数情况下无需任何配置。 如果你仍然遇到超时错误(例如在慢速硬件上处理非常大的上下文),可以手动覆盖流式读取超时时间: ```bash # 在您的 `.env` 中 — 从默认值 120 秒提高到 30 分钟 HERMES_STREAM_READ_TIMEOUT=1800 ``` | 超时类型 | 默认值 | 本地自动调整 | 环境变量覆盖 | |----------|--------|--------------|--------------| | 流式读取(socket 层) | 120s | 提升至 1800s | `HERMES_STREAM_READ_TIMEOUT` | | 旧流检测 | 180s | 完全禁用 | `HERMES_STREAM_STALE_TIMEOUT` | | API 调用(非流式) | 1800s | 无需更改 | `HERMES_API_TIMEOUT` | 最可能引发问题的是**流式读取超时**——这是接收下一数据块的 socket 层截止时间。在大上下文预填充阶段,本地模型可能在处理提示时数分钟内无输出。自动检测机制会透明地处理这一情况。 --- ### 在本地使用 Ollama 运行 Hermes — 零 API 成本 - URL: https://hermesagent.org.cn/docs/guides/local-ollama-setup - Path: guides/local-ollama-setup.md - Category: guides - Description: 在本地机器上完全使用 Ollama 和开放权重模型(如 Gemma 4)运行 Hermes Agent 的分步指南,无需云 API 密钥或付费订阅 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/local-ollama-setup.md - Translated At: 2026-06-16T00:44:38.679Z - Headings: 问题所在 | 本指南解决的问题 | 所需条件 | 步骤 1:安装 Ollama | 步骤 2:拉取模型 | 步骤 3:配置 Hermes | 步骤 4:开始使用 Hermes | 步骤 5:为任务选择合适的模型 | 步骤 6:优化速度 | 增加 Ollama 的上下文窗口 | 保持模型加载状态 | 使用 GPU 卸载(如果可用) # 在本地使用 Ollama 运行 Hermes — 零 API 成本 {#run-hermes-locally-with-ollama-—-zero-api-cost} ## 问题所在 {#the-problem} 云端大语言模型(LLM)API 按 Token 收费。一次高强度的编码会话可能花费 5–20 美元。对于个人项目、学习或涉及隐私的工作来说,这笔费用会不断累积——而且你还将每一次对话都发送给了第三方。 ## 本指南解决的问题 {#what-this-guide-solves} 你将设置完全在自有硬件上运行的 Hermes Agent,并使用 [Ollama](https://ollama.com) 作为模型后端。无需 API 密钥,无需订阅,数据不会离开你的机器。配置完成后,Hermes 的工作方式与使用 OpenRouter 或 Anthropic 时完全相同——终端命令、文件编辑、网页浏览、任务委托——但模型是在本地运行的。 读完本指南后,你将拥有: - 由 Ollama 提供服务的一个或多个开源权重模型 - 连接到 Ollama 自定义端点的 Hermes - 一个能够编辑文件、运行命令和浏览网页的可用本地代理 - 可选:一个完全由自有硬件驱动的 Telegram/Discord 机器人 ## 所需条件 {#what-you-need} | 组件 | 最低配置 | 推荐配置 | |-----------|---------|-------------| | **内存 (RAM)** | 8 GB(适用于 3B 模型) | 32+ GB(适用于 27B+ 模型) | | **存储** | 5 GB 可用空间 | 30+ GB(适用于多个模型) | | **CPU** | 4 核 | 8+ 核(AMD EPYC, Ryzen, Intel Xeon) | | **GPU** | 非必需 | 配备 8+ GB 显存的 NVIDIA GPU 可显著加速 | :::tip 仅 CPU 也可运行,但响应速度较慢 Ollama 可以在仅配备 CPU 的服务器上运行。在现代 8 核 CPU 上运行 9B 模型的速度约为 ~10 tokens/秒。在 CPU 上运行 31B 模型速度较慢(~2–5 tokens/秒)——每次响应需要 30–120 秒,但可以正常工作。GPU 可以大幅改善这一情况。对于仅使用 CPU 的环境,请通过环境变量增加 API 超时时间(这不是 `config.yaml` 中的配置键): ```bash # ~/.hermes/.env HERMES_API_TIMEOUT=1800 # 30 minutes — generous for slow local models ``` ::: ## 步骤 1:安装 Ollama {#step-1-install-ollama} ```bash curl -fsSL https://ollama.com/install.sh | sh ``` 验证其是否正在运行: ```bash ollama --version curl http://localhost:11434/api/tags # Should return {"models":[]} ``` ## 步骤 2:拉取模型 {#step-2-pull-a-model} 根据你的硬件选择模型: | 模型 | 磁盘占用大小 | 所需内存 | 工具调用支持 | 最佳用途 | |-------|-------------|------------|:------------:|----------| | `gemma4:31b` | ~20 GB | 24+ GB | 是 | 最佳质量——强大的工具使用和推理能力 | | `gemma2:27b` | ~16 GB | 20+ GB | 否 | 对话任务,无工具使用 | | `gemma2:9b` | ~5 GB | 8+ GB | 否 | 快速聊天、问答——无法调用工具 | | `llama3.2:3b` | ~2 GB | 4+ GB | 否 | 仅用于轻量级快速回答 | :::warning 工具调用至关重要 Hermes 是一个**代理型**助手——它通过工具调用来编辑文件、运行命令和浏览网页。不支持工具调用的模型只能进行聊天;它们无法执行操作。为了获得完整的 Hermes 体验,请使用支持工具的模型(如 `gemma4:31b`)。 ::: 拉取你选择的模型: ```bash ollama pull gemma4:31b ``` :::info 多个模型 你可以拉取多个模型,并在 Hermes 中使用 `/model` 命令在它们之间切换。Ollama 会根据需求将活动模型加载到内存中,并自动卸载空闲模型。 ::: 验证模型是否正常工作: ```bash curl http://localhost:11434/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "gemma4:31b", "messages": [{"role": "user", "content": "Say hello"}], "max_tokens": 50 }' ``` 你应该看到包含模型回复的 JSON 响应。 ## 步骤 3:配置 Hermes {#step-3-configure-hermes} 运行 Hermes 设置向导: ```bash hermes setup ``` 当提示选择提供商时,选择 **Custom Endpoint(自定义端点)** 并输入: - **Base URL(基础 URL):** `http://localhost:11434/v1` - **API Key(API 密钥):** 留空或输入 `no-key`(Ollama 不需要密钥) - **Model(模型):** `gemma4:31b`(或你拉取的任何模型) 或者,直接编辑 `~/.hermes/config.yaml`: ```yaml model: default: "gemma4:31b" provider: "custom" base_url: "http://localhost:11434/v1" ``` ## 步骤 4:开始使用 Hermes {#step-4-start-using-hermes} ```bash hermes ``` 就是这样。你现在正在运行一个完全本地的代理。试一试: ``` You: List all Python files in this directory and count the lines of code in each You: Read the README.md and summarize what this project does You: Create a Python script that fetches the weather for Ho Chi Minh City ``` Hermes 将使用终端工具、文件操作和你的本地模型——无需调用云端服务。 ## 步骤 5:为任务选择合适的模型 {#step-5-pick-the-right-model-for-your-task} 并非每个任务都需要最大的模型。以下是一份实用指南: | 任务 | 推荐模型 | 原因 | |------|-------------------|-----| | 文件编辑、代码、终端命令 | `gemma4:31b` | 唯一具有可靠工具调用支持的模型 | | 快速问答(无需工具使用) | `gemma2:9b` | 对话任务的响应速度快 | | 轻量级聊天 | `llama3.2:3b` | 速度最快,但功能非常有限 | :::note 对于完整的代理工作(编辑文件、运行命令、浏览网页),`gemma4:31b` 目前是具有工具调用支持的最佳本地选项。查看 [Ollama 的模型库](https://ollama.com/library) 以获取更新模型——工具调用支持正在迅速扩展。 ::: 在会话期间随时切换模型: ``` /model gemma2:9b ``` ## 步骤 6:优化速度 {#step-6-optimize-for-speed} ### 增加 Ollama 的上下文窗口 {#increase-ollamas-context-window} 默认情况下,Ollama 使用 2048 个 Token 的上下文。Hermes 在进行带有工具的代理工作时至少需要 64,000 个 Token: ```bash # Create a Modelfile that extends context cat > /tmp/Modelfile << 'EOF' FROM gemma4:31b PARAMETER num_ctx 64000 EOF ollama create gemma4-64k -f /tmp/Modelfile ``` 然后更新你的 Hermes 配置,将模型名称设置为 `gemma4-64k`。 ### 保持模型加载状态 {#keep-the-model-loaded} 默认情况下,Ollama 会在闲置 5 分钟后卸载模型。对于持久的网关机器人,请保持其加载状态: ```bash # Set keep-alive to 24 hours curl http://localhost:11434/api/generate \ -d '{"model": "gemma4:31b", "keep_alive": "24h"}' ``` 或者在 Ollama 的环境变量中进行全局设置: ```bash # /etc/systemd/system/ollama.service.d/override.conf [Service] Environment="OLLAMA_KEEP_ALIVE=24h" ``` ### 使用 GPU 卸载(如果可用) {#use-gpu-offloading-if-available} 如果你拥有 NVIDIA GPU,Ollama 会自动将层卸载到 GPU 上。可以通过以下命令检查: ```bash ollama ps # Shows which model is loaded and how many GPU layers ``` 对于在 12 GB GPU 上运行的 31B 模型,你将实现部分卸载(约 40 层在 GPU 上,其余在 CPU 上),这仍然能带来显著的速度提升。 ## 第 7 步:作为网关机器人运行(可选) {#step-7-run-as-a-gateway-bot-optional} 一旦 Hermes 在 CLI 中本地正常工作,你可以将其暴露为 Telegram 或 Discord 机器人——仍然完全在你的硬件上运行。 ### Telegram {#telegram} 1. 通过 [@BotFather](https://t.me/BotFather) 创建机器人并获取 token 2. 添加到你的 `~/.hermes/config.yaml`: ```yaml model: default: "gemma4:31b" provider: "custom" base_url: "http://localhost:11434/v1" platforms: telegram: enabled: true token: "YOUR_TELEGRAM_BOT_TOKEN" ``` 3. 启动网关: ```bash hermes gateway ``` 现在在 Telegram 上给你的机器人发送消息——它将使用你的本地模型进行回复。 ### Discord {#discord} 1. 在 [discord.com/developers](https://discord.com/developers/applications) 创建 Discord 应用 2. 添加到配置中: ```yaml platforms: discord: enabled: true token: "YOUR_DISCORD_BOT_TOKEN" ``` 3. 启动:`hermes gateway` ## 第 8 步:设置回退机制(可选) {#step-8-set-up-fallbacks-optional} 本地模型在处理复杂任务时可能会遇到困难。设置一个云回退机制,仅当本地模型失败时才激活: ```yaml model: default: "gemma4:31b" provider: "custom" base_url: "http://localhost:11434/v1" fallback_providers: - provider: openrouter model: anthropic/claude-sonnet-4 ``` 这样,你 90% 的使用量是免费的(本地),只有困难的任务才会调用付费 API。 ## 故障排除 {#troubleshooting} ### 启动时出现 "Connection refused" {#connection-refused-on-startup} Ollama 未运行。启动它: ```bash sudo systemctl start ollama # or ollama serve ``` ### 响应缓慢 {#slow-responses} - **检查模型大小与内存:** 如果你的模型需要的内存超过可用内存,它会交换到磁盘。使用更小的模型或增加内存。 - **检查 `ollama ps`:** 如果没有 GPU 层被卸载,响应将受限于 CPU。这对于仅 CPU 的服务器来说是正常的。 - **减少上下文:** 大型对话会减慢推理速度。定期使用 `/compress`,或在配置中设置较低的压缩阈值。 ### 模型不遵循工具调用 {#model-doesnt-follow-tool-calls} 较小的模型(3B、7B)有时会忽略工具调用指令,生成纯文本而不是结构化的函数调用。解决方案: - **使用更大的模型** — `gemma4:31b` 或 `gemma2:27b` 处理工具调用的效果远好于 3B/7B 模型。 - **Hermes 具有自动修复功能** — 它能检测格式错误的工具调用并尝试自动修复。 - **设置回退机制** — 如果本地模型失败 3 次,Hermes 将回退到云提供商。 ### 上下文窗口错误 {#context-window-errors} 默认的 Ollama 上下文(2048 个 token)对于代理工作来说太小。请参阅 [第 6 步](#step-6-optimize-for-speed) 以增加它。 ## 成本对比 {#cost-comparison} 以下是基于典型编码会话(约 100K token 输入,约 20K token 输出)本地运行相比云 API 所节省的费用: | 提供商 | 每次会话成本 | 每月(每日使用) | |----------|-----------------|---------------------| | Anthropic Claude Sonnet | ~$0.80 | ~$24 | | OpenRouter (GPT-4o) | ~$0.60 | ~$18 | | **Ollama(本地)** | **$0.00** | **$0.00** | 你唯一的成本是电费——根据硬件不同,每次会话大约 $0.01–0.05。 ## 本地运行效果良好的场景 {#what-works-well-locally} - **文件编辑和代码生成** — 9B+ 模型能很好地处理此任务 - **终端命令** — Hermes 封装命令,运行它,无论模型如何都能读取输出 - **网页浏览** — 浏览器工具负责获取内容;模型仅解释结果 - **Cron 作业和计划任务** — 与云设置的工作方式相同 - **多平台网关** — Telegram、Discord、Slack 均可与本地模型配合使用 ## 云模型更优的场景 {#whats-better-with-cloud-models} - **非常复杂的多步推理** — 70B+ 或像 Claude Opus 这样的云模型明显更好 - **长上下文窗口** — 云模型提供 100K–1M token;除非你进行配置,否则本地运行时通常默认低于 Hermes 的 64K 最低要求 - **大响应的速度** — 对于长生成,云推理比仅 CPU 的本地推理更快 最佳策略:日常任务使用本地模型,为困难任务设置云回退机制。 --- ### 注册 Microsoft Graph 应用程序 - URL: https://hermesagent.org.cn/docs/guides/microsoft-graph-app-registration - Path: guides/microsoft-graph-app-registration.md - Category: guides - Description: Azure 门户操作指南:创建支持 Teams 会议管道的应用注册 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/microsoft-graph-app-registration.md - Translated At: 2026-06-16T00:44:34.599Z - Headings: 先决条件 | 步骤 1:创建应用程序注册 | 步骤 2:创建客户端密码 | 步骤 3:授予 Graph API 权限 | 基于转录的摘要所需 | 录音回退所需(当转录不可用时) | 出站摘要交付所需(仅限 Graph 模式) | 不推荐 | 步骤 4:(推荐)使用应用程序访问策略限定应用程序范围 | 步骤 5:将凭据写入你的 Env 文件 | 步骤 6:验证令牌流程 | 轮换客户端密钥 # 注册 Microsoft Graph 应用程序 {#register-a-microsoft-graph-application} Teams 会议管道使用**仅应用**(守护程序)身份验证从 Microsoft Graph 读取会议转录、录音和相关工件——无需用户登录,也无需针对每个会议进行交互式同意。这需要在 Azure AD 中注册一个具有管理员同意的应用程序权限的应用程序。 本指南将逐步介绍: 1. 创建应用程序注册 2. 创建客户端密码 3. 授予管道所需的 Graph API 权限 4. 对这些权限进行管理员同意 5. (可选)使用应用程序访问策略将应用程序范围限定为特定用户 你需要**租户管理员权限**(或由管理员代表你授予同意)才能完成此操作。请收藏你收集的值——最后需要将它们放入 `~/.hermes/.env` 中。 ## 先决条件 {#prerequisites} - 一个 Microsoft 365 租户,具有 Teams Premium 或能生成会议转录和录音的 Teams 许可证 - 对 [entra.microsoft.com](https://entra.microsoft.com) 上的 Azure 门户的管理员访问权限 - 一个可公开访问的 HTTPS 端点,用于接收 Graph 更改通知(稍后在 webhook 监听器步骤中设置) ## 步骤 1:创建应用程序注册 {#step-1-create-the-app-registration} 1. 以租户管理员身份登录 [entra.microsoft.com](https://entra.microsoft.com)。 2. 导航到 **Identity → Applications → App registrations**(标识 → 应用程序 → 应用注册)。 3. 点击 **New registration**(新注册)。 4. 填写: - **Name**(名称):`Hermes Teams Meeting Pipeline`(或任何你能识别的名称)。 - **Supported account types**(支持的账户类型):*Accounts in this organizational directory only (Single tenant)*(仅此组织目录中的账户(单租户))。 - **Redirect URI**(重定向 URI):留空——仅应用身份验证不需要此项。 5. 点击 **Register**(注册)。 你将进入应用程序的概述页面。复制两个值: - **Application (client) ID**(应用程序(客户端)ID)→ `MSGRAPH_CLIENT_ID` - **Directory (tenant) ID**(目录(租户)ID)→ `MSGRAPH_TENANT_ID` ## 步骤 2:创建客户端密码 {#step-2-create-a-client-secret} 1. 在左侧导航栏中,打开 **Certificates & secrets**(证书和密码)。 2. 点击 **New client secret**(新客户端密码)。 3. **Description**(描述):`hermes-graph-secret`。**Expires**(过期时间):选择一个符合你的轮换策略的值(通常为 6-24 个月)。 4. 点击 **Add**(添加)。 5. 立即复制 **Value**(值)列——它仅显示一次。该值即为 `MSGRAPH_CLIENT_SECRET`。 > **Secret ID**(密码 ID)列不是密码。你需要的是 **Value**(值)列。 ## 步骤 3:授予 Graph API 权限 {#step-3-grant-graph-api-permissions} 管道使用最小可行的应用程序权限集。仅添加你需要的内容;每增加一个权限都会扩大应用程序可以在整个租户中读取的范围。 1. 在左侧导航栏中,打开 **API permissions**(API 权限)。 2. 点击 **Add a permission**(添加权限)→ **Microsoft Graph** → **Application permissions**(应用程序权限)。 3. 从下表中添加与你想让管道执行的操作相匹配的权限。 4. 添加后,点击 **Grant admin consent for ``**(为 `<你的租户>` 授予管理员同意)。状态列应为每个权限显示绿色对勾。 ### 基于转录的摘要所需 {#required-for-transcript-first-summaries} | 权限 | 允许应用程序执行的操作 | |------------|--------------------------| | `OnlineMeetings.Read.All` | 读取 Teams 在线会议元数据(主题、参与者、加入 URL)。 | | `OnlineMeetingTranscript.Read.All` | 读取由 Teams 生成的会议转录。 | ### 录音回退所需(当转录不可用时) {#required-for-recording-fallback-when-a-transcript-is-unavailable} | 权限 | 允许应用程序执行的操作 | |------------|--------------------------| | `OnlineMeetingRecording.Read.All` | 下载 Teams 会议录音以进行离线 STT 处理。 | | `CallRecords.Read.All` | 当只知道加入 URL 时,从呼叫记录中解析会议。 | ### 出站摘要交付所需(仅限 Graph 模式) {#required-for-outbound-summary-delivery-graph-mode-only} 如果 `platforms.teams.extra.delivery_mode` 为 `graph`,管道会通过 Graph API 将摘要发布到 Teams 频道或聊天中。如果你使用 `incoming_webhook` 交付模式,则跳过这些权限。 | 权限 | 允许应用程序执行的操作 | |------------|--------------------------| | `ChannelMessage.Send` | 代表应用程序向 Teams 频道发布消息。 | | `Chat.ReadWrite.All` | 向一对一和群聊发布消息(仅当你将 `chat_id` 设置为交付目标时)。 | ### 不推荐 {#not-recommended} - `OnlineMeetings.ReadWrite.All` / `Chat.ReadWrite`(不带 `.All`)——比管道所需的范围更广。 - 委派权限——管道使用仅应用(客户端凭据)流;如果没有用户登录,委派权限将无法工作。 ## 步骤 4:(推荐)使用应用程序访问策略限定应用程序范围 {#step-4-recommended-scope-the-app-with-an-application-access-policy} 默认情况下,像 `OnlineMeetings.Read.All` 这样的应用程序权限会授予应用程序访问租户中**所有**会议的权限。对于合作伙伴演示和开发租户来说,这没问题;但对于生产环境,你几乎肯定希望限制应用程序可以读取哪些用户的会议。 Microsoft 为此专门提供了 Teams 的**应用程序访问策略**。该策略仅通过 PowerShell 配置;没有门户 UI。 在安装了 MicrosoftTeams 模块并已连接 (`Connect-MicrosoftTeams`) 的管理员 PowerShell 中: ```powershell # Create a policy scoped to the Hermes app New-CsApplicationAccessPolicy ` -Identity "Hermes-Meeting-Pipeline-Policy" ` -AppIds "" ` -Description "Restrict Hermes meeting pipeline to allow-listed users" # Grant the policy to specific users whose meetings the pipeline may read Grant-CsApplicationAccessPolicy ` -PolicyName "Hermes-Meeting-Pipeline-Policy" ` -Identity "alice@example.com" Grant-CsApplicationAccessPolicy ` -PolicyName "Hermes-Meeting-Pipeline-Policy" ` -Identity "bob@example.com" ``` 授予后,传播最多可能需要 30 分钟。使用以下命令进行验证: ```powershell Test-CsApplicationAccessPolicy -Identity "alice@example.com" -AppId "" ``` 如果没有该策略,**任何**用户的会议都是可读的——这是权限在技术上授予的范围。不要在生产租户上跳过此步骤。 ## 步骤 5:将凭据写入你的 Env 文件 {#step-5-write-the-credentials-to-your-env-file} 将收集的三个值放入 `~/.hermes/.env`: ```bash MSGRAPH_TENANT_ID= MSGRAPH_CLIENT_ID= MSGRAPH_CLIENT_SECRET= ``` 设置文件权限,确保只有你可以读取该密钥: ```bash chmod 600 ~/.hermes/.env ``` ## 步骤 6:验证令牌流程 {#step-6-verify-the-token-flow} Hermes 附带了一个 Graph 身份验证冒烟测试。在 Hermes 安装目录下执行: ```python python -c " import asyncio from tools.microsoft_graph_auth import MicrosoftGraphTokenProvider provider = MicrosoftGraphTokenProvider.from_env() token = asyncio.run(provider.get_access_token()) print('Token acquired, length:', len(token)) print(provider.inspect_token_health()) " ``` 成功运行时会打印一个长令牌字符串和一个健康状态字典,其中显示 `cached: True` 以及接近 3600 的 `expires_in_seconds` 值。失败时会产生带有 Azure 错误代码的 `MicrosoftGraphTokenError` — 最常见的错误如下: | Azure 错误 | 含义 | 修复方法 | |-------------|---------|-----| | `AADSTS7000215: Invalid client secret` | 密钥值不匹配或已过期。 | 在步骤 2 中生成新密钥;更新 `.env`。 | | `AADSTS700016: Application not found` | `MSGRAPH_CLIENT_ID` 错误或租户错误。 | 仔细检查步骤 1 中的值是否来自同一应用。 | | `AADSTS90002: Tenant not found` | `MSGRAPH_TENANT_ID` 拼写错误。 | 再次从应用概述中复制目录(租户)ID。 | | 调用时出现 `insufficient_claims`(而非获取令牌时) | 令牌获取成功,但 Graph 返回 401/403。 | 你跳过了步骤 3 的管理员同意,或者添加了权限但未重新同意。返回 API 权限页面并再次点击 **Grant admin consent**(授予管理员同意)。 | ## 轮换客户端密钥 {#rotating-the-client-secret} Azure 客户端密钥有固定的过期时间。在你的密钥过期之前: 1. 在步骤 2 中创建第二个客户端密钥,不要删除第一个密钥。 2. 使用新值更新 `~/.hermes/.env` 中的 `MSGRAPH_CLIENT_SECRET`。 3. 重启网关以加载新密钥:`hermes gateway restart`。 4. 使用上述冒烟测试进行验证。 5. 从 Azure 门户中删除旧密钥。 ## 后续步骤 {#next-steps} 一旦凭据验证通过,请继续执行以下操作: - **Webhook 监听器设置** — 搭建接收 Graph 变更通知的 `msgraph_webhook` 网关节点平台。 - **管道配置** — 配置 Teams 会议管道运行时和操作员 CLI。 - **出站交付** — 将摘要回传到 Teams 频道或聊天中。 这些页面位于添加相应运行时的 PR 旁边。此凭据设置是一个独立的前置条件,可以提前安全地完成。 --- ### 从 OpenClaw 迁移 - URL: https://hermesagent.org.cn/docs/guides/migrate-from-openclaw - Path: guides/migrate-from-openclaw.md - Category: guides - Description: OpenClaw / Clawdbot 设置迁移到 Hermes Agent 的完整指南 —— 有哪些内容会被迁移、如何迁移配置映射,以及迁移后需要检查的内容。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/migrate-from-openclaw.md - Translated At: 2026-04-11T03:28:13.774Z - Headings: 快速开始 | 选项 | 迁移内容 | 人格、记忆与指令 | 技能(4 个来源) | 模型与提供方配置 | Agent 行为 | 会话重置策略 | MCP 服务器 | TTS(文本转语音) | 消息平台 | 其他配置 # 从 OpenClaw 迁移 {#migrate-from-openclaw} `hermes claw migrate` 命令可将你的 OpenClaw(或旧版 Clawdbot/Moldbot)设置导入到 Hermes。本指南详细说明了迁移内容、配置键映射关系,以及迁移后需要验证的事项。 ## 快速开始 {#quick-start} ```bash # 预览将发生的操作(不会修改文件) hermes claw migrate --dry-run # 运行迁移(默认不包含密钥) hermes claw migrate # 完整迁移(包含 API 密钥) hermes claw migrate --preset full ``` 迁移默认从 `~/.openclaw/` 读取数据。如果你仍保留旧版的 `~/.clawdbot/` 或 `~/.moldbot/` 目录,系统会自动检测。同样,旧版配置文件名(如 `clawdbot.json`、`moldbot.json`)也会被自动识别。 ## 选项 {#options} | 选项 | 描述 | |------|------| | `--dry-run` | 预览将要迁移的内容,但不写入任何数据。 | | `--preset ` | `full`(默认,包含密钥)或 `user-data`(不包含 API 密钥)。 | | `--overwrite` | 在发生冲突时覆盖现有的 Hermes 文件(默认:跳过)。 | | `--migrate-secrets` | 包含 API 密钥(当使用 `--preset full` 时默认开启)。 | | `--source ` | 自定义 OpenClaw 目录路径。 | | `--workspace-target ` | 指定 `AGENTS.md` 的存放位置。 | | `--skill-conflict ` | `skip`(默认)、`overwrite` 或 `rename`。 | | `--yes` | 跳过确认提示。 | ## 迁移内容 {#what-gets-migrated} ### 人格、记忆与指令 {#persona-memory-and-instructions} | 内容 | OpenClaw 源路径 | Hermes 目标路径 | 说明 | |------|----------------|----------------|------| | 人格设定 | `workspace/SOUL.md` | `~/.hermes/SOUL.md` | 直接复制 | | 工作区指令 | `workspace/AGENTS.md` | `--workspace-target` 指定的 `AGENTS.md` | 需要 `--workspace-target` 标志 | | 长期记忆 | `workspace/MEMORY.md` | `~/.hermes/memories/MEMORY.md` | 解析为条目,与现有内容合并,去重。使用 `§` 作为分隔符。 | | 用户档案 | `workspace/USER.md` | `~/.hermes/memories/USER.md` | 与记忆相同的条目合并逻辑 | | 每日记忆文件 | `workspace/memory/*.md` | `~/.hermes/memories/MEMORY.md` | 所有每日文件合并至主记忆文件 | 所有工作区文件还会检查 `workspace.default/` 作为备用路径。 ### 技能(4 个来源) {#skills-4-sources} | 来源 | OpenClaw 位置 | Hermes 目标位置 | |------|---------------|----------------| | 工作区技能 | `workspace/skills/` | `~/.hermes/skills/openclaw-imports/` | | 管理/共享技能 | `~/.openclaw/skills/` | `~/.hermes/skills/openclaw-imports/` | | 个人跨项目技能 | `~/.agents/skills/` | `~/.hermes/skills/openclaw-imports/` | | 项目级共享技能 | `workspace/.agents/skills/` | `~/.hermes/skills/openclaw-imports/` | 技能冲突由 `--skill-conflict` 处理:`skip` 保留现有 Hermes 技能,`overwrite` 替换之,`rename` 创建 `-imported` 复制版本。 ### 模型与提供方配置 {#model-and-provider-configuration} | 内容 | OpenClaw 配置路径 | Hermes 目标路径 | 说明 | |------|------------------|----------------|------| | 默认模型 | `agents.defaults.model` | `config.yaml` → `model` | 可为字符串或 `{primary, fallbacks}` 对象 | | 自定义提供方 | `models.providers.*` | `config.yaml` → `custom_providers` | 映射 `baseUrl`、`apiType`("openai"→"chat_completions","anthropic"→"anthropic_messages") | | 提供方 API 密钥 | `models.providers.*.apiKey` | `~/.hermes/.env` | 需启用 `--migrate-secrets`。详见下方 [API 密钥解析](#api-key-resolution) | ### Agent 行为 {#agent-behavior} | 内容 | OpenClaw 配置路径 | Hermes 配置路径 | 映射关系 | |------|------------------|----------------|----------| | 最大轮次 | `agents.defaults.timeoutSeconds` | `agent.max_turns` | `timeoutSeconds / 10`,上限为 200 | | 详细模式 | `agents.defaults.verboseDefault` | `agent.verbose` | "off" / "on" / "full" | | 思考力度 | `agents.defaults.thinkingDefault` | `agent.reasoning_effort` | "always"/"high" → "high","auto"/"medium" → "medium","off"/"low"/"none"/"minimal" → "low" | | 压缩功能 | `agents.defaults.compaction.mode` | `compression.enabled` | "off" → false,其他值 → true | | 压缩模型 | `agents.defaults.compaction.model` | `compression.summary_model` | 直接复制字符串 | | 人类延迟 | `agents.defaults.humanDelay.mode` | `human_delay.mode` | "natural" / "custom" / "off" | | 人类延迟时间 | `agents.defaults.humanDelay.minMs` / `.maxMs` | `human_delay.min_ms` / `.max_ms` | 直接复制 | | 时区 | `agents.defaults.userTimezone` | `timezone` | 直接复制字符串 | | 执行超时 | `tools.exec.timeoutSec` | `terminal.timeout` | 直接复制(字段为 `timeoutSec`,非 `timeout`) | | Docker沙箱 | `agents.defaults.sandbox.backend` | `terminal.backend` | "docker" → "docker" | | Docker 镜像 | `agents.defaults.sandbox.docker.image` | `terminal.docker_image` | 直接复制 | ### 会话重置策略 {#session-reset-policies} | OpenClaw 配置路径 | Hermes 配置路径 | 说明 | |------------------|----------------|------| | `session.reset.mode` | `session_reset.mode` | "daily"、"idle" 或两者兼有 | | `session.reset.atHour` | `session_reset.at_hour` | 每日重置的小时数(0–23) | | `session.reset.idleMinutes` | `session_reset.idle_minutes` | 无操作分钟数 | 注意:OpenClaw 还有 `session.resetTriggers`(一个简单的字符串数组,如 `["daily", "idle"]`)。如果未找到结构化 `session.reset`,迁移将回退至从 `resetTriggers` 推断。 ### MCP 服务器 {#mcp-servers} | OpenClaw 字段 | Hermes 字段 | 说明 | |----------------|-------------|------| | `mcp.servers.*.command` | `mcp_servers.*.command` | Stdio 传输 | | `mcp.servers.*.args` | `mcp_servers.*.args` | | | `mcp.servers.*.env` | `mcp_servers.*.env` | | | `mcp.servers.*.cwd` | `mcp_servers.*.cwd` | | | `mcp.servers.*.url` | `mcp_servers.*.url` | HTTP/SSE 传输 | | `mcp.servers.*.tools.include` | `mcp_servers.*.tools.include` | 工具过滤 | | `mcp.servers.*.tools.exclude` | `mcp_servers.*.tools.exclude` | | ### TTS(文本转语音) {#tts-text-to-speech} TTS 设置从 **两个** OpenClaw 配置位置读取,优先级如下: 1. `messages.tts.providers.{provider}.*`(标准位置) 2. 顶层 `talk.providers.{provider}.*`(回退位置) 3. 旧版扁平键 `messages.tts.{provider}.*`(最旧格式) | 项目 | Hermes 目标位置 | |------|----------------| | 提供商名称 | `config.yaml` → `tts.provider` | | ElevenLabs 语音 ID | `config.yaml` → `tts.elevenlabs.voice_id` | | ElevenLabs 模型 ID | `config.yaml` → `tts.elevenlabs.model_id` | | OpenAI 模型 | `config.yaml` → `tts.openai.model` | | OpenAI 语音 | `config.yaml` → `tts.openai.voice` | | Edge TTS 语音 | `config.yaml` → `tts.edge.voice` | | TTS 资产 | `~/.hermes/tts/`(文件复制) | ### 消息平台 {#messaging-platforms} | 平台 | OpenClaw 配置路径 | Hermes `.env` 变量 | 说明 | |------|-------------------|--------------------|------| | Telegram | `channels.telegram.botToken` | `TELEGRAM_BOT_TOKEN` | Token 可为字符串或 [SecretRef](#secretref-handling) | | Telegram | `credentials/telegram-default-allowFrom.json` | `TELEGRAM_ALLOWED_USERS` | 从 `allowFrom[]` 数组中以逗号连接 | | Discord | `channels.discord.token` | `DISCORD_BOT_TOKEN` | | | Discord | `channels.discord.allowFrom` | `DISCORD_ALLOWED_USERS` | | | Slack | `channels.slack.botToken` | `SLACK_BOT_TOKEN` | | | Slack | `channels.slack.appToken` | `SLACK_APP_TOKEN` | | | Slack | `channels.slack.allowFrom` | `SLACK_ALLOWED_USERS` | | | WhatsApp | `channels.whatsapp.allowFrom` | `WHATSAPP_ALLOWED_USERS` | 通过 Baileys QR 配对认证(非 token) | | Signal | `channels.signal.account` | `SIGNAL_ACCOUNT` | | | Signal | `channels.signal.httpUrl` | `SIGNAL_HTTP_URL` | | | Signal | `channels.signal.allowFrom` | `SIGNAL_ALLOWED_USERS` | | | Matrix | `channels.matrix.botToken` | `MATRIX_ACCESS_TOKEN` | 通过 deep-channels 迁移 | | Mattermost | `channels.mattermost.botToken` | `MATTERMOST_BOT_TOKEN` | 通过 deep-channels 迁移 | ### 其他配置 {#other-config} | 项目 | OpenClaw 路径 | Hermes 路径 | 说明 | |------|---------------|-------------|------| | 审批模式 | `approvals.exec.mode` | `config.yaml` → `approvals.mode` | "auto"→"off", "always"→"manual", "smart"→"smart" | | 命令白名单 | `exec-approvals.json` | `config.yaml` → `command_allowlist` | 模式合并并去重 | | 浏览器 CDP URL | `browser.cdpUrl` | `config.yaml` → `browser.cdp_url` | | | 浏览器无头模式 | `browser.headless` | `config.yaml` → `browser.headless` | | | Brave 搜索密钥 | `tools.web.search.brave.apiKey` | `.env` → `BRAVE_API_KEY` | 需启用 `--migrate-secrets` | | 网关认证 token | `gateway.auth.token` | `.env` → `HERMES_GATEWAY_TOKEN` | 需启用 `--migrate-secrets` | | 工作目录 | `agents.defaults.workspace` | `.env` → `MESSAGING_CWD` | | ### 已归档(无直接 Hermes 对应项) {#archived-no-direct-hermes-equivalent} 这些配置将保存至 `~/.hermes/migration/openclaw//archive/` 以供手动审查: | 项目 | 归档文件 | 如何在 Hermes 中重建 | |------|--------|---------------------| | `IDENTITY.md` | `archive/workspace/IDENTITY.md` | 合并至 `SOUL.md` | | `TOOLS.md` | `archive/workspace/TOOLS.md` | Hermes 内置工具说明 | | `HEARTBEAT.md` | `archive/workspace/HEARTBEAT.md` | 使用 cron 任务实现周期性任务 | | `BOOTSTRAP.md` | `archive/workspace/BOOTSTRAP.md` | 使用上下文文件或技能 | | Cron 任务 | `archive/cron-config.json` | 使用 `hermes cron create` 重建 | | 插件 | `archive/plugins-config.json` | 参见 [插件指南](/docs/user-guide/features/hooks) | | 钩子/Webhook | `archive/hooks-config.json` | 使用 `hermes webhook` 或网关钩子 | | 记忆后端 | `archive/memory-backend-config.json` | 通过 `hermes honcho` 配置 | | 技能注册表 | `archive/skills-registry-config.json` | 使用 `hermes skills config` | | UI/身份 | `archive/ui-identity-config.json` | 使用 `/skin` 命令 | | 日志 | `archive/logging-diagnostics-config.json` | 在 `config.yaml` 的 logging 部分设置 | | 多 Agent 列表 | `archive/agents-list.json` | 使用 Hermes 配置文件 | | 通道绑定 | `archive/bindings.json` | 按平台手动设置 | | 复杂通道 | `archive/channels-deep-config.json` | 手动平台配置 | ## API 密钥解析 {#api-key-resolution} 当启用 `--migrate-secrets` 时,API 密钥将按优先级从 **三个来源** 收集: 1. **配置值** — `models.providers.*.apiKey` 和 `openclaw.json` 中 TTS 提供商密钥 2. **环境文件** — `~/.openclaw/.env`(如 `OPENROUTER_API_KEY`、`ANTHROPIC_API_KEY` 等) 3. **认证配置文件** — `~/.openclaw/agents/main/agent/auth-profiles.json`(按 Agent 的凭据) 配置值具有最高优先级。`.env` 文件用于填充缺失的值。认证配置文件则用于填充剩余的空白。 ### 支持的键目标 {#supported-key-targets} `OPENROUTER_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `DEEPSEEK_API_KEY`, `GEMINI_API_KEY`, `ZAI_API_KEY`, `MINIMAX_API_KEY`, `ELEVENLABS_API_KEY`, `TELEGRAM_BOT_TOKEN`, `VOICE_TOOLS_OPENAI_KEY` 不在上述允许列表中的键将永远不会被复制。 ## SecretRef 处理 {#secretref-handling} OpenClaw 配置中用于令牌和 API 密钥的值可以采用三种格式: ```json // 纯字符串 "channels": { "telegram": { "botToken": "123456:ABC-DEF..." } } // 环境模板 "channels": { "telegram": { "botToken": "${TELEGRAM_BOT_TOKEN}" } } // SecretRef 对象 "channels": { "telegram": { "botToken": { "source": "env", "id": "TELEGRAM_BOT_TOKEN" } } } ``` 迁移过程会解析这三种格式。对于环境模板和 `source: "env"` 的 SecretRef 对象,它会从 `~/.openclaw/.env` 中查找对应值。而 `source: "file"` 或 `source: "exec"` 的 SecretRef 对象无法自动解析——这些值必须在迁移后手动添加到 Hermes 中。 ## 迁移后操作 {#after-migration} 1. **检查迁移报告** —— 迁移完成后会打印报告,包含已迁移、跳过和冲突项的数量。 2. **审查归档文件** —— `~/.hermes/migration/openclaw//archive/` 中的任何内容都需要手动处理。 3. **验证 API 密钥** —— 运行 `hermes status` 以检查各服务商的认证状态。 4. **测试消息功能** —— 如果你迁移了平台令牌,请重启网关:`systemctl --user restart hermes-gateway` 5. **检查会话策略** —— 确认 `hermes config get session_reset` 的值符合你的预期。 6. **重新配对 WhatsApp** —— WhatsApp 使用二维码配对(Baileys),不支持令牌迁移。请运行 `hermes whatsapp` 来完成配对。 ## 故障排除 {#troubleshooting} ### “未找到 OpenClaw 目录” {#openclaw-directory-not-found} 迁移过程会依次检查 `~/.openclaw/`、`~/.clawdbot/`、`~/.moldbot/`。如果你的安装路径不同,请使用 `--source /path/to/your/openclaw` 指定路径。 ### “未找到任何服务商 API 密钥” {#no-provider-api-keys-found} 密钥可能位于你的 `.env` 文件中,而非 `openclaw.json`。迁移过程会同时检查两者——请确保 `~/.openclaw/.env` 存在且包含所需密钥。如果密钥使用了 `source: "file"` 或 `source: "exec"` 的 SecretRef,则无法自动解析。 ### 迁移后技能未出现 {#skills-not-appearing-after-migration} 导入的技能会存放在 `~/.hermes/skills/openclaw-imports/`。要使这些技能生效,请启动一个新的会话,或运行 `/skills` 命令以确认它们已加载。 ### TTS 语音未被迁移 {#tts-voice-not-migrated} OpenClaw 将 TTS 设置存储在两个位置:`messages.tts.providers.*` 和顶层的 `talk` 配置。迁移过程会检查这两个位置。如果你的语音 ID 是通过 OpenClaw UI 设置的(存储在其他路径),可能需要手动设置:`hermes config set tts.elevenlabs.voice_id YOUR_VOICE_ID`。 --- ### MiniMax OAuth - URL: https://hermesagent.org.cn/docs/guides/minimax-oauth - Path: guides/minimax-oauth.md - Category: guides - Description: 通过浏览器 OAuth 登录 MiniMax,并在 Hermes Agent 中使用 MiniMax M2.7 模型 — 无需 API 密钥 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/minimax-oauth.md - Translated At: 2026-06-16T00:44:57.644Z - Headings: 概览 | 前提条件 | 快速开始 | 手动登录 | 中国区 | 远程/无头会话 | OAuth 流程 | 检查登录状态 | 切换模型 | 配置参考 | 区域端点 | Provider 别名 # MiniMax OAuth {#minimax-oauth} Hermes Agent 通过基于浏览器的 OAuth 登录流程支持 **MiniMax**,使用与 [MiniMax 门户](https://www.minimax.io) 相同的凭据。无需 API 密钥或信用卡——只需登录一次,Hermes 就会自动刷新您的会话。 该传输层复用 `anthropic_messages` 适配器(MiniMax 在 `/anthropic` 处公开了一个兼容 Anthropic Messages 的端点),因此所有现有的工具调用、流式传输和上下文功能无需任何适配器更改即可正常工作。 ## 概览 {#overview} | 项目 | 值 | |------|-------| | Provider ID | `minimax-oauth` | | 显示名称 | MiniMax (OAuth) | | 认证类型 | 浏览器 OAuth(PKCE 重定向流程) | | 传输层 | 兼容 Anthropic Messages (`anthropic_messages`) | | 模型 | `MiniMax-M2.7`, `MiniMax-M2.7-highspeed` | | 全球端点 | `https://api.minimax.io/anthropic` | | 中国端点 | `https://api.minimaxi.com/anthropic` | | 需要环境变量 | 否(此 provider **不**使用 `MINIMAX_API_KEY`) | ## 前提条件 {#prerequisites} - Python 3.9+ - 已安装 Hermes Agent - 拥有 [minimax.io](https://www.minimax.io)(全球)或 [minimaxi.com](https://www.minimaxi.com)(中国)的 MiniMax 账户 - 本地机器上可用浏览器(或在远程会话中使用 `--no-browser`) ## 快速开始 {#quick-start} ```bash # Launch the provider and model picker hermes model # → Select "MiniMax (OAuth)" from the provider list # → Hermes opens your browser to the MiniMax authorization page # → Approve access in the browser # → Select a model (MiniMax-M2.7 or MiniMax-M2.7-highspeed) # → Start chatting hermes ``` 首次登录后,凭据将存储在 `~/.hermes/auth.json` 中,并在每次会话前自动刷新。 ## 手动登录 {#logging-in-manually} 您可以触发登录而无需经过模型选择器: ```bash hermes auth add minimax-oauth ``` ### 中国区 {#china-region} 如果您的账户位于中国平台 (`minimaxi.com`),请改用基于 API 密钥的 `minimax-cn` provider——`minimax-cn` 仅注册为 `auth_type="api_key"`(无 OAuth 流程)。直接配置 `MINIMAX_CN_API_KEY`(以及可选的 `MINIMAX_CN_BASE_URL`): ```bash echo 'MINIMAX_CN_API_KEY=your-key' >> ~/.hermes/.env ``` ### 远程/无头会话 {#remote--headless-sessions} 在没有浏览器的服务器或容器上: ```bash hermes auth add minimax-oauth --no-browser ``` Hermes 将打印验证 URL 和用户代码——在任何设备上打开该 URL 并在提示时输入代码。 ## OAuth 流程 {#the-oauth-flow} Hermes 针对 MiniMax OAuth 端点实现 PKCE 浏览器 OAuth 流程: 1. Hermes 生成 PKCE verifier/challenge 对和一个随机 state 值。 2. 它将 challenge POST 到 `{base_url}/oauth/code` 并接收 `user_code` 和 `verification_uri`。 3. 您的浏览器打开 `verification_uri`。如果提示,请输入 `user_code`。 4. Hermes 轮询 `{base_url}/oauth/token` 直到收到令牌(或超过截止时间)。 5. 令牌(`access_token`、`refresh_token`、过期时间)保存在 `~/.hermes/auth.json` 中的 `minimax-oauth` 键下。 令牌刷新(标准 OAuth `refresh_token` 授权)会在每次会话开始时自动运行,前提是访问令牌距离过期不足 60 秒。 ## 检查登录状态 {#checking-login-status} ```bash hermes doctor ``` `◆ Auth Providers` 部分将显示: ``` ✓ MiniMax OAuth (logged in, region=global) ``` 或者,如果未登录: ``` ⚠ MiniMax OAuth (not logged in) ``` ## 切换模型 {#switching-models} ```bash hermes model # → Select "MiniMax (OAuth)" # → Pick from the model list ``` 或直接设置模型: ```bash hermes config set model.default MiniMax-M2.7 hermes config set model.provider minimax-oauth ``` ## 配置参考 {#configuration-reference} 登录后,`~/.hermes/config.yaml` 将包含类似以下条目: ```yaml model: default: MiniMax-M2.7 provider: minimax-oauth base_url: https://api.minimax.io/anthropic ``` ### 区域端点 {#region-endpoints} | Provider id | 门户 | 推理端点 | |-------------|--------|-------------------| | `minimax-oauth` (全球) | `https://api.minimax.io` | `https://api.minimax.io/anthropic` | | `minimax-cn` (中国) | `https://api.minimaxi.com` | `https://api.minimaxi.com/anthropic` | ### Provider 别名 {#provider-aliases} 以下所有名称均解析为 `minimax-oauth`: ```bash hermes --provider minimax-oauth # canonical hermes --provider minimax-portal # alias hermes --provider minimax-global # alias hermes --provider minimax_oauth # alias (underscore form) ``` ## 环境变量 {#environment-variables} `minimax-oauth` provider **不**使用 `MINIMAX_API_KEY` 或 `MINIMAX_BASE_URL`。这些变量仅用于基于 API 密钥的 `minimax` 和 `minimax-cn` providers。 | 变量 | 效果 | |----------|--------| | `MINIMAX_API_KEY` | 仅由 `minimax` provider 使用——对 `minimax-oauth` 忽略 | | `MINIMAX_CN_API_KEY` | 仅由 `minimax-cn` provider 使用——对 `minimax-oauth` 忽略 | 要将 `minimax-oauth` 用作活动 provider,请在 `config.yaml` 中设置 `model.provider: minimax-oauth`(使用 `hermes setup` 进行引导式流程),或在单次调用时传递 `--provider minimax-oauth`: ```bash hermes --provider minimax-oauth ``` ## 模型 {#models} | 模型 | 最佳用途 | |-------|----------| | `MiniMax-M2.7` | 长上下文推理、复杂工具调用 | | `MiniMax-M2.7-highspeed` | 低延迟、轻量级任务、辅助调用 | 两种模型均支持高达 200,000 个 token 的上下文。 当 `minimax-oauth` 为主要 provider 时,`MiniMax-M2.7-highspeed` 也会自动用作视觉和委托任务的辅助模型。 ## 故障排除 {#troubleshooting} ### 令牌过期——未自动重新登录 {#token-expired-—-not-re-logging-in-automatically} 如果令牌距离过期不足 60 秒,Hermes 会在每次会话开始时刷新令牌。如果访问令牌已经过期(例如,在长时间离线后),刷新将在下一个请求时自动发生。如果刷新因 `refresh_token_reused` 或 `invalid_grant` 失败,Hermes 将会话标记为需要重新登录。 当刷新失败为终止性错误(HTTP 4xx、`invalid_grant`、授权已撤销等)时,Hermes 会将刷新令牌标记为失效并在本地隔离,以避免不断重放注定失败的交换请求。代理会显示一条“需要重新身份验证”的消息,并在您再次登录之前保持静默。 **修复方法:** 再次运行 `hermes auth add minimax-oauth` 以启动全新的登录流程。下一次成功交换后,隔离状态将被清除。 ### 授权超时 {#authorization-timed-out} 设备代码流程具有有限的有效期窗口。如果您未及时批准登录,Hermes 将抛出超时错误。 **修复方法:** 重新运行 `hermes auth add minimax-oauth`(或 `hermes model`)。流程将重新开始。 ### 状态不匹配(可能的 CSRF 攻击) {#state-mismatch-possible-csrf} Hermes 检测到授权服务器返回的 `state` 值与其发送的值不匹配。 **修复方法:** 重新执行登录操作。如果问题持续存在,请检查是否存在修改 OAuth 响应的代理或重定向。 ### 从远程服务器登录 {#logging-in-from-a-remote-server} 如果 `hermes` 无法打开浏览器窗口,请使用 `--no-browser`: ```bash hermes auth add minimax-oauth --no-browser ``` Hermes 将打印 URL 和代码。在任何设备上打开该 URL 并完成那里的流程。 ### 运行时出现“未登录 MiniMax OAuth”错误 {#not-logged-into-minimax-oauth-error-at-runtime} 身份验证存储中没有 `minimax-oauth` 的凭据。您尚未登录,或者凭据文件已被删除。 **修复方法:** 运行 `hermes model` 并选择 MiniMax (OAuth),或者运行 `hermes auth add minimax-oauth`。 ## 注销 {#logging-out} 要移除存储的 MiniMax OAuth 凭据: ```bash hermes auth remove minimax-oauth ``` ## 另请参阅 {#see-also} - [AI 提供商参考](../integrations/providers) - [环境变量](../reference/environment-variables) - [配置](../user-guide/configuration) - [hermes doctor](../reference/cli-commands) --- ### 通过 SSH 完成 OAuth - URL: https://hermesagent.org.cn/docs/guides/oauth-over-ssh - Path: guides/oauth-over-ssh.md - Category: guides - Description: 当 Hermes 运行在远程主机、容器或跳板机后面时,如何完成 xAI、Spotify 和 OAuth MCP server 的浏览器回调。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/oauth-over-ssh.md - Translated At: 2026-05-30T10:05:00.000+08:00 - Headings: SSH 端口转发 | 没有 SSH 客户端怎么办? | 哪些 provider 需要这样做? | 参考链接 # 通过 SSH 完成 OAuth {#oauth-over-ssh} 有些 Hermes provider 会使用 loopback redirect OAuth,例如 xAI Grok OAuth、Spotify,以及 Linear、Sentry、Atlassian、Asana、Figma 等远程 MCP server。它们会把浏览器重定向到类似 `http://127.0.0.1:/callback` 的地址,让 Hermes 启动的小 HTTP listener 接收授权码。 当 Hermes 和浏览器在同一台机器上时,这很简单。问题出在远程机器:你的浏览器访问的是本地电脑的 `127.0.0.1`,但 listener 其实在远程服务器上。 ## SSH 端口转发 {#ssh-forward} 解决方法是做本地端口转发。以 xAI OAuth 的默认端口 `56121` 为例: ```bash # 在本地电脑新开一个终端 ssh -N -L 56121:127.0.0.1:56121 user@remote-host # 在已经登录的远程 SSH 会话中运行 hermes auth add xai-oauth --no-browser ``` Hermes 会打印授权 URL。把它复制到本地浏览器打开,浏览器回调到本地 `127.0.0.1:56121` 后,SSH 隧道会把请求转发给远程 Hermes listener。 Spotify 常用端口是 `43827`。MCP server 可能自动选择端口,实际端口以 Hermes 输出的 `Waiting for callback on ...` 为准。 ## 没有 SSH 客户端怎么办? {#manual-paste} 如果你在 GCP Cloud Shell、GitHub Codespaces、EC2 Instance Connect、Gitpod 或浏览器 Web IDE 里操作,可能没有可用的本地 SSH 客户端。这时使用 `--manual-paste`: ```bash hermes auth add xai-oauth --manual-paste ``` 流程是: 1. Hermes 打印授权 URL; 2. 你在本地浏览器打开并授权; 3. 浏览器跳转到 `127.0.0.1` 失败,这是正常现象; 4. 从浏览器地址栏复制完整回调 URL; 5. 粘贴回 Hermes 的 `Callback URL:` 提示处。 Hermes 接受完整 URL、`?code=...&state=...` 查询片段,或上游页面直接展示的 code。这个方式只是改变回调传输方式,不降低 OAuth 本身的 PKCE、state 和 nonce 校验。 ## 哪些 provider 需要这样做? {#providers} | Provider | 常见端口 | 远程运行时是否需要处理 | |---|---:|---| | `xai-oauth` | `56121` | 需要 SSH 转发或 manual paste | | Spotify | `43827` | 需要 SSH 转发或 manual paste | | OAuth MCP server | 自动选择 | 需要 SSH 转发或 paste 回调 URL | | Anthropic Claude Pro / Max | 不适用 | 不需要,使用 paste code | | OpenAI Codex / ChatGPT Plus / Pro | 不适用 | 不需要,使用 device code | | MiniMax、Nous Portal | 不适用 | 不需要,使用 device code | ## 参考链接 {#references} - [官方原文:OAuth over SSH / Remote Hosts](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/oauth-over-ssh.md) - [xAI Grok OAuth](/docs/guides/xai-grok-oauth) --- ### 操作 Teams 会议管道 - URL: https://hermesagent.org.cn/docs/guides/operate-teams-meeting-pipeline - Path: guides/operate-teams-meeting-pipeline.md - Category: guides - Description: Microsoft Teams 会议管道的运行手册、上线检查清单和操作人员工作表 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/operate-teams-meeting-pipeline.md - Translated At: 2026-06-16T00:45:09.329Z - Headings: 核心操作员命令 | 验证配置快照 | 检查令牌健康状态 | 检查订阅 | 续订即将过期的订阅 | 自动化订阅续订(生产环境必需) | 选项 1:Hermes cron(如果你已经运行 Hermes 网关,推荐此项) | 选项 2:systemd timer(推荐用于 Linux 生产部署) | 选项 3:普通 crontab | 验证续订是否正常工作 | 检查最近的任务 | 重放存储的任务 # 操作 Teams 会议流水线 {#operate-the-teams-meeting-pipeline} 在已从 [Teams 会议](/docs/user-guide/messaging/teams-meetings) 启用该功能后,请使用本指南。 本页涵盖: - 操作员 CLI 流程 - 常规订阅维护 - 故障分类排查 - 上线检查 - 发布工作表 ## 核心操作员命令 {#core-operator-commands} ### 验证配置快照 {#validate-the-config-snapshot} ```bash hermes teams-pipeline validate ``` 在任何配置更改后首先使用此命令。 ### 检查令牌健康状态 {#inspect-token-health} ```bash hermes teams-pipeline token-health hermes teams-pipeline token-health --force-refresh ``` 当怀疑存在过期的身份验证状态时,使用 `--force-refresh`。 ### 检查订阅 {#inspect-subscriptions} ```bash hermes teams-pipeline subscriptions ``` ### 续订即将过期的订阅 {#renew-near-expiry-subscriptions} ```bash hermes teams-pipeline maintain-subscriptions hermes teams-pipeline maintain-subscriptions --dry-run ``` ### 自动化订阅续订(生产环境必需) {#automating-subscription-renewal-required-for-production} **Microsoft Graph 订阅最多在 72 小时后过期。** 如果没有进行续订,会议通知将在 3 天后静默停止,导致流水线看似“损坏”。这是任何基于 Graph 的集成的头号运营故障模式。 你**必须**按计划运行 `maintain-subscriptions`。从以下三个选项中选择一个: #### 选项 1:Hermes cron(如果你已经运行 Hermes 网关,推荐此项) {#option-1-hermes-cron-recommended-if-you-already-run-the-hermes-gateway} Hermes 附带内置的 cron 调度器。`--no-agent` 模式将脚本作为任务运行(而不是使用 LLM),且 `--script` 必须指向 `~/.hermes/scripts/` 下的文件。首先创建脚本: ```bash mkdir -p ~/.hermes/scripts cat > ~/.hermes/scripts/maintain-teams-subscriptions.sh <<'EOF' #!/usr/bin/env bash exec hermes teams-pipeline maintain-subscriptions EOF chmod +x ~/.hermes/scripts/maintain-teams-subscriptions.sh ``` 然后注册一个每 12 小时运行一次的仅脚本 cron 任务(相对于 72 小时的过期窗口提供 6 倍的余量): ```bash hermes cron create "0 */12 * * *" \ --name "teams-pipeline-maintain-subscriptions" \ --no-agent \ --script maintain-teams-subscriptions.sh \ --deliver local ``` 验证其已注册并检查下次运行时间: ```bash hermes cron list hermes cron status # scheduler status ``` #### 选项 2:systemd timer(推荐用于 Linux 生产部署) {#option-2-systemd-timer-recommended-for-linux-production-deployments} 创建 `/etc/systemd/system/hermes-teams-pipeline-maintain.service`: ```ini [Unit] Description=Hermes Teams pipeline subscription maintenance After=network-online.target [Service] Type=oneshot User=hermes EnvironmentFile=/etc/hermes/env ExecStart=/usr/local/bin/hermes teams-pipeline maintain-subscriptions ``` 以及 `/etc/systemd/system/hermes-teams-pipeline-maintain.timer`: ```ini [Unit] Description=Run Hermes Teams pipeline subscription maintenance every 12 hours [Timer] OnBootSec=5min OnUnitActiveSec=12h Persistent=true [Install] WantedBy=timers.target ``` 启用: ```bash sudo systemctl daemon-reload sudo systemctl enable --now hermes-teams-pipeline-maintain.timer systemctl list-timers hermes-teams-pipeline-maintain.timer ``` #### 选项 3:普通 crontab {#option-3-plain-crontab} ```cron 0 */12 * * * /usr/local/bin/hermes teams-pipeline maintain-subscriptions >> /var/log/hermes/teams-pipeline-maintain.log 2>&1 ``` 确保 cron 环境拥有 `MSGRAPH_*` 凭据。最简单的修复方法是在 crontab 调用的包装脚本顶部 source `~/.hermes/.env`。 #### 验证续订是否正常工作 {#verifying-renewal-is-working} 设置好计划后,在第一次计划运行后检查续订活动: ```bash hermes teams-pipeline subscriptions # should show expirationDateTime advanced hermes teams-pipeline maintain-subscriptions --dry-run # should show "0 expiring soon" most of the time ``` 如果你发现 Graph webhook 在恰好约 72 小时后神秘地“停止工作”,首先要检查的是:续订任务是否实际运行了? ### 检查最近的任务 {#inspect-recent-jobs} ```bash hermes teams-pipeline list hermes teams-pipeline list --status failed hermes teams-pipeline show ``` ### 重放存储的任务 {#replay-a-stored-job} ```bash hermes teams-pipeline run ``` ### 干跑会议工件获取 {#dry-run-meeting-artifact-fetches} ```bash hermes teams-pipeline fetch --meeting-id hermes teams-pipeline fetch --join-web-url "" ``` ## 常规运行手册 {#routine-runbook} ### 首次设置后 {#after-first-setup} 按顺序运行以下命令: ```bash hermes teams-pipeline validate hermes teams-pipeline token-health --force-refresh hermes teams-pipeline subscriptions ``` 然后触发或等待真实的会议事件并确认: ```bash hermes teams-pipeline list hermes teams-pipeline show ``` ### 每日或定期检查 {#daily-or-periodic-checks} - 运行 `hermes teams-pipeline maintain-subscriptions --dry-run` - 检查 `hermes teams-pipeline list --status failed` - 验证 Teams 交付目标是否仍为正确的聊天或频道 ### 更改 webhook URL 或交付目标之前 {#before-changing-webhook-urls-or-delivery-targets} - 更新公共通知 URL 或 Teams 目标配置 - 运行 `hermes teams-pipeline validate` - 续订或重新创建受影响的订阅 - 确认新事件进入预期的接收端 ## 故障分类排查 {#failure-triage} ### 未创建任何任务 {#no-jobs-are-being-created} 检查: - `msgraph_webhook` 是否已启用 - 公共通知 URL 是否指向 `/msgraph/webhook` - 订阅中的客户端状态是否与 `MSGRAPH_WEBHOOK_CLIENT_STATE` 匹配 - 远程订阅是否仍然存在且未过期 ### 任务停留在重试状态或在摘要生成前失败 {#jobs-stay-in-retry-or-fail-before-summarization} 检查: - 转录权限和可用性 - 录制权限和工件可用性 - 如果启用了录制回退,检查 `ffmpeg` 可用性 - Graph 令牌健康状态 ### 已生成摘要但未交付到 Teams {#summaries-are-produced-but-not-delivered-to-teams} 检查: - `platforms.teams.enabled: true` - `delivery_mode` - webhook 模式下的 `incoming_webhook_url` - Graph 模式下的 `chat_id` 或 `team_id` 加上 `channel_id` - 如果使用 Graph 发帖,检查 Teams 身份验证配置 ### 重复或意外的重放 {#duplicate-or-unexpected-replays} 检查: - 是否使用 `hermes teams-pipeline run` 手动重放了任务 - 该会议的接收端记录是否已存在 - 是否在本地配置中有意启用了重新发送路径 ## 上线检查清单 {#go-live-checklist} - [ ] Graph 凭据存在且正确 - [ ] `msgraph_webhook` 已启用且可从公共互联网访问 - [ ] `MSGRAPH_WEBHOOK_CLIENT_STATE` 已设置并与订阅匹配 - [ ] 已创建转录订阅 - [ ] 如果需要 STT 回退,则已创建录制订阅 - [ ] 如果启用了录制回退,则已安装 `ffmpeg` - [ ] Teams 出站交付目标已配置并验证 - [ ] 仅在确实需要时配置 Notion 和 Linear 接收端 - [ ] `hermes teams-pipeline validate` 返回 OK 快照 - [ ] `hermes teams-pipeline token-health --force-refresh` 成功执行 - [ ] **`maintain-subscriptions` 已安排**(Hermes cron、systemd timer 或 crontab — 参见 [自动化订阅续订](#automating-subscription-renewal-required-for-production))。如果没有此项,Graph 订阅将在 72 小时内静默过期。 - [ ] 真实的端到端会议事件已生成存储的作业 - [ ] 至少有一个摘要已到达预期的交付接收端 ## 交付模式决策指南 {#delivery-mode-decision-guide} | 模式 | 适用场景 | 权衡 | |------|----------|----------| | `incoming_webhook` | 只需简单发布到 Teams | 设置最简单,控制力较少 | | `graph` | 需要通过 Graph 发布到频道或聊天 | 控制力更强,但需要更多身份验证和目标配置 | ## 操作员工作表 {#operator-worksheet} 在 rollout 之前填写此表: | 项目 | 值 | |------|-------| | 公共通知 URL | | | Graph 租户 ID | | | Graph 客户端 ID | | | Webhook 客户端状态 | | | 转录资源订阅 | | | 录制资源订阅 | | | Teams 交付模式 | | | Teams 聊天 ID 或团队/频道 | | | Notion 数据库 ID | | | Linear 团队 ID | | | 存储路径覆盖(如果有) | | | 每日检查负责人 | | ## 变更审查工作表 {#change-review-worksheet} 在更改部署之前使用此表: | 问题 | 回答 | |----------|--------| | 我们是否正在更改公共 webhook URL? | | | 我们是否正在轮换 Graph 凭据? | | | 我们是否正在更改 Teams 交付模式? | | | 我们是否正在迁移到新的 Teams 聊天或频道? | | | 是否需要重新创建或续订订阅? | | | 我们是否需要进行全新的端到端验证运行? | | ## 相关文档 {#related-docs} - [Teams 会议设置](/docs/user-guide/messaging/teams-meetings) - [Microsoft Teams 机器人设置](/docs/user-guide/messaging/teams) --- ### 将脚本输出管道传输至消息平台 - URL: https://hermesagent.org.cn/docs/guides/pipe-script-output - Path: guides/pipe-script-output.md - Category: guides - Description: 使用 hermes send 将文本从任何 shell 脚本、cron 作业、CI 钩子或监控守护进程发送到 Telegram、Discord、Slack、Signal 和其他平台。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/pipe-script-output.md - Translated At: 2026-06-16T00:45:14.065Z - Headings: 快速开始 | 参数参考 | 目标格式 | 退出码 | 消息正文解析 | 实际示例 | 监控:内存 / 磁盘警报 | CI / CD:构建和测试结果 | Cron:每日报告 | 长时间运行的任务:完成后通知 | 使用 json 和 quiet 进行脚本编写 | hermes send 是否需要运行网关? # 将脚本输出管道传输至消息平台 {#pipe-script-output-to-messaging-platforms} `hermes send` 是一个小巧、可脚本化的命令行工具(CLI),用于向 Hermes 已配置的任何消息平台推送消息。你可以将其视为用于通知的跨平台 `curl`——你无需运行网关,无需大型语言模型(LLM),也无需在每个脚本中重新粘贴机器人令牌。 适用场景包括: - 系统监控(内存、磁盘、GPU 温度、长时间运行的作业完成) - CI/CD 通知(部署完成、测试失败) - 需要向你发送结果通知的 Cron 脚本 - 从终端快速发送一次性消息 - 将任何工具的输出管道传输到任意位置(`make | hermes send --to slack:#builds`) 该命令复用 `hermes gateway` 已使用的相同凭据和平台适配器,因此无需维护第二套配置界面。 --- ## 快速开始 {#quick-start} ```bash # Plain text to the home channel for a platform hermes send --to telegram "deploy finished" # Pipe in stdout from anything echo "RAM 92%" | hermes send --to telegram:-1001234567890 # Send a file hermes send --to discord:#ops --file /tmp/report.md # Attach a subject/header line hermes send --to slack:#eng --subject "[CI] build.log" --file build.log # Thread target (Telegram topic, Discord thread) hermes send --to telegram:-1001234567890:17585 "threaded reply" # List every configured target hermes send --list # Filter by platform hermes send --list telegram ``` --- ## 参数参考 {#argument-reference} | 标志 | 描述 | |------|-------------| | `-t, --to TARGET` | 目标。参见 [目标格式](#target-formats)。 | | `message`(位置参数) | 消息文本。省略此项以从 `--file` 或标准输入读取。 | | `-f, --file PATH` | 从文件读取正文。`--file -` 强制使用标准输入。 | | `-s, --subject LINE` | 在正文前 prepend 一个标题/主题行。 | | `-l, --list` | 列出可用目标。可选的位置参数平台过滤器。 | | `-q, --quiet` | 成功时不输出 stdout(仅返回退出码——非常适合脚本)。 | | `--json` | 输出发送操作的原始 JSON 结果。 | | `-h, --help` | 显示内置帮助文本。 | ### 目标格式 {#target-formats} | 格式 | 示例 | 含义 | |--------|---------|---------| | `platform` | `telegram` | 发送到平台配置的默认频道 | | `platform:chat_id` | `telegram:-1001234567890` | 特定的数字聊天 ID / 群组 / 用户 | | `platform:chat_id:thread_id` | `telegram:-1001234567890:17585` | 特定的线程或 Telegram 论坛主题 | | `platform:#channel` | `discord:#ops` | 人类友好的频道名称(根据频道目录解析) | | `platform:+E164` | `signal:+15551234567` | 基于电话号码寻址的平台:Signal、SMS、WhatsApp | Hermes 附带适配器的任何平台均可作为目标: `telegram`、`discord`、`slack`、`signal`、`sms`、`whatsapp`、`matrix`、 `mattermost`、`feishu`、`dingtalk`、`wecom`、`weixin`、`email` 等。 ### 退出码 {#exit-codes} | 代码 | 含义 | |------|---------| | `0` | 发送(或列表)成功 | | `1` | 平台级交付失败(认证、权限、网络问题) | | `2` | 用法 / 参数 / 配置错误 | 退出码遵循标准的 Unix 约定,因此你的脚本可以像处理 `curl` 或 `grep` 一样根据退出码进行分支判断。 --- ## 消息正文解析 {#message-body-resolution} `hermes send` 按以下顺序解析消息正文: 1. **位置参数** — `hermes send --to telegram "hi"` 2. **`--file PATH`** — `hermes send --to telegram --file msg.txt` 3. **管道标准输入** — `echo hi | hermes send --to telegram` 当标准输入是 TTY(无管道)时,Hermes **不会**等待输入——你会收到明确的用法错误提示。这可以防止脚本因意外遗漏正文而挂起。 --- ## 实际示例 {#real-world-examples} ### 监控:内存 / 磁盘警报 {#monitoring-memory--disk-alerts} 用一行可移植的代码替换看门狗脚本中临时的 `curl https://api.telegram.org/...` 调用: ```bash #!/usr/bin/env bash ram_pct=$(free | awk '/^Mem:/ {printf "%d", $3 * 100 / $2}') if [ "$ram_pct" -ge 85 ]; then hermes send --to telegram --subject "⚠ MEMORY WARNING" \ "RAM ${ram_pct}% on $(hostname)" fi ``` 由于 `hermes send` 复用你的 Hermes 配置,同一脚本可在安装了 Hermes 的任何主机上运行——无需手动将机器人令牌导出到每台机器的环境变量中。 :::tip 不要通过网关报警其自身状态 对于可能在网关本身陷入困境时触发的看门狗(如 OOM 警报、磁盘满警报),请继续使用最小化的 `curl` 调用而非 `hermes send`。如果因为系统负载过高导致 Python 解释器无法加载,你仍然希望该警报能够发出。 ::: ### CI / CD:构建和测试结果 {#ci--cd-build-and-test-results} ```bash # In .github/workflows/deploy.yml or any CI script if ./scripts/deploy.sh; then hermes send --to slack:#deploys "✅ ${CI_COMMIT_SHA:0:7} deployed" else tail -n 100 deploy.log | hermes send \ --to slack:#deploys --subject "❌ deploy failed" exit 1 fi ``` ### Cron:每日报告 {#cron-daily-report} ```bash # Crontab entry 0 9 * * * /usr/local/bin/generate-metrics.sh \ | /home/me/.hermes/bin/hermes send \ --to telegram --subject "Daily metrics $(date +%Y-%m-%d)" ``` ### 长时间运行的任务:完成后通知 {#long-running-tasks-ping-when-done} ```bash ./train.py --epochs 200 && \ hermes send --to telegram "training done" || \ hermes send --to telegram "training failed (exit $?)" ``` ### 使用 `--json` 和 `--quiet` 进行脚本编写 {#scripting-with---json-and---quiet} ```bash # Hard-fail a script if delivery fails; don't clutter logs on success hermes send --to telegram --quiet "keepalive" || { echo "Telegram delivery failed" >&2 exit 1 } # Capture the message ID for later editing / threading msg_id=$(hermes send --to discord:#ops --json "build started" \ | jq -r .message_id) ``` --- ## `hermes send` 是否需要运行网关? {#does-hermes-send-need-the-gateway-running} **通常不需要。** 对于任何基于机器人令牌的平台——Telegram、Discord、Slack、Signal、SMS、WhatsApp Cloud API 以及大多数其他平台——`hermes send` 会使用来自 `~/.hermes/.env` 和 `~/.hermes/config.yaml` 的凭据直接调用平台的 REST 端点。它是一个独立的子进程,消息交付后立即退出。 仅对于依赖持久适配器连接的**插件平台**(例如,保持长生命周期 WebSocket 连接的自定义插件),才需要活跃的网关。在这种情况下,你会收到指向网关的明确错误;请使用 `hermes gateway start` 启动网关并重试。 --- ## 列出和发现目标 {#listing-and-discovering-targets} 在向特定频道发送消息之前,你可以检查可用的目标: ```bash # Every target across every configured platform hermes send --list # Just Telegram targets hermes send --list telegram # Machine-readable hermes send --list --json ``` 列表源自 `~/.hermes/channel_directory.json网关运行时每隔几分钟刷新一次该文件。如果你看到“尚未发现任何频道”,请启动一次网关(`hermes gateway start`),以便其填充缓存。 人性化名称(`discord:#ops`、`slack:#engineering`)会在发送时对此缓存进行解析,因此你无需记住数字 ID。 --- ## 与其他方法的比较 {#comparison-with-other-approaches} | 方法 | 多平台支持 | 复用 Hermes 凭证 | 需要网关 | 最佳适用场景 | |----------|----------------|---------------------|---------------|----------| | `hermes send` | ✅ | ✅ | 否(bot-token) | 以下所有场景 | | 向每个平台发送原始 `curl` 请求 | 需分别编写脚本 | 手动配置 | 否 | 关键监控任务 | | 带有 `--deliver` 的 `cron` 任务 | ✅ | ✅ | 否 | 定时代理任务 | | `send_message` 代理工具 | ✅ | ✅ | 否 | 在代理循环内部使用 | `hermes send` 被有意设计为尽可能简单的接口。如果你需要代理决定发送什么内容,请在聊天或 cron 任务中使用 `send_message` 工具。如果你需要运行由 LLM 生成内容的定时任务,请使用 `cronjob(action='create', prompt=...)` 并设置 `deliver='telegram:...'`。如果你只需要管道传输原始字符串,请使用 `hermes send`。 --- ## 相关资源 {#related} - [使用 Cron 自动化一切](/docs/guides/automate-with-cron) — 输出自动分发到任意平台的定时任务。 - [网关内部机制](/docs/developer-guide/gateway-internals) — `hermes send` 与 cron 分发共享的分发路由器。 - [消息平台设置](/docs/user-guide/messaging/) — 每个平台的一次性配置。 --- ### 使用 Hermes 作为 Python 库 - URL: https://hermesagent.org.cn/docs/guides/python-library - Path: guides/python-library.md - Category: guides - Description: 在您自己的 Python 脚本、Web 应用或自动化流水线中嵌入 AIAgent —— 无需命令行界面 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/python-library.md - Translated At: 2026-04-11T03:28:32.957Z - Headings: 安装 | 基本用法 | 完整对话控制 | 配置工具 | 多轮对话 | 保存对话轨迹 | 自定义系统提示 | 批量处理 | 集成示例 | FastAPI 端点 | Discord 机器人 | CI/CD 流水线步骤 # 将 Hermes 作为 Python 库使用 {#using-hermes-as-a-python-library} Hermes 不仅是一个命令行工具。你也可以直接导入 `AIAgent`,在自己的 Python 脚本、Web 应用或自动化流水线中以编程方式使用它。本指南将展示如何操作。 --- ## 安装 {#installation} 直接从仓库安装 Hermes: ```bash pip install git+https://github.com/NousResearch/hermes-agent.git ``` 或使用 [uv](https://docs.astral.sh/uv/): ```bash uv pip install git+https://github.com/NousResearch/hermes-agent.git ``` 你也可以在 `requirements.txt` 中固定版本: ```text hermes-agent @ git+https://github.com/NousResearch/hermes-agent.git ``` :::tip 在作为库使用时,CLI 所用的相同环境变量也是必需的。至少需要设置 `OPENROUTER_API_KEY`(或使用直接提供方访问时设置 `OPENAI_API_KEY` / `ANTHROPIC_API_KEY`)。 ::: --- ## 基本用法 {#basic-usage} 使用 Hermes 最简单的方式是 `chat()` 方法——传入一条消息,即可获得字符串响应: ```python from run_agent import AIAgent agent = AIAgent( model="anthropic/claude-sonnet-4", quiet_mode=True, ) response = agent.chat("What is the capital of France?") print(response) ``` `chat()` 方法在内部处理完整的对话循环——工具调用、重试等所有操作,并仅返回最终的文本响应。 :::warning 在将 Hermes 嵌入到你自己的代码中时,始终设置 `quiet_mode=True`。否则,该 Agent 会打印 CLI 的旋转光标、进度指示器和其他终端输出,这将污染你应用程序的输出。 ::: --- ## 完整对话控制 {#full-conversation-control} 如需对对话有更多控制,可直接使用 `run_conversation()`。它返回一个包含完整响应、消息历史和元数据的字典: ```python agent = AIAgent( model="anthropic/claude-sonnet-4", quiet_mode=True, ) result = agent.run_conversation( user_message="Search for recent Python 3.13 features", task_id="my-task-1", ) print(result["final_response"]) print(f"Messages exchanged: {len(result['messages'])}") ``` 返回的字典包含: - **`final_response`** —— Agent 的最终文本回复 - **`messages`** —— 完整的消息历史(系统、用户、助手、工具调用) - **`task_id`** —— 用于虚拟机隔离的任务标识符 你还可以传入自定义系统消息,以覆盖该调用的临时系统提示: ```python result = agent.run_conversation( user_message="Explain quicksort", system_message="You are a computer science tutor. Use simple analogies.", ) ``` --- ## 配置工具 {#configuring-tools} 使用 `enabled_toolsets` 或 `disabled_toolsets` 控制 Agent 可访问的工具集: ```python # 仅启用网页tools(浏览、搜索) agent = AIAgent( model="anthropic/claude-sonnet-4", enabled_toolsets=["web"], quiet_mode=True, ) # 启用除终端访问之外的所有内容 agent = AIAgent( model="anthropic/claude-sonnet-4", disabled_toolsets=["terminal"], quiet_mode=True, ) ``` :::tip 当你希望 Agent 具备最小化、受限的配置时(例如,研究机器人仅允许网络搜索),请使用 `enabled_toolsets`。当你希望拥有大部分功能但需要限制特定工具(例如,在共享环境中禁用终端访问)时,请使用 `disabled_toolsets`。 ::: --- ## 多轮对话 {#multi-turn-conversations} 通过将消息历史传回,可在多轮对话中保持对话状态: ```python agent = AIAgent( model="anthropic/claude-sonnet-4", quiet_mode=True, ) # 第一回合 result1 = agent.run_conversation("My name is Alice") history = result1["messages"] # 第二回合 — agent 记得 context result2 = agent.run_conversation( "What's my name?", conversation_history=history, ) print(result2["final_response"]) # "Your name is Alice." ``` `conversation_history` 参数接受前一次结果中的 `messages` 列表。Agent 会内部复制该列表,因此你原始的列表不会被修改。 --- ## 保存对话轨迹 {#saving-trajectories} 启用轨迹保存功能,以 ShareGPT 格式捕获对话——这对于生成训练数据或调试非常有用: ```python agent = AIAgent( model="anthropic/claude-sonnet-4", save_trajectories=True, quiet_mode=True, ) agent.chat("Write a Python function to sort a list") # 以 ShareGPT 格式保存到 trajectory_samples.jsonl ``` 每次对话都会作为单行 JSONL 追加,便于从自动化运行中收集数据集。 --- ## 自定义系统提示 {#custom-system-prompts} 使用 `ephemeral_system_prompt` 设置自定义系统提示,以引导 Agent 行为,但该提示**不会**保存到轨迹文件中(从而保持你的训练数据干净): ```python agent = AIAgent( model="anthropic/claude-sonnet-4", ephemeral_system_prompt="You are a SQL expert. Only answer database questions.", quiet_mode=True, ) response = agent.chat("How do I write a JOIN query?") print(response) ``` 这非常适合构建专用 Agent——代码审查员、文档撰写器、SQL 助手等,全部使用相同的底层工具。 --- ## 批量处理 {#batch-processing} 对于并行运行多个提示,Hermes 提供了 `batch_runner.py`。它管理并发的 `AIAgent` 实例,并确保资源隔离: ```bash python batch_runner.py --input prompts.jsonl --output results.jsonl ``` 每个提示都会获得独立的 `task_id` 和隔离环境。如果你需要自定义批量逻辑,也可以直接使用 `AIAgent` 构建自己的方案: ```python import concurrent.futures from run_agent import AIAgent prompts = [ "Explain recursion", "What is a hash table?", "How does garbage collection work?", ] def process_prompt(prompt): # 每个任务创建一个新的 agent 以确保线程安全 agent = AIAgent( model="anthropic/claude-sonnet-4", quiet_mode=True, skip_memory=True, ) return agent.chat(prompt) with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor: results = list(executor.map(process_prompt, prompts)) for prompt, result in zip(prompts, results): print(f"Q: {prompt}\nA: {result}\n") ``` :::warning 请为每个线程或任务**创建一个新的 `AIAgent` 实例**。该 Agent 维护内部状态(对话历史、工具会话、迭代计数器),这些状态不支持线程共享。 ::: --- ## 集成示例 {#integration-examples} ### FastAPI 端点 {#fastapi-endpoint} ```python from fastapi import FastAPI from pydantic import BaseModel from run_agent import AIAgent app = FastAPI() class ChatRequest(BaseModel): message: str model: str = "anthropic/claude-sonnet-4" @app.post("/chat") async def chat(request: ChatRequest): agent = AIAgent( model=request.model, quiet_mode=True, skip_context_files=True, skip_memory=True, ) response = agent.chat(request.message) return {"response": response} ``` ### Discord 机器人 {#discord-bot} ```python import discord from run_agent import AIAgent client = discord.Client(intents=discord.Intents.default()) @client.event async def on_message(message): if message.author == client.user: return if message.content.startswith("!hermes "): query = message.content[8:] agent = AIAgent( model="anthropic/claude-sonnet-4", quiet_mode=True, skip_context_files=True, skip_memory=True, platform="discord", ) response = agent.chat(query) await message.channel.send(response[:2000]) client.run("YOUR_DISCORD_TOKEN") ``` ### CI/CD 流水线步骤 {#cicd-pipeline-step} ```python #!/usr/bin/env python3 """CI step: auto-review a PR diff.""" import subprocess from run_agent import AIAgent diff = subprocess.check_output(["git", "diff", "main...HEAD"]).decode() agent = AIAgent( model="anthropic/claude-sonnet-4", quiet_mode=True, skip_context_files=True, skip_memory=True, disabled_toolsets=["terminal", "browser"], ) review = agent.chat( f"Review this PR diff for bugs, security issues, and style problems:\n\n{diff}" ) print(review) ``` --- ## 关键构造函数参数 {#key-constructor-parameters} | 参数 | 类型 | 默认值 | 描述 | |------|------|--------|------| | `model` | `str` | `"anthropic/claude-opus-4.6"` | OpenRouter 格式的模型 | | `quiet_mode` | `bool` | `False` | 抑制 CLI 输出 | | `enabled_toolsets` | `List[str]` | `None` | 白名单特定工具集 | | `disabled_toolsets` | `List[str]` | `None` | 黑名单特定工具集 | | `save_trajectories` | `bool` | `False` | 将对话保存为 JSONL | | `ephemeral_system_prompt` | `str` | `None` | 自定义系统提示(不保存到轨迹) | | `max_iterations` | `int` | `90` | 每次对话的最大工具调用迭代次数 | | `skip_context_files` | `bool` | `False` | 跳过加载 AGENTS.md 文件 | | `skip_memory` | `bool` | `False` | 禁用持久记忆的读写 | | `api_key` | `str` | `None` | API 密钥(会回退到环境变量) | | `base_url` | `str` | `None` | 自定义 API 端点 URL | | `platform` | `str` | `None` | 平台提示(如 `"discord"`、`"telegram"` 等) | --- ## 重要说明 {#important-notes} :::tip - 如果不希望将工作目录中的 `AGENTS.md` 文件加载到系统提示中,请设置 **`skip_context_files=True`**。 - 若要阻止 Agent 读取或写入持久记忆,请设置 **`skip_memory=True`** —— 建议用于无状态 API 端点。 - `platform` 参数(例如 `"discord"`、`"telegram"`)会注入平台特定的格式化提示,使 Agent 能够调整其输出风格。 ::: :::warning - **线程安全性**:每个线程或任务应创建一个 `AIAgent` 实例。切勿在并发调用之间共享实例。 - **资源清理**:当对话结束时,Agent 会自动清理资源(终端会话、浏览器实例)。如果在长期运行的进程中运行,请确保每次对话都能正常完成。 - **迭代次数限制**:默认的 `max_iterations=90` 已经相当宽松。对于简单的问答用例,建议降低该值(例如设置为 `max_iterations=10`),以防止工具调用循环失控并控制成本。 ::: --- ### 使用 Nous Portal 运行 Hermes Agent - URL: https://hermesagent.org.cn/docs/guides/run-hermes-with-nous-portal - Path: guides/run-hermes-with-nous-portal.md - Category: guides - Description: 从订阅、OAuth 登录、切换模型、启用 Tool Gateway 到验证路由,完整跑通 Hermes Agent 与 Nous Portal。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/run-hermes-with-nous-portal.md - Translated At: 2026-05-30T10:05:00.000+08:00 - Headings: 准备工作 | 第一步:运行 setup | 第二步:开始对话 | 第三步:切换模型 | 远程服务器怎么办? | 排错建议 | 参考链接 # 使用 Nous Portal 运行 Hermes Agent {#run-hermes-with-nous-portal} 本教程带你从零跑通 [Nous Portal](/docs/integrations/nous-portal)。如果你只想少配 Key、尽快使用 Hermes,这是官方推荐路线。 ## 准备工作 {#prerequisites} 你需要: - 已安装 Hermes Agent; - 当前机器能打开浏览器,或能做 SSH 端口转发; - 大约 5 分钟。 你不需要单独准备 OpenAI、Anthropic、Firecrawl、FAL、Browser Use 等一堆账号。这正是 Portal 的意义。 ## 第一步:运行 setup {#setup} 运行: ```bash hermes setup --portal ``` Hermes 会引导你完成 OAuth 登录,并把 Nous Portal 写入配置。登录成功后,先检查状态: ```bash hermes portal status ``` 如果状态显示 provider 和 Tool Gateway 已连接,就可以进入下一步。 ## 第二步:开始对话 {#chat} 运行: ```bash hermes chat ``` 可以先问一个需要工具能力的问题,例如: ```text 请搜索 Hermes Agent 最新 release,并总结升级建议。 ``` 如果 Hermes 能调用网页搜索或提取工具,说明 Portal 和 Tool Gateway 基本跑通。 ## 第三步:切换模型 {#switch-models} Portal 提供多个模型。你可以在 Dashboard 中选择,也可以通过 Hermes 的模型配置界面切换。配置模型时建议遵循这个原则: - 主模型选择强推理、强工具调用模型; - 辅助模型选择快且便宜的模型; - 视觉、网页摘要等任务按能力单独配置。 更多说明见 [配置模型](/docs/user-guide/configuring-models)。 ## 远程服务器怎么办? {#ssh} 如果 Hermes 跑在远程服务器上,而 OAuth 需要本地浏览器,可以用 SSH 端口转发。简单来说,就是把远程回调端口映射到本地,让浏览器能完成登录回跳。 官方提供了独立的 OAuth over SSH 指南,本中文站后续会继续补齐该页面。 ## 排错建议 {#troubleshooting} 如果 setup 后不能正常使用,按顺序检查: 1. `hermes portal status` 是否显示登录成功; 2. 当前 profile 是否使用 Portal provider; 3. Dashboard 和 CLI 是否使用同一个 Hermes home; 4. 是否有旧环境变量覆盖了 provider; 5. 网络环境是否阻止 OAuth 回调或 Portal API。 不要一上来同时改很多配置。一次只改一个变量,更容易定位问题。 ## 参考链接 {#references} - [官方原文:Run Hermes Agent with Nous Portal](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/run-hermes-with-nous-portal.md) - [Nous Portal 集成](/docs/integrations/nous-portal) --- ### 在 Hermes Agent 中免费运行 Nemotron 3 Ultra - URL: https://hermesagent.org.cn/docs/guides/run-nemotron-3-ultra-free - Path: guides/run-nemotron-3-ultra-free.md - Category: guides - Description: 在 Nous Portal 上免费试用 NVIDIA Nemotron 3 Ultra(6 月 4 日至 18 日),Hermes Agent 提供首日支持 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/run-nemotron-3-ultra-free.md - Translated At: 2026-06-16T00:45:16.108Z - Headings: 选项 A — 桌面应用(推荐) | 1. 下载并安装 | 2. 连接 Nous Portal | 3. 选择免费的 Nemotron 3 Ultra 模型 | 4. 开始聊天 | 选项 B — 命令行 | 1. 安装 Hermes Agent | 2. 运行快速设置 | 3. 创建 Nous Portal 账户 | 4. 连接您的账户 | 5. 选择免费的 Nemotron 3 Ultra 模型 | 6. 开始聊天 # 在 Hermes Agent 中免费运行 Nemotron 3 Ultra {#run-nemotron-3-ultra-free-in-hermes-agent} Nous Research 已加入由领先 AI 实验室组成的 **Nemotron Coalition**,并与 **NVIDIA** 合作推进开放的前沿基础模型。为庆祝这一时刻,我们与 **Nebius** 合作,在 [Nous Portal](https://portal.nousresearch.com) 上免费提供 **Nemotron 3 Ultra**,为期两周(**6 月 4 日 – 6 月 18 日**)。请按照以下说明,今天就在您的 Hermes Agent 中试用该模型。 :::info 限时优惠 `nvidia/nemotron-3-ultra:free` 层级仅在 **6 月 4 日至 6 月 18 日** 期间可用。`:free` 标签是使其保持在不收费计划中的关键——请选择该确切变体。 ::: 选择适合您的安装方式。**桌面应用**最简单——无需终端。如果您习惯使用终端,**命令行**安装紧随其后。 ## 选项 A — 桌面应用(推荐) {#option-a-—-desktop-app-recommended} 最简单的路径:一键安装程序,配有引导式的点对点设置。无需终端。 ### 1. 下载并安装 {#1-download-and-install} [下载 Hermes Desktop 安装程序](https://hermes-agent.nousresearch.com/)(适用于 macOS 或 Windows),然后打开它。首次启动时,它会完成自身设置(通常不到一分钟)。 ### 2. 连接 Nous Portal {#2-connect-nous-portal} 当应用打开时,您将看到“让我们开始设置”屏幕。点击 **Nous Portal**(标记为 **Recommended**)。浏览器将打开——创建 [Nous Portal](https://portal.nousresearch.com) 账户(或登录),选择 **Free** 计划,并授权 Hermes。应用会自动连接。 ### 3. 选择免费的 Nemotron 3 Ultra 模型 {#3-pick-the-free-nemotron-3-ultra-model} 连接后,应用会显示 **Default model** 卡片。点击 **Change**,搜索 **nemotron 3 ultra**,并选择标记为 **Free tier** 的变体: ``` nvidia/nemotron-3-ultra:free ``` `:free` 标签是使其保持在不收费层级中的关键——请选择该变体。 ### 4. 开始聊天 {#4-start-chatting} 点击 **Start chatting**。就是这样——您正在免费与 Nemotron 3 Ultra 对话。 ## 选项 B — 命令行 {#option-b-—-command-line} 更喜欢使用终端? ### 1. 安装 Hermes Agent {#1-install-hermes-agent} 在 macOS/Linux/WSL2/Android 上,运行 ```bash curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash ``` 在 Windows 上,运行 ```powershell iex (irm https://hermes-agent.nousresearch.com/install.ps1) ``` 希望先审查?下载 [`install.sh`](https://hermes-agent.nousresearch.com/install.sh),检查它,然后运行它。 完成后,重新加载您的 shell: ```bash source ~/.bashrc # or source ~/.zshrc ``` ### 2. 运行快速设置 {#2-run-quick-setup} ```bash hermes setup ``` 选择 **Quick Setup**。Hermes 会打开一个浏览器标签页,等待您完成后续步骤。 ### 3. 创建 Nous Portal 账户 {#3-create-a-nous-portal-account} 在浏览器中,创建 [Nous Portal](https://portal.nousresearch.com) 账户(或登录)并选择 **Free** 计划。 ### 4. 连接您的账户 {#4-connect-your-account} 当提示将您的账户连接到 Hermes Agent 时,点击 **Connect**。链接成功后,您将看到确认信息。 ### 5. 选择免费的 Nemotron 3 Ultra 模型 {#5-select-the-free-nemotron-3-ultra-model} 返回终端。从模型列表中,选择: ``` nvidia/nemotron-3-ultra:free ``` `:free` 标签是使其保持在不收费层级中的关键,因此请确保选择该变体。 ### 6. 开始聊天 {#6-start-chatting} 完成剩余的快速设置提示,然后运行: ```bash hermes ``` 就是这样——您正在免费与 Nemotron 3 Ultra 对话。 ## 稍后切换 {#switching-to-it-later} 已经设置了其他模型? - **桌面应用:** 打开模型选择器,搜索 **nemotron 3 ultra**,并选择 **Free tier** 变体。 - **CLI / TUI:** 在会话中随时使用 `/model nvidia/nemotron-3-ultra:free` 进行切换,或运行 `/model` 打开选择器并从列表中选择。 ## 故障排除 {#troubleshooting} - **在列表中看不到模型?** 确保您已完成 Nous Portal 连接,并且使用的是 **Free** 计划。在 CLI 中,`hermes portal info` 可确认您已登录并通过 Nous 路由。 - **选错了变体?** 重新选择 `nvidia/nemotron-3-ultra:free` ——必须包含 `:free` 后缀才能保持在不收费层级。 - **浏览器未打开 / 您在远程主机上(CLI)?** 请参阅 [OAuth over SSH / Remote Hosts](/docs/guides/oauth-over-ssh) 了解端口转发和手动粘贴的解决方法。 ## 另见 {#see-also} - **[Desktop App](/docs/user-guide/desktop)** —— 原生一键应用(macOS、Windows、Linux) - **[Run Hermes Agent with Nous Portal](/docs/guides/run-hermes-with-nous-portal)** —— 完整的 Portal 演练:模型、Tool Gateway 和验证 - **[Nous Portal integration](/docs/integrations/nous-portal)** —— 订阅内容详情 - **[Quickstart](/docs/getting-started/quickstart)** —— 5 分钟内从安装到聊天 --- ### 教程:团队 Telegram 助手 - URL: https://hermesagent.org.cn/docs/guides/team-telegram-assistant - Path: guides/team-telegram-assistant.md - Category: guides - Description: 逐步指南:设置一个团队可使用的 Telegram 机器人,用于代码帮助、研究、系统管理等 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/team-telegram-assistant.md - Translated At: 2026-04-11T03:28:57.011Z - Headings: 我们要构建什么 | 先决条件 | 第一步:创建 Telegram 机器人 | 第二步:配置网关 | 选项 A:交互式设置(推荐) | 选项 B:手动配置 | 查找你的用户 ID | 第三步:启动网关 | 快速测试 | 生产环境:作为服务安装 | 验证是否正在运行 | 第四步:设置团队访问权限 # 设置团队 Telegram 助手 {#set-up-a-team-telegram-assistant} 本教程将指导你如何设置一个由 Hermes Agent 驱动的 Telegram 机器人,供团队成员多人使用。完成之后,你的团队将拥有一位共享的 AI 助手,可以通过消息向其寻求代码、研究、系统管理及其他任务的帮助——并配有基于用户的授权机制,确保安全。 ## 我们要构建什么 {#what-were-building} 一个 Telegram 机器人,具备以下功能: - **任何已授权的团队成员** 都可以通过私信(DM)向其求助——代码审查、研究、Shell 命令、调试等 - **在你的服务器上运行**,拥有完整的工具访问权限——终端、文件编辑、网络搜索、代码执行 - **基于用户的独立会话** —— 每位用户都拥有自己的对话上下文 - **默认安全** —— 仅允许经过批准的用户交互,支持两种授权方式 - **定时任务** —— 每日站会、健康检查和提醒将自动发送至团队频道 --- ## 先决条件 {#prerequisites} 开始之前,请确保你已具备以下条件: - **已在服务器或 VPS 上安装 Hermes Agent**(不要在你的笔记本电脑上运行——机器人需要持续运行)。如果尚未安装,请参考 [安装指南](/docs/getting-started/installation)。 - **一个 Telegram 账号**(用于你自己,即机器人所有者) - **已配置 LLM 提供商** —— 至少需要一个 OpenAI、Anthropic 或其他支持的提供商的 API 密钥,存放在 `~/.hermes/.env` 中 :::tip 每月 5 美元的 VPS 足够运行网关。Hermes 本身非常轻量——费用主要来自远程的 LLM API 调用。 ::: --- ## 第一步:创建 Telegram 机器人 {#step-1-create-a-telegram-bot} 每个 Telegram 机器人都始于 **@BotFather** —— Telegram 官方的机器人创建工具。 1. **打开 Telegram**,搜索 `@BotFather`,或访问 [t.me/BotFather](https://t.me/BotFather) 2. **发送 `/newbot`** —— BotFather 会询问你两个问题: - **显示名称** —— 用户看到的名称(例如:`Team Hermes Assistant`) - **用户名** —— 必须以 `bot` 结尾(例如:`myteam_hermes_bot`) 3. **复制机器人令牌** —— BotFather 会回复类似内容: ``` Use this token to access the HTTP API: 7123456789:AAH1bGciOiJSUzI1NiIsInR5cCI6Ikp... ``` 请保存此令牌——你将在下一步中用到。 4. **设置描述**(可选但推荐): ``` /setdescription ``` 选择你的机器人,然后输入类似内容: ``` Team AI assistant powered by Hermes Agent. DM me for help with code, research, debugging, and more. ``` 5. **设置机器人命令**(可选——为用户提供命令菜单): ``` /setcommands ``` 选择你的机器人,然后粘贴: ``` new - Start a fresh conversation model - Show or change the AI model status - Show session info help - Show available commands stop - Stop the current task ``` :::warning 请务必保密你的机器人令牌。任何持有令牌的人都能控制该机器人。如果令牌泄露,请在 BotFather 中使用 `/revoke` 生成新令牌。 ::: --- ## 第二步:配置网关 {#step-2-configure-the-gateway} 你有两种选择:交互式设置向导(推荐)或手动配置。 ### 选项 A:交互式设置(推荐) {#option-a-interactive-setup-recommended} ```bash hermes gateway setup ``` 该向导将引导你完成所有步骤,使用方向键进行选择。选择 **Telegram**,粘贴你的机器人令牌,并在提示时输入你的用户 ID。 ### 选项 B:手动配置 {#option-b-manual-configuration} 将以下内容添加到 `~/.hermes/.env` 文件中: ```bash # 来自 BotFather 的 Telegram 机器人 token TELEGRAM_BOT_TOKEN=7123456789:AAH1bGciOiJSUzI1NiIsInR5cCI6Ikp... # 您的 Telegram 用户 ID(数字) TELEGRAM_ALLOWED_USERS=123456789 ``` ### 查找你的用户 ID {#finding-your-user-id} 你的 Telegram 用户 ID 是一个数字(不是你的用户名)。如何查找: 1. 在 Telegram 中向 [@userinfobot](https://t.me/userinfobot) 发送消息 2. 它会立即回复你的数字用户 ID 3. 将该数字复制到 `TELEGRAM_ALLOWED_USERS` 中 :::info Telegram 用户 ID 是永久性的数字,如 `123456789`。它们与你的 `@username` 不同,后者可能更改。始终使用数字 ID 作为白名单。 ::: --- ## 第三步:启动网关 {#step-3-start-the-gateway} ### 快速测试 {#quick-test} 首先在前台运行网关,以确保一切正常: ```bash hermes gateway ``` 你应该看到类似输出: ``` [Gateway] Starting Hermes Gateway... [Gateway] Telegram adapter connected [Gateway] Cron scheduler started (tick every 60s) ``` 打开 Telegram,找到你的机器人并发送一条消息。如果它回复了,说明一切正常。按 `Ctrl+C` 停止运行。 ### 生产环境:作为服务安装 {#production-install-as-a-service} 为了实现持久化部署,确保重启后仍能运行: ```bash hermes gateway install sudo hermes gateway install --system # 仅限 Linux:启动时系统服务 ``` 这将创建一个后台服务:默认在 Linux 上为用户级 **systemd** 服务,在 macOS 上为 **launchd** 服务,或在你传递 `--system` 参数时为开机启动的 Linux 系统服务。 ```bash # Linux — 管理默认用户服务 hermes gateway start hermes gateway stop hermes gateway status # 查看实时日志 journalctl --user -u hermes-gateway -f # SSH 注销后继续运行 sudo loginctl enable-linger $USER # Linux 服务器 — 显式系统服务命令 sudo hermes gateway start --system sudo hermes gateway status --system journalctl -u hermes-gateway -f ``` ```bash # macOS — 管理服务 hermes gateway start hermes gateway stop tail -f ~/.hermes/logs/gateway.log ``` :::tip macOS PATH launchd plist 在安装时捕获了你的 shell PATH,因此网关的子进程可以找到 Node.js、ffmpeg 等工具。如果你之后安装了新工具,请重新运行 `hermes gateway install` 以更新 plist。 ::: ### 验证是否正在运行 {#verify-its-running} ```bash hermes gateway status ``` 然后向你的 Telegram 机器人发送一条测试消息。你应该在几秒内收到回复。 --- ## 第四步:设置团队访问权限 {#step-4-set-up-team-access} 现在让我们为团队成员设置访问权限。有两种方法。 ### 方法 A:静态白名单 {#approach-a-static-allowlist} 收集每位团队成员的 Telegram 用户 ID(让他们向 [@userinfobot](https://t.me/userinfobot) 发送消息),然后以逗号分隔的形式添加到配置中: ```bash # 在“0”中 TELEGRAM_ALLOWED_USERS=123456789,987654321,555555555 ``` 修改后重启网关: ```bash hermes gateway stop && hermes gateway start ``` ### 方法 B:私信配对(推荐用于团队) {#approach-b-dm-pairing-recommended-for-teams} DM 配对更加灵活——你无需提前收集用户 ID。其工作原理如下: 1. **团队成员向机器人发送私信** —— 由于他们不在白名单中,机器人会回复一个一次性配对码: ``` 🔐 Pairing code: XKGH5N7P Send this code to the bot owner for approval. ``` 2. **同事将代码发送给你**(通过任意渠道——Slack、邮件、当面) 3. **你在服务器上批准该代码**: ```bash hermes pairing approve telegram XKGH5N7P ``` 4. **他们即可接入**——机器人会立即开始响应他们的消息 **管理配对用户:** ```bash # 查看所有待处理和已批准的用户 hermes pairing list # 撤销某人的访问权限 hermes pairing revoke telegram 987654321 # 清除过期的待处理代码 hermes pairing clear-pending ``` :::tip 私聊配对非常适合团队使用,因为添加新用户时无需重启网关。批准立即生效。 ::: ### 安全注意事项 {#security-considerations} - **切勿在具有终端访问权限的机器人上设置 `GATEWAY_ALLOW_ALL_USERS=true`** ——任何找到你机器人的人都可能在你的服务器上运行命令 - 配对码在 **1 小时后过期**,并使用加密随机性生成 - 速率限制可防止暴力破解攻击:每用户每 10 分钟最多 1 次请求,每个平台最多 3 个待处理的配对码 - 连续 5 次批准失败后,平台将进入 1 小时锁定状态 - 所有配对数据均以 `chmod 0600` 权限存储 --- ## 第 5 步:配置机器人 {#step-5-configure-the-bot} ### 设置主频道 {#set-a-home-channel} **主频道**是机器人发送定时任务结果和主动消息的频道。如果没有设置主频道,计划任务将无处发送输出。 **选项 1:** 在机器人是成员的任意 Telegram 群组或聊天中使用 `/sethome` 命令。 **选项 2:** 手动在 `~/.hermes/.env` 中设置: ```bash TELEGRAM_HOME_CHANNEL=-1001234567890 TELEGRAM_HOME_CHANNEL_NAME="Team Updates" ``` 要查找频道 ID,请将 [@userinfobot](https://t.me/userinfobot) 添加到群组中——它会报告该群组的聊天 ID。 ### 配置工具执行状态显示 {#configure-tool-progress-display} 控制机器人在使用工具时显示的详细程度。在 `~/.hermes/config.yaml` 中: ```yaml display: tool_progress: new # 关闭 |新 |全部 |冗长的 ``` | 模式 | 你看到的内容 | |------|-------------| | `off` | 仅显示简洁响应——无工具活动信息 | | `new` | 每次新工具调用显示简要状态(推荐用于消息交互) | | `all` | 显示每次工具调用的详细信息 | | `verbose` | 显示完整工具输出,包括命令执行结果 | 用户也可以通过在聊天中使用 `/verbose` 命令来按会话更改此设置。 ### 使用 SOUL.md 设置个性 {#set-up-a-personality-with-soulmd} 通过编辑 `~/.hermes/SOUL.md` 来自定义机器人的沟通方式: 完整指南请参见 [使用 SOUL.md 与 Hermes](/docs/guides/use-soul-with-hermes)。 ```markdown # 灵魂 You are a helpful team assistant. Be concise and technical. Use code blocks for any code. Skip pleasantries — the team values directness. When debugging, always ask for error logs before guessing at solutions. ``` ### 添加项目上下文 {#add-project-context} 如果你的团队专注于特定项目,请创建上下文文件,让机器人了解你的技术栈: ```markdown # 团队 Context - We use Python 3.12 with FastAPI and SQLAlchemy - Frontend is React with TypeScript - CI/CD runs on GitHub Actions - Production deploys to AWS ECS - Always suggest writing tests for new code ``` :::info 上下文文件会被注入到每个会话的系统提示中。请保持简洁——每个字符都会计入你的 token 预算。 ::: --- ## 第 6 步:设置定时任务 {#step-6-set-up-scheduled-tasks} 在网关运行后,你可以安排重复执行的任务,并将结果发送到团队频道。 ### 每日站会摘要 {#daily-standup-summary} 在 Telegram 中向机器人发送消息: ``` Every weekday at 9am, check the GitHub repository at github.com/myorg/myproject for: 1. Pull requests opened/merged in the last 24 hours 2. Issues created or closed 3. Any CI/CD failures on the main branch Format as a brief standup-style summary. ``` 该 Agent 会自动创建一个定时任务,并将结果发送到你提问的聊天(或主频道)。 ### 服务器健康检查 {#server-health-check} ``` Every 6 hours, check disk usage with 'df -h', memory with 'free -h', and Docker container status with 'docker ps'. Report anything unusual — partitions above 80%, containers that have restarted, or high memory usage. ``` ### 管理定时任务 {#managing-scheduled-tasks} ```bash # 来自CLI hermes cron list # 查看所有预定的作业 hermes cron status # 检查调度程序是否正在运行 # 来自 Telegram 聊天 /cron list # 查看职位 /cron remove # 删除职位 ``` :::warning 定时任务提示在完全独立的新会话中运行,不保留之前对话的记忆。请确保每个提示中包含**所有**Agent 所需的上下文——包括文件路径、URL、服务器地址和清晰的指令。 ::: --- ## 生产环境建议 {#production-tips} ### 使用 Docker 提升安全性 {#use-docker-for-safety} 在共享团队机器人中,使用 Docker 作为终端后端,使 Agent 命令在容器中运行,而非在主机上: ```bash # 在“0”中 TERMINAL_BACKEND=docker TERMINAL_DOCKER_IMAGE=nikolaik/python-nodejs:python3.11-nodejs20 ``` 或在 `~/.hermes/config.yaml` 中设置: ```yaml terminal: backend: docker container_cpu: 1 container_memory: 5120 container_persistent: true ``` 这样即使有人要求机器人运行破坏性命令,你的主机系统也受到保护。 ### 监控网关 {#monitor-the-gateway} ```bash # 检查 Gateway 是否正在运行 hermes gateway status # 观看实时日志(Linux) journalctl --user -u hermes-gateway -f # 观看实时日志(macOS) tail -f ~/.hermes/logs/gateway.log ``` ### 保持 Hermes 更新 {#keep-hermes-updated} 从 Telegram 向机器人发送 `/update` 命令——它将拉取最新版本并重启。或从服务器执行: ```bash hermes update hermes gateway stop && hermes gateway start ``` ### 日志位置 {#log-locations} | 内容 | 位置 | |------|------| | 网关日志 | `journalctl --user -u hermes-gateway`(Linux)或 `~/.hermes/logs/gateway.log`(macOS) | | 定时任务输出 | `~/.hermes/cron/output/{job_id}/{timestamp}.md` | | 定时任务定义 | `~/.hermes/cron/jobs.json` | | 配对数据 | `~/.hermes/pairing/` | | 会话历史 | `~/.hermes/sessions/` | --- ## 进阶使用 {#going-further} 你已经成功搭建了一个团队用的 Telegram 助手。以下是一些后续步骤: - **[安全指南](/docs/user-guide/security)** —— 深入了解授权、容器隔离和命令审批 - **[消息网关](/docs/user-guide/messaging)** —— 网关架构、会话管理及聊天命令的完整参考 - **[Telegram 设置](/docs/user-guide/messaging/telegram)** —— 包括语音消息和文本转语音(TTS)的平台特定细节 - **[定时任务](/docs/user-guide/features/cron)** —— 高级定时调度,支持交付选项和 cron 表达式 - **[上下文文件](/docs/user-guide/features/context-files)** —— AGENTS.md、SOUL.md 和 .cursorrules 用于项目知识管理 - **[个性设置](/docs/user-guide/features/personality)** —— 内置个性预设和自定义人格定义 - **添加更多平台**——同一网关可同时运行 [Discord](/docs/user-guide/messaging/discord)、[Slack](/docs/user-guide/messaging/slack) 和 [WhatsApp](/docs/user-guide/messaging/whatsapp) *有疑问或问题?在 GitHub 上打开一个议题 —— 欢迎贡献。* --- ### 技巧与最佳实践 - URL: https://hermesagent.org.cn/docs/guides/tips - Path: guides/tips.md - Category: guides - Description: 使用 Hermes Agent 的实用建议 —— 提示技巧、CLI 快捷键、上下文文件、记忆功能、成本优化与安全防护 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/tips.md - Translated At: 2026-04-11T03:29:16.320Z - Headings: 获得最佳结果 | 明确表达你的需求 | 提前提供上下文 | 使用上下文文件处理重复指令 | 让 Agent 使用其工具 | 使用技能处理复杂工作流 | CLI 高级用户技巧 | 多行输入 | 粘贴检测 | 中断与重定向 | 使用 c 恢复会话 | 剪贴板图像粘贴 # 使用技巧与最佳实践 {#tips--best-practices} 一份快速见效的实用技巧合集,帮助你立即更高效地使用 Hermes Agent。每个部分聚焦不同方面——浏览标题并跳转到你关心的内容。 --- ## 获得最佳结果 {#getting-the-best-results} ### 明确表达你的需求 {#be-specific-about-what-you-want} 模糊的提示会产生模糊的结果。不要说“修复代码”,而应具体说明:“修复 `api/handlers.py` 第 47 行的 TypeError —— `process_request()` 函数从 `parse_body()` 接收到 `None`。” 提供的上下文越多,所需迭代次数就越少。 ### 提前提供上下文 {#provide-context-up-front} 在请求开头就加载相关细节:文件路径、错误信息、预期行为。一条精心设计的消息胜过三轮澄清。直接粘贴错误堆栈跟踪——Agent 可以解析它们。 ### 使用上下文文件处理重复指令 {#use-context-files-for-recurring-instructions} 如果你发现自己反复重复相同指令(如“使用制表符而非空格”、“我们使用 pytest”、“API 地址是 `/api/v2`”),请将这些内容放入 `AGENTS.md` 文件中。Agent 会在每次会话中自动读取该文件——设置完成后无需额外操作。 ### 让 Agent 使用其工具 {#let-the-agent-use-its-tools} 不要试图手动引导每一步。说“查找并修复失败的测试”而不是“打开 `tests/test_foo.py`,查看第 42 行,然后……”。Agent 具备文件搜索、终端访问和代码执行能力——让它自主探索并迭代。 ### 使用技能处理复杂工作流 {#use-skills-for-complex-workflows} 在编写冗长提示说明如何完成某项任务之前,请先检查是否已有对应技能。输入 `/skills` 浏览可用技能,或直接调用某个技能,如 `/axolotl` 或 `/github-pr-workflow`。 ## CLI 高级用户技巧 {#cli-power-user-tips} ### 多行输入 {#multi-line-input} 按 **Alt+Enter**(或 **Ctrl+J**)可插入换行而不发送消息。这让你能在按下 Enter 发送前,组合多行提示、粘贴代码块或构建复杂请求。 ### 粘贴检测 {#paste-detection} CLI 会自动检测多行粘贴。直接粘贴代码块或错误堆栈跟踪即可——不会将每一行作为单独消息发送。粘贴内容会被缓冲,并作为一条消息整体发送。 ### 中断与重定向 {#interrupt-and-redirect} 按一次 **Ctrl+C** 可中断 Agent 的响应。之后你可以输入新消息来重定向它。在 2 秒内连续按两次 **Ctrl+C** 可强制退出。当 Agent 开始走错方向时,此功能极为有用。 ### 使用 `-c` 恢复会话 {#resume-sessions-with--c} 忘记上次会话的内容了?运行 `hermes -c` 可以恢复到你离开时的完全状态,完整会话历史将被还原。你也可以通过标题恢复:`hermes -r "my research project"`。 ### 剪贴板图像粘贴 {#clipboard-image-paste} 按 **Ctrl+V** 可直接将剪贴板中的图像粘贴到聊天中。Agent 通过视觉能力分析截图、图表、错误弹窗或 UI 原型——无需先保存为文件。 ### 斜杠命令自动补全 {#slash-command-autocomplete} 输入 `/` 后按 **Tab** 可查看所有可用命令。这包括内置命令(如 `/compress`、`/model`、`/title`)以及所有已安装的技能。你无需记忆任何内容——Tab 补全会帮你搞定。 :::tip 使用 `/verbose` 可循环切换工具输出显示模式:**off → new → all → verbose**。“all” 模式适合观察 Agent 的操作过程;“off” 模式则最简洁,适用于简单问答。 ::: ## 上下文文件 {#context-files} ### AGENTS.md:你的项目的“大脑” {#agentsmd-your-projects-brain} 在项目根目录创建一个 `AGENTS.md` 文件,包含架构决策、编码规范和项目特定指令。该文件会在每次会话中自动注入,因此 Agent 始终了解你的项目规则。 ```markdown # 项目上下文 - This is a FastAPI backend with SQLAlchemy ORM - Always use async/await for database operations - Tests go in tests/ and use pytest-asyncio - Never commit .env files ``` ### SOUL.md:自定义个性 {#soulmd-customize-personality} 希望 Hermes 拥有稳定的默认语气?请编辑 `~/.hermes/SOUL.md`(或如果你使用自定义 Hermes 主目录,则为 `$HERMES_HOME/SOUL.md`)。Hermes 现在会自动创建一个初始 SOUL,并将这个全局文件作为 Hermes 实例的默认个性配置来源。 完整教程请参见 [使用 SOUL.md 与 Hermes](/docs/guides/use-soul-with-hermes)。 ```markdown # 灵魂 You are a senior backend engineer. Be terse and direct. Skip explanations unless asked. Prefer one-liners over verbose solutions. Always consider error handling and edge cases. ``` 使用 `SOUL.md` 保存持久个性;使用 `AGENTS.md` 存储项目特定指令。 ### .cursorrules 兼容性 {#cursorrules-compatibility} 如果你已有 `.cursorrules` 或 `.cursor/rules/*.mdc` 文件?Hermes 也能读取它们。无需重复定义编码规范——它们会自动从工作目录加载。 ### 发现机制 {#discovery} Hermes 在会话开始时会从当前工作目录加载顶层的 `AGENTS.md`。子目录中的 `AGENTS.md` 文件会在工具调用期间通过 `subdirectory_hints.py` 懒加载,并注入到工具结果中——它们不会提前加载到系统提示中。 :::tip 保持上下文文件简洁聚焦。每个字符都会计入你的 token 预算,因为它们会被注入到每一条消息中。 ::: ## 记忆与技能 {#memory--skills} ### 记忆 vs. 技能:该放哪里? {#memory-vs-skills-what-goes-where} **记忆**用于存储事实:你的环境、偏好、项目位置,以及 Agent 对你了解的各类信息。**技能**用于流程:多步骤工作流、工具特定指令和可复用的“配方”。用记忆记录“是什么”,用技能记录“怎么做”。 ### 何时创建技能 {#when-to-create-skills} 如果你发现某个任务需要 5 步以上,并且你可能会再次执行,就让 Agent 为它创建一个技能。例如,输入“将你刚才的操作保存为名为 `deploy-staging` 的技能”。下次只需输入 `/deploy-staging`,Agent 就会加载完整的操作流程。 ### 管理内存容量 {#managing-memory-capacity} 内存是故意受限的(MEMORY.md 约 2,200 字符,USER.md 约 1,375 字符)。当内存满时,Agent 会自动合并条目。你可以通过输入“清理你的记忆”或“替换旧的 Python 3.9 笔记——我们现在用的是 3.12”来协助。 ### 让 Agent 记住 {#let-the-agent-remember} 在一次高效会话结束后,输入“记住这次的内容以便下次使用”,Agent 将保存关键收获。你也可以更具体地说明:“将我们的 CI 使用 GitHub Actions 和 `deploy.yml` 工作流的信息保存到记忆中。” :::warning 记忆是一个冻结的快照——会话期间所做的更改不会立即反映在系统提示中,直到下一次会话开始才会生效。Agent 会立即写入磁盘,但提示缓存不会在会话中被刷新。 ::: ## 性能与成本 {#performance--cost} ### 不要破坏提示缓存 {#dont-break-the-prompt-cache} 大多数大语言模型(LLM)提供商会缓存系统提示前缀。如果你保持系统提示稳定(相同的上下文文件、相同记忆),会话中的后续消息将获得**缓存命中**,成本显著降低。避免在会话中更改模型或系统提示。 ### 在达到限制前使用 /compress {#use-compress-before-hitting-limits} 长时间会话会累积大量 token。当你注意到响应变慢或被截断时,运行 `/compress`。它会总结对话历史,在大幅减少 token 数量的同时保留关键上下文。使用 `/usage` 检查当前状态。 ### 委托以实现并行工作 {#delegate-for-parallel-work} 需要同时研究三个主题?让 Agent 使用 `delegate_task` 并行执行子任务。每个子 Agent 独立运行,拥有自己的上下文,最终只返回摘要——极大降低主对话的 token 使用量。 ### 使用 execute_code 执行批量操作 {#use-execute_code-for-batch-operations} 不要逐个运行终端命令,而是让 Agent 编写一个脚本一次性完成所有操作。“写一个 Python 脚本将所有 `.jpeg` 文件重命名为 `.jpg` 并运行它”比逐个重命名文件更高效且成本更低。 ### 选择合适的模型 {#choose-the-right-model} 使用 `/model` 在会话中切换模型。对于复杂推理和架构决策,使用前沿模型(Claude Sonnet/Opus、GPT-4o)。对于简单任务(如格式化、重命名或样板生成),切换到更快的模型。 :::tip 定期运行 `/usage` 查看你的 token 消耗情况。运行 `/insights` 获取过去 30 天使用模式的更全面视图。 ::: ## 消息提示 {#messaging-tips} ### 设置主频道 {#set-a-home-channel} 在你偏好的 Telegram 或 Discord 频道中使用 `/sethome`,将其设为主频道。定时任务和计划任务的输出将发送至此。若未设置,Agent 将无处发送主动消息。 ### 使用 /title 组织会话 {#use-title-to-organize-sessions} 使用 `/title auth-refactor` 或 `/title research-llm-quantization` 为会话命名。命名会话可通过 `hermes sessions list` 轻松查找,并通过 `hermes -r "auth-refactor"` 恢复。未命名会话会堆积,难以区分。 ### 私信配对实现团队访问 {#dm-pairing-for-team-access} 无需手动收集用户 ID 添加白名单,启用私信配对功能。当同事向机器人发送私信时,他们会收到一个一次性配对码。你通过 `hermes pairing approve telegram XKGH5N7P` 批准即可——简单且安全。 ### 工具进度显示模式 {#tool-progress-display-modes} 使用 `/verbose` 控制你看到的工具活动程度。在消息平台中,通常越少越好——保持“new”模式,仅显示新的工具调用。在 CLI 中,“all” 模式可提供 Agent 执行全过程的实时视图。 :::tip 在消息平台中,会话会在空闲一段时间后自动重置(默认:24 小时)或每天凌晨 4 点重置。如需更长会话,可在 `~/.hermes/config.yaml` 中按平台调整。 ::: ## 安全 {#security} ### 使用 Docker 处理不受信任的代码 {#use-docker-for-untrusted-code} 在处理不受信任的仓库或运行陌生代码时,使用 Docker 或 Daytona 作为终端后端。在 `.env` 文件中设置 `TERMINAL_BACKEND=docker`。容器内的破坏性命令无法危害你的主机系统。 ```bash # 写在你的 `.env` 中: TERMINAL_BACKEND=docker TERMINAL_DOCKER_IMAGE=hermes-sandbox:latest ``` ### 避免 Windows 编码陷阱 {#avoid-windows-encoding-pitfalls} 在 Windows 上,某些默认编码(如 `cp125x`)无法表示所有 Unicode 字符,这可能导致在测试或脚本中写入文件时出现 `UnicodeEncodeError`。 - 优先显式使用 UTF-8 编码打开文件: ```python with open("results.txt", "w", encoding="utf-8") as f: f.write("✓ All good\n") ``` - 在 PowerShell 中,你还可以将当前会话切换为 UTF-8,以确保控制台和原生命令输出使用 UTF-8: ```powershell $OutputEncoding = [Console]::OutputEncoding = [Text.UTF8Encoding]::new($false) ``` 这可使 PowerShell 及其子进程始终使用 UTF-8,有助于避免仅在 Windows 上出现的失败。 ### 选择“始终”前仔细审查 {#review-before-choosing-always} 当 Agent 触发危险命令审批(如 `rm -rf`、`DROP TABLE` 等)时,你会看到四个选项:**一次**、**会话**、**始终**、**拒绝**。选择“始终”前务必仔细考虑——这将永久允许该模式。建议先使用“会话”模式,直到你感到安心。 ### 命令审批是你的安全网 {#command-approval-is-your-safety-net} Hermes 在执行前会将每个命令与一个精心筛选的危险模式列表进行比对。这包括递归删除、SQL 删除操作、将 curl 的输出直接管道传递给 shell 等行为。请勿在生产环境中禁用此功能——它存在是有充分理由的。 :::warning 当在容器后端(Docker、Singularity、Modal、Daytona)中运行时,危险命令检查将被**跳过**,因为容器本身是安全边界。请确保您的容器镜像已正确锁定。 ::: ### 为消息机器人使用白名单 {#use-allowlists-for-messaging-bots} 切勿在具有终端访问权限的机器人上设置 `GATEWAY_ALLOW_ALL_USERS=true`。始终使用平台特定的白名单(如 `TELEGRAM_ALLOWED_USERS`、`DISCORD_ALLOWED_USERS`)或私信配对方式来控制谁可以与您的 Agent 交互。 ```bash # 建议:每个平台明确允许名单 TELEGRAM_ALLOWED_USERS=123456789,987654321 DISCORD_ALLOWED_USERS=123456789012345678 # 或者使用跨平台白名单 GATEWAY_ALLOWED_USERS=123456789,987654321 ``` --- *有建议想添加到本页?打开一个 issue 或 PR——欢迎社区贡献。* --- ### 使用 MCP 与 Hermes - URL: https://hermesagent.org.cn/docs/guides/use-mcp-with-hermes - Path: guides/use-mcp-with-hermes.md - Category: guides - Description: 连接 MCP 服务器到 Hermes Agent 的实用指南,过滤其工具,并在实际工作流中安全使用 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/use-mcp-with-hermes.md - Translated At: 2026-04-11T03:29:22.014Z - Headings: 何时应使用 MCP? | 思维模型 | 第一步:安装 MCP 支持 | 第二步:先添加一个服务器 | 第三步:验证 MCP 已加载 | 第四步:立即开始过滤 | 示例:仅允许所需内容(白名单) | 示例:屏蔽危险操作(黑名单) | 示例:同时禁用实用封装器 | 过滤实际影响什么? | 你可能会看到的实用封装器 | 常见模式 # 使用 MCP 与 Hermes {#use-mcp-with-hermes} 本指南展示了如何在日常工作中实际使用 MCP 与 Hermes Agent。 如果功能页面解释了 MCP 是什么,那么本指南则关注如何快速且安全地从中获取价值。 ## 何时应使用 MCP? {#when-should-you-use-mcp} 在以下情况使用 MCP: - 已存在以 MCP 形式提供的工具,且你不想构建原生的 Hermes 工具 - 希望 Hermes 通过干净的 RPC 层与本地或远程系统交互 - 希望按服务器进行细粒度的暴露控制 - 希望将 Hermes 连接到内部 API、数据库或公司系统,而无需修改 Hermes 核心 不要使用 MCP 的情况包括: - 内置的 Hermes 工具已能很好地完成任务 - 服务器暴露了大量危险工具,而你尚未准备好进行过滤 - 你只需要一个非常狭窄的集成,原生工具会更简单且更安全 ## 思维模型 {#mental-model} 将 MCP 视为一个适配层: - Hermes 保持为 Agent - MCP 服务器提供工具 - Hermes 在启动或重新加载时发现这些工具 - 模型可像使用普通工具一样使用它们 - 你控制每个服务器可见的部分 最后一点至关重要。良好的 MCP 使用方式不仅仅是“连接一切”,而是“连接正确的内容,并且只暴露最小但够用的能力范围”。 ## 第一步:安装 MCP 支持 {#step-1-install-mcp-support} 如果你通过标准安装脚本安装了 Hermes,MCP 支持已包含在内(安装程序会运行 `uv pip install -e ".[all]"`)。 如果你未使用额外组件安装,需要单独添加 MCP: ```bash cd ~/.hermes/hermes-agent uv pip install -e ".[mcp]" ``` 对于基于 npm 的服务器,请确保 Node.js 和 `npx` 可用。 对于许多 Python MCP 服务器,`uvx` 是一个不错的默认选择。 ## 第二步:先添加一个服务器 {#step-2-add-one-server-first} 从一个单一、安全的服务器开始。 示例:仅对一个项目目录进行文件系统访问。 ```yaml mcp_servers: project_fs: command: "npx" args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/my-project"] ``` 然后启动 Hermes: ```bash hermes chat ``` 现在提出一个具体问题: ```text Inspect this project and summarize the repo layout. ``` ## 第三步:验证 MCP 已加载 {#step-3-verify-mcp-loaded} 你可以通过以下几种方式验证 MCP: - 配置后,Hermes 启动横幅/状态应显示 MCP 集成 - 询问 Hermes 它有哪些可用工具 - 在配置更改后使用 `/reload-mcp` - 检查日志以确认服务器是否连接失败 一个实用的测试提示: ```text Tell me which MCP-backed tools are available right now. ``` ## 第四步:立即开始过滤 {#step-4-start-filtering-immediately} 如果服务器暴露了大量工具,请不要等到以后再处理。 ### 示例:仅允许所需内容(白名单) {#example-whitelist-only-what-you-want} ```yaml mcp_servers: github: command: "npx" args: ["-y", "@modelcontextprotocol/server-github"] env: GITHUB_PERSONAL_ACCESS_TOKEN: "***" tools: include: [list_issues, create_issue, search_code] ``` 这通常是敏感系统的最佳默认策略。 ### 示例:屏蔽危险操作(黑名单) {#example-blacklist-dangerous-actions} ```yaml mcp_servers: stripe: url: "https://mcp.stripe.com" headers: Authorization: "Bearer ***" tools: exclude: [delete_customer, refund_payment] ``` ### 示例:同时禁用实用封装器 {#example-disable-utility-wrappers-too} ```yaml mcp_servers: docs: url: "https://mcp.docs.example.com" tools: prompts: false resources: false ``` ## 过滤实际影响什么? {#what-does-filtering-actually-affect} Hermes 中通过 MCP 暴露的功能分为两类: 1. 服务器原生的 MCP 工具 - 通过以下方式过滤: - `tools.include` - `tools.exclude` 2. Hermes 添加的实用封装器 - 通过以下方式过滤: - `tools.resources` - `tools.prompts` ### 你可能会看到的实用封装器 {#utility-wrappers-you-may-see} 资源: - `list_resources` - `read_resource` 提示: - `list_prompts` - `get_prompt` 这些封装器仅在满足以下条件时才会出现: - 你的配置允许它们 - MCP 服务器会话确实支持这些功能 因此,Hermes 不会假装某个服务器拥有资源/提示,如果它实际上并不支持。 ## 常见模式 {#common-patterns} ### 模式 1:本地项目助手 {#pattern-1-local-project-assistant} 当希望 Hermes 在一个有限的工作区范围内推理时,使用 MCP 来连接仓库本地的文件系统或 Git 服务器。 ```yaml mcp_servers: fs: command: "npx" args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/project"] git: command: "uvx" args: ["mcp-server-git", "--repository", "/home/user/project"] ``` 良好提示示例: ```text Review the project structure and identify where configuration lives. ``` ```text Check the local git state and summarize what changed recently. ``` ### 模式 2:GitHub 问题处理助手 {#pattern-2-github-triage-assistant} ```yaml mcp_servers: github: command: "npx" args: ["-y", "@modelcontextprotocol/server-github"] env: GITHUB_PERSONAL_ACCESS_TOKEN: "***" tools: include: [list_issues, create_issue, update_issue, search_code] prompts: false resources: false ``` 良好提示示例: ```text List open issues about MCP, cluster them by theme, and draft a high-quality issue for the most common bug. ``` ```text Search the repo for uses of _discover_and_register_server and explain how MCP tools are registered. ``` ### 模式 3:内部 API 助手 {#pattern-3-internal-api-assistant} ```yaml mcp_servers: internal_api: url: "https://mcp.internal.example.com" headers: Authorization: "Bearer ***" tools: include: [list_customers, get_customer, list_invoices] resources: false prompts: false ``` 良好提示示例: ```text Look up customer ACME Corp and summarize recent invoice activity. ``` 在这种场景中,严格的白名单远优于排除列表。 ### 模式 4:文档 / 知识服务器 {#pattern-4-documentation--knowledge-servers} 某些 MCP 服务器暴露的提示或资源更像是共享知识资产,而非直接操作。 ```yaml mcp_servers: docs: url: "https://mcp.docs.example.com" tools: prompts: true resources: true ``` 良好提示示例: ```text List available MCP resources from the docs server, then read the onboarding guide and summarize it. ``` ```text List prompts exposed by the docs server and tell me which ones would help with incident response. ``` ## 教程:带过滤的端到端设置 {#tutorial-end-to-end-setup-with-filtering} 以下是一个实用的逐步流程。 ### 阶段 1:添加 GitHub MCP 并使用严格白名单 {#phase-1-add-github-mcp-with-a-tight-whitelist} ```yaml mcp_servers: github: command: "npx" args: ["-y", "@modelcontextprotocol/server-github"] env: GITHUB_PERSONAL_ACCESS_TOKEN: "***" tools: include: [list_issues, create_issue, search_code] prompts: false resources: false ``` 启动 Hermes 并提问: ```text Search the codebase for references to MCP and summarize the main integration points. ``` ### 阶段 2:仅在需要时扩展 {#phase-2-expand-only-when-needed} 如果之后需要更新问题: ```yaml tools: include: [list_issues, create_issue, update_issue, search_code] ``` 然后重新加载: ```text /reload-mcp ``` ### 阶段 3:添加第二个具有不同策略的服务器 {#phase-3-add-a-second-server-with-different-policy} ```yaml mcp_servers: github: command: "npx" args: ["-y", "@modelcontextprotocol/server-github"] env: GITHUB_PERSONAL_ACCESS_TOKEN: "***" tools: include: [list_issues, create_issue, update_issue, search_code] prompts: false resources: false filesystem: command: "npx" args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/project"] ``` 现在 Hermes 可以组合使用它们: ```text Inspect the local project files, then create a GitHub issue summarizing the bug you find. ``` 这正是 MCP 的强大之处:无需修改 Hermes 核心即可实现多系统工作流。 ## 安全使用建议 {#safe-usage-recommendations} ### 对危险系统优先使用允许列表 {#prefer-allowlists-for-dangerous-systems} 对于任何金融、面向客户或具有破坏性的系统: - 使用 `tools.include` - 从最小的集合开始 ### 禁用未使用的实用功能 {#disable-unused-utilities} 如果你不希望模型浏览服务器提供的资源/提示,请关闭它们: ```yaml tools: resources: false prompts: false ``` ### 将服务器作用域限制在狭窄范围内 {#keep-servers-scoped-narrowly} 示例: - 以单个项目目录为根目录的文件系统服务器,而非整个主目录 - 指向单个仓库的 Git 服务器 - 默认以读取为主、工具暴露较多的内部 API 服务器 ### 配置更改后重新加载 {#reload-after-config-changes} ```text /reload-mcp ``` 在更改以下内容后执行此操作: - include/exclude 列表 - 启用标志 - 资源/提示开关 - 认证头 / 环境变量 ## 按症状排查问题 {#troubleshooting-by-symptom} ### “服务器已连接,但我预期的工具缺失” {#the-server-connects-but-the-tools-i-expected-are-missing} 可能原因: - 被 `tools.include` 过滤 - 被 `tools.exclude` 排除 - 通过 `resources: false` 或 `prompts: false` 禁用了工具包装器 - 服务器本身不支持资源/提示功能 ### “服务器已配置,但没有任何内容加载” {#the-server-is-configured-but-nothing-loads} 请检查: - 配置中未留下 `enabled: false` - 命令/运行时存在(如 `npx`、`uvx` 等) - HTTP 端点可访问 - 认证环境变量或请求头正确 ### “为什么我看到的工具比 MCP 服务器宣传的要少?” {#why-do-i-see-fewer-tools-than-the-mcp-server-advertises} 因为 Hermes 现在尊重每个服务器的策略和能力感知注册机制。这是预期行为,通常也是期望的结果。 ### “如何在不删除配置的情况下移除一个 MCP 服务器?” {#how-do-i-remove-an-mcp-server-without-deleting-the-config} 使用: ```yaml enabled: false ``` 这将保留配置,但阻止连接和注册。 ## 推荐的首个 MCP 部署方案 {#recommended-first-mcp-setups} 对大多数用户而言,良好的首个服务器选择包括: - 文件系统 - Git - GitHub - fetch / 文档 MCP 服务器 - 一个功能狭窄的内部 API 不太理想的首个服务器选择包括: - 包含大量破坏性操作且无过滤机制的大型业务系统 - 你无法充分理解并加以约束的任何系统 ## 相关文档 {#related-docs} - [MCP(模型上下文协议)](/docs/user-guide/features/mcp) - [常见问题](/docs/reference/faq) - [斜杠命令](/docs/reference/slash-commands) --- ### 使用 SOUL.md 与 Hermes - URL: https://hermesagent.org.cn/docs/guides/use-soul-with-hermes - Path: guides/use-soul-with-hermes.md - Category: guides - Description: 如何使用 SOUL.md 来定义 Hermes Agent 的默认语音,其中应包含哪些内容,以及它与 AGENTS.md 和 /personality 的区别是什么。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/use-soul-with-hermes.md - Translated At: 2026-04-11T03:31:47.765Z - Headings: SOUL.md 的用途 | SOUL.md 不适用于 | 文件位置 | 首次运行行为 | Hermes 如何使用它 | 一次有效的首次修改 | 示例风格 | 1. 务实工程师 | 风格 | 避免事项 | 2. 研究伙伴 | 风格 # 使用 SOUL.md 配合 Hermes {#use-soulmd-with-hermes} `SOUL.md` 是你的 Hermes 实例的**核心身份标识**。它是系统提示中的第一部分——定义了 Agent 的身份、表达方式以及应避免的内容。 如果你想让 Hermes 每次与你对话时都保持一致的助手形象,或者想完全用你自己的人格替换 Hermes 的默认形象,那么这个文件就是你要使用的。 ## SOUL.md 的用途 {#what-soulmd-is-for} 使用 `SOUL.md` 来定义: - 语气 - 个性 - 沟通风格 - Hermes 应该多直接或温暖 - Hermes 在风格上应避免什么 - Hermes 如何应对不确定性、分歧和模糊性 简而言之: - `SOUL.md` 关注的是 Hermes 是谁,以及它如何表达 ## SOUL.md 不适用于 {#what-soulmd-is-not-for} 不要在其中使用: - 项目特定的编码规范 - 文件路径 - 命令 - 服务端口 - 架构说明 - 项目工作流指南 这些内容应放在 `AGENTS.md` 中。 一个简单的判断原则: - 如果它应该在所有场景下适用,请放入 `SOUL.md` - 如果它仅属于某个特定项目,请放入 `AGENTS.md` ## 文件位置 {#where-it-lives} Hermes 现在仅使用当前实例的全局 SOUL 文件: ```text ~/.hermes/SOUL.md ``` 如果你使用自定义主目录运行 Hermes,则路径变为: ```text $HERMES_HOME/SOUL.md ``` ## 首次运行行为 {#first-run-behavior} 如果不存在 `SOUL.md`,Hermes 会自动为你生成一个初始版本。 这意味着大多数用户现在可以直接获得一个可读可编辑的真实文件。 重要提示: - 如果你已存在 `SOUL.md`,Hermes 不会覆盖它 - 如果文件存在但为空,Hermes 不会从其中添加任何内容到提示中 ## Hermes 如何使用它 {#how-hermes-uses-it} 当 Hermes 启动会话时,它会从 `HERMES_HOME` 读取 `SOUL.md`,扫描其中是否存在提示注入模式,必要时进行截断,并将其作为**Agent 身份**——即系统提示中的第 #1 个槽位。这意味着 `SOUL.md` 完全取代内置的默认身份文本。 如果 `SOUL.md` 缺失、为空或无法加载,Hermes 将回退到内置的默认身份。 不会在文件外添加任何包装语言。内容本身才是关键——以你希望 Agent 思考和表达的方式书写。 ## 一次有效的首次修改 {#a-good-first-edit} 如果你不做其他操作,只需打开文件并修改几行,使其更符合你的感觉。 例如: ```markdown You are direct, calm, and technically precise. Prefer substance over politeness theater. Push back clearly when an idea is weak. Keep answers compact unless deeper detail is useful. ``` 仅此一项就能显著改变 Hermes 的感觉。 ## 示例风格 {#example-styles} ### 1. 务实工程师 {#1-pragmatic-engineer} ```markdown You are a pragmatic senior engineer. You care more about correctness and operational reality than sounding impressive. ## 风格 - Be direct - Be concise unless complexity requires depth - Say when something is a bad idea - Prefer practical tradeoffs over idealized abstractions ## 避免事项 - Sycophancy - Hype language - Overexplaining obvious things ``` ### 2. 研究伙伴 {#2-research-partner} ```markdown You are a thoughtful research collaborator. You are curious, honest about uncertainty, and excited by unusual ideas. ## 风格 - Explore possibilities without pretending certainty - Distinguish speculation from evidence - Ask clarifying questions when the idea space is underspecified - Prefer conceptual depth over shallow completeness ``` ### 3. 教师 / 解释者 {#3-teacher--explainer} ```markdown You are a patient technical teacher. You care about understanding, not performance. ## 风格 - Explain clearly - Use examples when they help - Do not assume prior knowledge unless the user signals it - Build from intuition to details ``` ### 4. 严格评审者 {#4-tough-reviewer} ```markdown You are a rigorous reviewer. You are fair, but you do not soften important criticism. ## 风格 - Point out weak assumptions directly - Prioritize correctness over harmony - Be explicit about risks and tradeoffs - Prefer blunt clarity to vague diplomacy ``` ## 一份强大的 SOUL.md 应具备什么特征? {#what-makes-a-strong-soulmd} 一份强大的 `SOUL.md` 应具备: - 稳定性 - 广泛适用性 - 明确的语气特征 - 不包含过多临时性指令 一份弱的 `SOUL.md` 则表现为: - 充满项目细节 - 内容相互矛盾 - 试图对每次响应的形态进行微观管理 - 大量使用“要乐于助人”“要清晰”之类的通用填充语 Hermes 本身已经尽力做到乐于助人和清晰表达。`SOUL.md` 应该增添真正的个性与风格,而非重复显而易见的默认设定。 ## 建议的结构 {#suggested-structure} 你不需要使用标题,但使用它们有助于组织。 一种简单有效的结构如下: ```markdown # 身份 Who Hermes is. # 风格 How Hermes should sound. # 避免事项 What Hermes should not do. # 默认值 How Hermes should behave when ambiguity appears. ``` ## SOUL.md 与 /personality 的关系 {#soulmd-vs-personality} 二者是互补的。 使用 `SOUL.md` 作为你持久不变的基础人格。 使用 `/personality` 实现临时模式切换。 示例: - 你的默认 SOUL 是务实且直接的 - 然后在某次会话中使用 `/personality teacher` - 后续再切换回默认人格,无需修改基础语音文件 ## SOUL.md 与 AGENTS.md 的区别 {#soulmd-vs-agentsmd} 这是最常见的误解。 ### 放入 SOUL.md 的内容 {#put-this-in-soulmd} - “要直接。” - “避免使用夸张语言。” - “除非深入有帮助,否则优先简短回答。” - “当用户错误时,应提出反驳。” ### 放入 AGENTS.md 的内容 {#put-this-in-agentsmd} - “使用 pytest,而非 unittest。” - “前端代码位于 `frontend/` 目录下。” - “不要直接编辑迁移文件。” - “API 运行在端口 8000。” ## 如何编辑它 {#how-to-edit-it} ```bash nano ~/.hermes/SOUL.md ``` 或 ```bash vim ~/.hermes/SOUL.md ``` 然后重启 Hermes 或开启新会话。 ## 实用工作流 {#a-practical-workflow} 1. 从生成的默认文件开始 2. 删除任何不符合你期望语气的内容 3. 添加 4–8 行,明确界定语气和默认行为 4. 与 Hermes 对话一段时间 5. 根据仍感觉不对的地方进行调整 这种迭代式方法比试图一次性设计出“完美”人格更有效。 ## 故障排查 {#troubleshooting} ### 我修改了 SOUL.md,但 Hermes 仍听起来一样 {#i-edited-soulmd-but-hermes-still-sounds-the-same} 请检查: - 你修改的是 `~/.hermes/SOUL.md` 或 `$HERMES_HOME/SOUL.md` - 而非某个项目本地的 `SOUL.md` - 文件不为空 - 修改后已重启会话 - 没有 `/personality` 覆盖层主导结果 ### Hermes 忽略了 SOUL.md 中的部分内容 {#hermes-is-ignoring-parts-of-my-soulmd} 可能原因: - 更高优先级的指令正在覆盖它 - 文件中包含相互冲突的指导 - 文件过长,已被截断 - 部分文本与提示注入内容相似,可能被扫描器拦截或修改 ### 我的 SOUL.md 变得太项目相关了 {#my-soulmd-became-too-project-specific} 将项目相关指令移至 `AGENTS.md`,并保持 `SOUL.md` 聚焦于身份与风格。 ## 相关文档 {#related-docs} - [个性与SOUL.md](/docs/user-guide/features/personality) - [上下文文件](/docs/user-guide/features/context-files) - [配置](/docs/user-guide/configuration) - [技巧与最佳实践](/docs/guides/tips) --- ### 使用 Voice Mode 与 Hermes - URL: https://hermesagent.org.cn/docs/guides/use-voice-mode-with-hermes - Path: guides/use-voice-mode-with-hermes.md - Category: guides - Description: Hermes 语音模式的实用指南:跨 CLI、Telegram、Discord 及 Discord 语音频道的设置与使用 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/use-voice-mode-with-hermes.md - Translated At: 2026-04-11T03:32:20.332Z - Headings: 语音模式适用场景 | 选择你的语音模式配置 | 第一步:确保普通Hermes正常工作 | 第二步:安装正确的附加组件 | CLI 麦克风 + 播放 | 消息平台 | 高级 ElevenLabs TTS | 本地 NeuTTS(可选) | 全部安装 | 第三步:安装系统依赖 | macOS | Ubuntu / Debian # 使用Hermes的语音模式 {#use-voice-mode-with-hermes} 本指南是[语音模式功能参考](/docs/user-guide/features/voice-mode)的实践配套文档。 若功能页面解释了语音模式能做什么,本指南则展示如何实际有效地使用它。 ## 语音模式适用场景 {#what-voice-mode-is-good-for} 语音模式特别适用于以下情况: - 希望实现无手操作的 CLI 工作流 - 希望在 Telegram 或 Discord 中获得语音回复 - 希望Hermes进入 Discord 语音频道进行实时对话 - 希望在行走时快速捕捉想法、调试或进行来回交流,而非打字 ## 选择你的语音模式配置 {#choose-your-voice-mode-setup} Hermes实际上提供了三种不同的语音体验。 | 模式 | 适用场景 | 平台 | |---|---|---| | 交互式麦克风循环 | 编码或研究时个人无手操作使用 | CLI | | 聊天中的语音回复 | 与正常消息并行的语音回复 | Telegram、Discord | | 实时语音频道机器人 | 在语音频道中进行群组或个人实时对话 | Discord 语音频道 | 推荐路径是: 1. 首先确保文本模式正常工作 2. 然后启用语音回复 3. 如果需要完整体验,最后再切换到 Discord 语音频道 ## 第一步:确保普通Hermes正常工作 {#step-1-make-sure-normal-hermes-works-first} 在启用语音模式前,请确认以下事项: - Hermes能够启动 - 你的服务提供商已正确配置 - Agent 可以正常响应文本提示 ```bash hermes ``` 提出一个简单问题: ```text What tools do you have available? ``` 如果以上尚未稳定,请先修复文本模式。 ## 第二步:安装正确的附加组件 {#step-2-install-the-right-extras} ### CLI 麦克风 + 播放 {#cli-microphone--playback} ```bash pip install "hermes-agent[voice]" ``` ### 消息平台 {#messaging-platforms} ```bash pip install "hermes-agent[messaging]" ``` ### 高级 ElevenLabs TTS {#premium-elevenlabs-tts} ```bash pip install "hermes-agent[tts-premium]" ``` ### 本地 NeuTTS(可选) {#local-neutts-optional} ```bash python -m pip install -U neutts[all] ``` ### 全部安装 {#everything} ```bash pip install "hermes-agent[all]" ``` ## 第三步:安装系统依赖 {#step-3-install-system-dependencies} ### macOS {#macos} ```bash brew install portaudio ffmpeg opus brew install espeak-ng ``` ### Ubuntu / Debian {#ubuntu--debian} ```bash sudo apt install portaudio19-dev ffmpeg libopus0 sudo apt install espeak-ng ``` 这些依赖项的重要性如下: - `portaudio` → CLI 语音模式的麦克风输入/播放支持 - `ffmpeg` → TTS 和消息传递所需的音频转换 - `opus` → Discord 语音编解码器支持 - `espeak-ng` → NeuTTS 的音素化后端 ## 第四步:选择 STT 和 TTS 提供商 {#step-4-choose-stt-and-tts-providers} Hermes支持本地和云端语音处理方案。 ### 最简单 / 最经济的配置 {#easiest--cheapest-setup} 使用本地 STT 和免费的 Edge TTS: - STT 提供商:`local` - TTS 提供商:`edge` 这通常是最佳起点。 ### 环境文件示例 {#environment-file-example} 将以下内容添加至 `~/.hermes/.env`: ```bash # 云STT选项(本地无需密钥) GROQ_API_KEY=*** VOICE_TOOLS_OPENAI_KEY=*** # 高级版 TTS(可选) ELEVENLABS_API_KEY=*** ``` ### 提供商推荐 {#provider-recommendations} #### 语音识别(STT) {#speech-to-text} - `local` → 隐私保护和零成本使用的最佳默认选择 - `groq` → 非常快速的云端转录 - `openai` → 质量良好的付费备用方案 #### 语音合成(TTS) {#text-to-speech} - `edge` → 免费且对大多数用户已足够 - `neutts` → 免费的本地/设备端 TTS - `elevenlabs` → 最佳音质 - `openai` → 质量居中 ### 如果你使用 `hermes setup` {#if-you-use-hermes-setup} 如果你在设置向导中选择了 NeuTTS,Hermes会检查 `neutts` 是否已安装。如果缺失,向导会提示你需要安装 Python 包 `neutts` 和系统包 `espeak-ng`,并提供自动安装选项。它将使用你平台的包管理器安装 `espeak-ng`,然后运行: ```bash python -m pip install -U neutts[all] ``` 如果你跳过安装或安装失败,向导将回退到 Edge TTS。 ## 第五步:推荐配置 {#step-5-recommended-config} ```yaml voice: record_key: "ctrl+b" max_recording_seconds: 120 auto_tts: false silence_threshold: 200 silence_duration: 3.0 stt: provider: "local" local: model: "base" tts: provider: "edge" edge: voice: "en-US-AriaNeural" ``` 这是大多数用户的保守默认配置。 如果你希望使用本地 TTS,将 `tts` 块改为: ```yaml tts: provider: "neutts" neutts: ref_audio: '' ref_text: '' model: neuphonic/neutts-air-q4-gguf device: cpu ``` ## 用例 1:CLI 语音模式 {#use-case-1-cli-voice-mode} ## 启用语音模式 {#turn-it-on} 启动Hermes: ```bash hermes ``` 进入 CLI 界面: ```text /voice on ``` ### 录音流程 {#recording-flow} 默认快捷键: - `Ctrl+B` 操作流程: 1. 按下 `Ctrl+B` 2. 开始说话 3. 等待静音检测自动停止录音 4. Hermes完成语音转文字并作出回应 5. 若 TTS 已启用,它将朗读答案 6. 循环可自动重启,实现连续使用 ### 实用命令 {#useful-commands} ```text /voice /voice on /voice off /voice tts /voice status ``` ### 优秀的 CLI 工作流 {#good-cli-workflows} #### 举步调试 {#walk-up-debugging} 说出: ```text I keep getting a docker permission error. Help me debug it. ``` 然后继续无手操作: - “再读一遍上一个错误” - “用更简单的语言解释根本原因” - “现在给我具体的修复方案” #### 研究 / 头脑风暴 {#research--brainstorming} 非常适合: - 边走边思考 - 口述尚未成型的想法 - 让Hermes实时帮你整理思路 #### 可访问性 / 低打字量会话 {#accessibility--low-typing-sessions} 当打字不便时,语音模式是保持完整Hermes工作流的最快方式之一。 ## 调整 CLI 行为 {#tuning-cli-behavior} ### 静音阈值 {#silence-threshold} 如果Hermes启动/停止过于敏感,可调整: ```yaml voice: silence_threshold: 250 ``` 阈值越高,灵敏度越低。 ### 静音持续时间 {#silence-duration} 如果你在句子之间停顿较多,可增加: ```yaml voice: silence_duration: 4.0 ``` ### 录音快捷键 {#record-key} 如果 `Ctrl+B` 与你的终端或 tmux 设置冲突: ```yaml voice: record_key: "ctrl+space" ``` ## 用例 2:Telegram 或 Discord 中的语音回复 {#use-case-2-voice-replies-in-telegram-or-discord} 此模式比完整语音频道更简单。 Hermes保持为普通聊天机器人,但可发出语音回复。 ### 启动网关 {#start-the-gateway} ```bash hermes gateway ``` ### 开启语音回复 {#turn-on-voice-replies} 在 Telegram 或 Discord 中: ```text /voice on ``` 或 ```text /voice tts ``` ### 模式 {#modes} | 模式 | 含义 | |---|---| | `off` | 仅文本 | | `voice_only` | 仅当用户发送语音时才进行语音回复 | | `all` | 每次回复都进行语音播报 | ### 何时使用哪种模式 {#when-to-use-which-mode} - `/voice on`:若你希望仅对语音消息进行语音回复 - `/voice tts`:若你希望始终拥有全程语音交互的助手 ### 优秀的消息交互工作流 {#good-messaging-workflows} #### 手机上的 Telegram 助手 {#telegram-assistant-on-your-phone} 适用场景: - 你远离电脑设备 - 希望发送语音消息并快速获得语音回复 - 希望 Hermes 表现得像一个便携式研究或运维助手 #### Discord 私聊中的语音输出 {#discord-dms-with-spoken-output} 适用于希望进行私密交互,避免在服务器频道中被提及的情况。 ## 使用场景 3:Discord 语音频道 {#use-case-3-discord-voice-channels} 这是最高级的模式。 Hermes 加入 Discord 语音频道,监听用户语音,进行语音识别(STT),执行标准 Agent 处理流程,并将回复以语音形式返回至频道。 ## 所需的 Discord 权限 {#required-discord-permissions} 除了常规的文本机器人设置外,请确保机器人拥有以下权限: - 连接(Connect) - 发言(Speak) - 建议启用:使用语音活动(Use Voice Activity) 同时在开发者门户中启用高权限意图(privileged intents): - 状态意图(Presence Intent) - 服务器成员意图(Server Members Intent) - 消息内容意图(Message Content Intent) ## 加入与离开 {#join-and-leave} 在机器人所在的 Discord 文本频道中执行以下操作: ```text /voice join /voice leave /voice status ``` ### 加入后发生的情况 {#what-happens-when-joined} - 用户在语音频道中说话 - Hermes 检测语音边界 - 语音转文字结果发布到关联的文本频道 - Hermes 以文本和音频形式进行回复 - 文本频道即为执行 `/voice join` 命令的频道 ### Discord 语音频道使用的最佳实践 {#best-practices-for-discord-vc-use} - 严格控制 `DISCORD_ALLOWED_USERS` 列表 - 初次使用时建议使用专用机器人/测试频道 - 在尝试语音频道模式前,先验证 STT 和 TTS 在普通文本聊天语音模式下的正常工作 ## 语音质量建议 {#voice-quality-recommendations} ### 最佳质量配置 {#best-quality-setup} - STT:本地 `large-v3` 或 Groq `whisper-large-v3` - TTS:ElevenLabs ### 最佳速度/便捷性配置 {#best-speed--convenience-setup} - STT:本地 `base` 或 Groq - TTS:Edge ### 最佳零成本配置 {#best-zero-cost-setup} - STT:本地 - TTS:Edge ## 常见故障模式 {#common-failure-modes} ### “未找到音频设备” {#no-audio-device-found} 安装 `portaudio`。 ### “机器人已加入但听不到任何声音” {#bot-joins-but-hears-nothing} 请检查: - 你的 Discord 用户 ID 是否在 `DISCORD_ALLOWED_USERS` 列表中 - 你是否被静音 - 高权限意图是否已启用 - 机器人是否拥有“连接”和“发言”权限 ### “能转录但无法语音播报” {#it-transcribes-but-does-not-speak} 请检查: - TTS 提供商配置 - ElevenLabs 或 OpenAI 的 API 密钥 / 配额 - Edge 转换路径所需的 `ffmpeg` 是否已安装 ### “Whisper 输出乱码” {#whisper-outputs-garbage} 尝试: - 更安静的环境 - 提高 `silence_threshold` 值 - 更换 STT 提供商或模型 - 发送更短、更清晰的语音片段 ### “在私聊中正常工作,但在服务器频道中不行” {#it-works-in-dms-but-not-in-server-channels} 这通常是提及策略(mention policy)导致的。 默认情况下,机器人在 Discord 服务器文本频道中需要被 `@提及` 才能响应,除非另行配置。 ## 建议的第一周设置 {#suggested-first-week-setup} 若希望最快获得成功体验: 1. 先让文本版 Hermes 正常运行 2. 安装 `hermes-agent[voice]` 3. 使用 CLI 语音模式,搭配本地 STT + Edge TTS 4. 然后在 Telegram 或 Discord 中启用 `/voice on` 5. 仅在上述步骤成功后,再尝试 Discord 语音频道模式 此流程可保持调试范围最小化。 ## 接下来阅读 {#where-to-read-next} - [语音模式功能参考](/docs/user-guide/features/voice-mode) - [消息网关](/docs/user-guide/messaging) - [Discord 设置](/docs/user-guide/messaging/discord) - [Telegram 设置](/docs/user-guide/messaging/telegram) - [配置指南](/docs/user-guide/configuration) --- ### 使用 Webhook 实现 GitHub PR 自动评论 - URL: https://hermesagent.org.cn/docs/guides/webhook-github-pr-review - Path: guides/webhook-github-pr-review.md - Category: guides - Description: 将 Hermes 连接到 GitHub,以便它自动获取 PR 差异、审查代码更改并发布评论——由 Webhook 触发,无需手动干预 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/webhook-github-pr-review.md - Translated At: 2026-05-03T17:16:34.889Z - Headings: 前提条件 | 步骤 1 — 启用 webhook 平台 | 步骤 2 — 启动网关 | 步骤 3 — 在 GitHub 上注册 webhook | 步骤 4 — 打开测试 PR | 使用 ngrok 进行本地测试 | 过滤特定操作 | 使用技能保持一致的审查风格 | 改为将响应发送到 Slack 或 Discord | GitLab 支持 | 安全说明 | 故障排除 # 使用 Webhook 实现自动化的 GitHub PR 评论 {#automated-github-pr-comments-with-webhooks} 本指南将引导你将 Hermes Agent 连接到 GitHub,使其能够自动获取拉取请求(Pull Request, PR)的差异(diff),分析代码变更,并发布评论——这一切均由 webhook 事件触发,无需人工干预。 当 PR 被打开或更新时,GitHub 会向你的 Hermes 实例发送一个 webhook POST 请求。Hermes 会使用一个提示词(prompt)运行 agent,指示它通过 `gh` CLI 获取差异内容,并将响应发布回 PR 讨论区。 :::tip 想要更简单的设置且无需公网端点? 如果你没有公网 URL 或者只是想快速开始,请查看[构建 GitHub PR 审查 Agent](github-pr-review-agent)——它使用 cron 作业按计划轮询 PR,可在 NAT 和防火墙后方工作。 ::: :::info 参考文档 有关完整的 webhook 平台参考(所有配置选项、交付类型、动态订阅、安全模型),请参阅 [Webhooks](/docs/user-guide/messaging/webhooks)。 ::: :::warning 提示词注入风险 Webhook 载荷包含攻击者可控的数据——PR 标题、提交消息和描述可能包含恶意指令。当你的 webhook 端点暴露在互联网上时,请在沙箱环境(Docker、SSH 后端)中运行网关。请参阅下方的[安全说明](#security-notes)。 ::: --- ## 前提条件 {#prerequisites} - 已安装并运行 Hermes Agent (`hermes gateway`) - 在网关主机上已安装并认证 [`gh` CLI](https://cli.github.com/) (`gh auth login`) - 你的 Hermes 实例拥有一个可公开访问的 URL(如果在本地运行,请参阅[使用 ngrok 进行本地测试](#local-testing-with-ngrok)) - 拥有 GitHub 仓库的管理员权限(管理 webhook 所需) --- ## 步骤 1 — 启用 webhook 平台 {#step-1-—-enable-the-webhook-platform} 将以下内容添加到你的 `~/.hermes/config.yaml` 中: ```yaml platforms: webhook: enabled: true extra: port: 8644 # default; change if another service occupies this port rate_limit: 30 # max requests per minute per route (not a global cap) routes: github-pr-review: secret: "your-webhook-secret-here" # must match the GitHub webhook secret exactly events: - pull_request # The agent is instructed to fetch the actual diff before reviewing. # {number} and {repository.full_name} are resolved from the GitHub payload. prompt: | A pull request event was received (action: {action}). PR #{number}: {pull_request.title} Author: {pull_request.user.login} Branch: {pull_request.head.ref} → {pull_request.base.ref} Description: {pull_request.body} URL: {pull_request.html_url} If the action is "closed" or "labeled", stop here and do not post a comment. Otherwise: 1. Run: gh pr diff {number} --repo {repository.full_name} 2. Review the code changes for correctness, security issues, and clarity. 3. Write a concise, actionable review comment and post it. deliver: github_comment deliver_extra: repo: "{repository.full_name}" pr_number: "{number}" ``` **关键字段:** | 字段 | 描述 | |---|---| | `secret`(路由级别) | 此路由的 HMAC 密钥。如果省略,则回退到全局 `extra.secret`。 | | `events` | 要接受的 `X-GitHub-Event` 头值列表。空列表 = 接受所有事件。 | | `prompt` | 模板;`{field}` 和 `{nested.field}` 将从 GitHub 载荷中解析。 | | `deliver` | `github_comment` 通过 `gh pr comment` 发布评论。`log` 仅写入网关日志。 | | `deliver_extra.repo` | 从载荷中解析为例如 `org/repo`。 | | `deliver_extra.pr_number` | 从载荷中解析为 PR 编号。 | :::note 载荷不包含代码 GitHub webhook 载荷包括 PR 元数据(标题、描述、分支名称、URL),但**不包含差异内容**。上述提示词指示 agent 运行 `gh pr diff` 来获取实际的变更。`terminal` 工具包含在默认的 `hermes-webhook` 工具集中,因此无需额外配置。 ::: --- ## 步骤 2 — 启动网关 {#step-2-—-start-the-gateway} ```bash hermes gateway ``` 你应该看到: ``` [webhook] Listening on 0.0.0.0:8644 — routes: github-pr-review ``` 验证其是否正在运行: ```bash curl http://localhost:8644/health # {"status": "ok", "platform": "webhook"} ``` --- ## 步骤 3 — 在 GitHub 上注册 webhook {#step-3-—-register-the-webhook-on-github} 1. 进入你的仓库 → **Settings**(设置)→ **Webhooks** → **Add webhook**(添加 webhook) 2. 填写: - **Payload URL:** `https://your-public-url.example.com/webhooks/github-pr-review` - **Content type:** `application/json` - **Secret:** 与你在路由配置中设置的 `secret` 值相同 - **Which events?**(哪些事件?)→ 选择单独的事件 → 勾选 **Pull requests**(拉取请求) 3. 点击 **Add webhook** GitHub 会立即发送一个 `ping` 事件以确认连接。该事件会被安全地忽略——因为 `ping` 不在你的 `events` 列表中——并返回 `{"status": "ignored", "event": "ping"}`。它仅在 DEBUG 级别记录,因此在默认日志级别下不会出现在控制台中。 --- ## 步骤 4 — 打开测试 PR {#step-4-—-open-a-test-pr} 创建一个分支,推送更改,并打开一个 PR。在 30–90 秒内(取决于 PR 大小和模型),Hermes 应该会发布一条审查评论。 要实时跟踪 agent 的进度: ```bash tail -f "${HERMES_HOME:-$HOME/.hermes}/logs/gateway.log" ``` --- ## 使用 ngrok 进行本地测试 {#local-testing-with-ngrok} 如果 Hermes 在你的笔记本电脑上运行,请使用 [ngrok](https://ngrok.com/) 将其暴露出来: ```bash ngrok http 8644 ``` 复制 `https://...ngrok-free.app` URL 并将其用作你的 GitHub Payload URL。在免费的 ngrok 层级中,每次 ngrok 重启时 URL 都会更改——请在每个会话中更新你的 GitHub webhook。付费的 ngrok 账户可获得静态域名。 你可以直接使用 `curl` 对静态路由进行冒烟测试——无需 GitHub 账户或真实的 PR。 :::tip 在本地测试时使用 `deliver: log` 在测试期间,将配置中的 `deliver: github_comment` 更改为 `deliver: log`。否则,agent 将尝试向测试载荷中虚构的 `org/repo#99` 仓库发布评论,这将会失败。当你对提示词输出满意后,再切换回 `deliver: github_comment`。 ::: ```bash SECRET="your-webhook-secret-here" BODY='{"action":"opened","number":99,"pull_request":{"title":"Test PR","body":"Adds a feature.","user":{"login":"testuser"},"head":{"ref":"feat/x"},"base":{"ref":"main"},"html_url":"https://github.com/org/repo/pull/99"},"repository":{"full_name":"org/repo"}}' SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print "sha256="$2}') curl -s -X POST http://localhost:8644/webhooks/github-pr-review \ -H "Content-Type: application/json" \ -H "X-GitHub-Event: pull_request" \ -H "X-Hub-Signature-256: $SIG" \ -d "$BODY" # Expected: {"status":"accepted","route":"github-pr-review","event":"pull_request","delivery_id":"..."} ``` 然后观察 agent 的运行情况: ```bash tail -f "${HERMES_HOME:-$HOME/.hermes}/logs/gateway.log" ``` :::note `hermes webhook test ` 仅适用于使用 `hermes webhook subscribe` 创建的**动态订阅**。它不会读取 `config.yaml` 中的路由。 ::: --- ## 过滤特定操作 {#filtering-to-specific-actions} GitHub 会为许多操作发送 `pull_request` 事件:`opened`、`synchronize`、`reopened`、`closed`、`labeled` 等。`events` 列表仅根据 `X-GitHub-Event` 标头值进行过滤——它无法在路由级别按操作子类型进行过滤。 步骤 1 中的提示已通过指示代理针对 `closed` 和 `labeled` 事件提前停止来处理此问题。 :::warning 代理仍然运行并消耗令牌 “在此停止”指令可防止进行有意义的审查,但无论操作如何,代理仍会为每个 `pull_request` 事件运行至完成。GitHub Webhook 只能按事件类型(`pull_request`、`push`、`issues` 等)过滤,而不能按操作子类型(`opened`、`closed`、`labeled`)过滤。不存在针对子操作的路由级过滤器。对于高流量的仓库,请接受此成本,或使用有条件调用你的 Webhook URL 的 GitHub Actions 工作流在上游进行过滤。 ::: > 不存在 Jinja2 或条件模板语法。`{field}` 和 `{nested.field}` 是唯一支持的替换项。任何其他内容都将逐字传递给代理。 --- ## 使用技能保持一致的审查风格 {#using-a-skill-for-consistent-review-style} 加载 [Hermes 技能](/docs/user-guide/features/skills) 以赋予代理一致的审查角色。在 `config.yaml` 的 `platforms.webhook.extra.routes` 内部向你的路由添加 `skills`: ```yaml platforms: webhook: enabled: true extra: routes: github-pr-review: secret: "your-webhook-secret-here" events: [pull_request] prompt: | A pull request event was received (action: {action}). PR #{number}: {pull_request.title} by {pull_request.user.login} URL: {pull_request.html_url} If the action is "closed" or "labeled", stop here and do not post a comment. Otherwise: 1. Run: gh pr diff {number} --repo {repository.full_name} 2. Review the diff using your review guidelines. 3. Write a concise, actionable review comment and post it. skills: - review deliver: github_comment deliver_extra: repo: "{repository.full_name}" pr_number: "{number}" ``` > **注意:** 仅加载列表中找到的第一个技能。Hermes 不会堆叠多个技能——后续条目将被忽略。 --- ## 改为将响应发送到 Slack 或 Discord {#sending-responses-to-slack-or-discord-instead} 用目标平台替换路由中的 `deliver` 和 `deliver_extra` 字段: ```yaml # Inside platforms.webhook.extra.routes.: # Slack deliver: slack deliver_extra: chat_id: "C0123456789" # Slack channel ID (omit to use the configured home channel) # Discord deliver: discord deliver_extra: chat_id: "987654321012345678" # Discord channel ID (omit to use home channel) ``` 还必须在网关中启用并连接目标平台。如果省略 `chat_id`,响应将发送到该平台配置的主频道。 有效的 `deliver` 值:`log` · `github_comment` · `telegram` · `discord` · `slack` · `signal` · `sms` --- ## GitLab 支持 {#gitlab-support} 同一适配器也适用于 GitLab。GitLab 使用 `X-Gitlab-Token` 进行身份验证(纯字符串匹配,而非 HMAC)——Hermes 会自动处理这两种情况。 对于事件过滤,GitLab 将 `X-GitLab-Event` 设置为类似 `Merge Request Hook`、`Push Hook`、`Pipeline Hook` 的值。在 `events` 中使用精确的标头值: ```yaml events: - Merge Request Hook ``` GitLab 的有效负载字段与 GitHub 的不同——例如,MR 标题使用 `{object_attributes.title}`,MR 编号使用 `{object_attributes.iid}`。发现完整有效负载结构的最简单方法是结合使用 Webhook 设置中的 GitLab **Test** 按钮和 **Recent Deliveries**(最近交付)日志。或者,从你的路由配置中省略 `prompt`——Hermes 随后会将格式化的 JSON 完整有效负载直接传递给代理,而代理的响应(在带有 `deliver: log` 的网关日志中可见)将描述其结构。 --- ## 安全说明 {#security-notes} - **切勿在生产环境中使用 `INSECURE_NO_AUTH`**——它会完全禁用签名验证。它仅用于本地开发。 - **定期轮换你的 Webhook 密钥**,并在 GitHub(Webhook 设置)和你的 `config.yaml` 中更新它。 - **速率限制**默认为每路由 30 请求/分钟(可通过 `extra.rate_limit` 配置)。超出限制将返回 `429`。 - **重复交付**(Webhook 重试)通过 1 小时幂等性缓存进行去重。缓存键依次为 `X-GitHub-Delivery`(如果存在)、`X-Request-ID`,然后是毫秒时间戳。当未设置任何交付 ID 标头时,重试**不会**去重。 - **提示注入:** PR 标题、描述和提交消息由攻击者控制。恶意 PR 可能会尝试操纵代理的操作。当暴露在公共互联网上时,请在沙箱环境(Docker、VM)中运行网关。 --- ## 故障排除 {#troubleshooting} | 症状 | 检查项 | |---|---| | `401 Invalid signature` | config.yaml 中的密钥与 GitHub Webhook 密钥不匹配 | | `404 Unknown route` | URL 中的路由名称与 `routes:` 中的键不匹配 | | `429 Rate limit exceeded` | 超过每路由 30 请求/分钟的限制——在从 GitHub UI 重新交付测试事件时很常见;等待一分钟或提高 `extra.rate_limit` | | 未发布评论 | 未安装 `gh`、不在 PATH 中或未进行身份验证(`gh auth login`) | | 代理运行但未发表评论 | 检查网关日志——如果代理输出为空或仅为 "SKIP",仍会尝试交付 | | 端口已被占用 | 更改 config.yaml 中的 `extra.port` | | 代理运行但仅审查 PR 描述 | 提示未包含 `gh pr diff` 指令——差异信息不在 Webhook 有效负载中 | | 看不到 ping 事件 | 被忽略的事件仅在 DEBUG 日志级别返回 `{"status":"ignored","event":"ping"}`——检查 GitHub 的交付日志(仓库 → Settings → Webhooks → 你的 Webhook → Recent Deliveries) | **GitHub 的 Recent Deliveries(最近交付)选项卡**(仓库 → Settings → Webhooks → 你的 Webhook)显示每次交付的确切请求标头、有效负载、HTTP 状态和响应正文。这是在不接触服务器日志的情况下诊断失败的最快方法。 --- ## 完整配置参考 {#full-config-reference} ```yaml platforms: webhook: enabled: true extra: host: "0.0.0.0" # bind address (default: 0.0.0.0) port: 8644 # listen port (default: 8644) secret: "" # optional global fallback secret rate_limit: 30 # requests per minute per route max_body_bytes: 1048576 # payload size limit in bytes (default: 1 MB) routes: : secret: "required-per-route" events: [] # [] = accept all; otherwise list X-GitHub-Event values prompt: "" # {field} / {nested.field} resolved from payload skills: [] # first matching skill is loaded (only one) deliver: "log" # log | github_comment | telegram | discord | slack | signal | sms deliver_extra: {} # repo + pr_number for github_comment; chat_id for others ``` --- ## 接下来是什么? {#whats-next} - **[基于 Cron 的 PR 审查](github-pr-review-agent)** — 按计划轮询 PR,无需公共端点 - **[Webhook 参考](/docs/user-guide/messaging/webhooks)** — Webhook 平台的完整配置参考 - **[构建插件](/docs/guides/build-a-hermes-plugin)** — 将审查逻辑打包为可共享的插件 - **[配置文件](/docs/user-guide/profiles)** — 运行具有独立记忆和配置的专用审查者配置文件 --- ### 使用技能 - URL: https://hermesagent.org.cn/docs/guides/work-with-skills - Path: guides/work-with-skills.md - Category: guides - Description: 查找、安装、使用和创建技能 — 按需获取的知识,用于教授 Hermes 新的工作流程 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/work-with-skills.md - Translated At: 2026-04-11T03:32:46.234Z - Headings: 查找技能 | 搜索技能 | 技能中心(Skills Hub) | 使用技能 | 渐进式披露(Progressive Disclosure) | 从中心安装技能 | 验证安装 | 配置技能设置 | 创建你自己的技能 | 1. 创建目录 | 2. 编写 SKILL.md | 何时使用 # 使用技能 {#working-with-skills} 技能是按需加载的知识文档,用于指导 Hermes 完成特定任务——从生成 ASCII 艺术到管理 GitHub Pull Request。本指南将带你了解日常如何使用技能。 如需完整的技术参考,请参阅 [技能系统](/docs/user-guide/features/skills)。 --- ## 查找技能 {#finding-skills} 每个 Hermes 安装都自带一组内置技能。查看可用的技能: ```bash # 在任何聊天中 session: /skills # 或者来自 CLI: hermes skills list ``` 这会显示一个简洁的列表,包含技能名称和描述: ``` ascii-art Generate ASCII art using pyfiglet, cowsay, boxes... arxiv Search and retrieve academic papers from arXiv... github-pr-workflow Full PR lifecycle — create branches, commit... plan Plan mode — inspect context, write a markdown... excalidraw Create hand-drawn style diagrams using Excalidraw... ``` ### 搜索技能 {#searching-for-a-skill} ```bash # 按关键字搜索 /skills search docker /skills search music ``` ### 技能中心(Skills Hub) {#the-skills-hub} 官方可选技能(较重或小众、默认未启用的技能)可通过中心获取: ```bash # 浏览官方可选skills /skills browse # 搜索中心 /skills search blockchain ``` --- ## 使用技能 {#using-a-skill} 所有已安装的技能都会自动成为斜杠命令。只需输入其名称即可: ```bash # 加载一个skill并给它一个任务 /ascii-art Make a banner that says "HELLO WORLD" /plan Design a REST API for a todo app /github-pr-workflow Create a PR for the auth refactor # 只需 skill 名称(无任务)即可加载它并让您描述您需要的内容 /excalidraw ``` 你也可以通过自然对话触发技能——只需让 Hermes 使用某个特定技能,它将通过 `skill_view` 工具加载该技能。 ### 渐进式披露(Progressive Disclosure) {#progressive-disclosure} 技能采用高效的令牌加载模式。Agent 不会一次性加载全部内容: 1. **`skills_list()`** —— 所有技能的简洁列表(约 3k 令牌)。在会话开始时加载。 2. **`skill_view(name)`** —— 某个技能的完整 `SKILL.md` 内容。当 Agent 判断需要时才加载。 3. **`skill_view(name, file_path)`** —— 技能内的某个特定参考文件。仅在需要时加载。 这意味着,只有在实际使用时,技能才会消耗令牌。 --- ## 从中心安装技能 {#installing-from-the-hub} 官方可选技能随 Hermes 一同提供,但默认未启用。需显式安装: ```bash # 安装官方可选的skill hermes skills install official/research/arxiv # 在聊天中从集线器安装 session /skills install official/creative/songwriting-and-ai-music ``` 操作流程如下: 1. 将技能目录复制到 `~/.hermes/skills/` 2. 它会出现在你的 `skills_list` 输出中 3. 可作为斜杠命令使用 :::tip 已安装的技能将在新会话中生效。若希望在当前会话中立即生效,请使用 `/reset` 重启会话,或添加 `--now` 参数立即清除提示缓存(会增加下一次交互的令牌消耗)。 ::: ### 验证安装 {#verifying-installation} ```bash # 检查它是否在那里 hermes skills list | grep arxiv # 或者在聊天中 /skills search arxiv ``` --- ## 配置技能设置 {#configuring-skill-settings} 某些技能在其前文(frontmatter)中声明了所需的配置项: ```yaml metadata: hermes: config: - key: tenor.api_key description: "Tenor API key for GIF search" prompt: "Enter your Tenor API key" url: "https://developers.google.com/tenor/guides/quickstart" ``` 当首次加载带有配置的技能时,Hermes 会提示你输入配置值。这些值将存储在 `config.yaml` 中的 `skills.config.*` 下。 可通过 CLI 管理技能配置: ```bash # 特定 skill 的交互式配置 hermes skills config gif-search # 查看所有skill配置 hermes config get skills.config ``` --- ## 创建你自己的技能 {#creating-your-own-skill} 技能只是带有 YAML 前文的 Markdown 文件。创建一个只需不到五分钟。 ### 1. 创建目录 {#1-create-the-directory} ```bash mkdir -p ~/.hermes/skills/my-category/my-skill ``` ### 2. 编写 SKILL.md {#2-write-skillmd} ```markdown title="~/.hermes/skills/my-category/my-skill/SKILL.md" --- name: my-skill description: Brief description of what this skill does version: 1.0.0 metadata: hermes: tags: [my-tag, automation] category: my-category --- # 我的Skill ## 何时使用 Use this skill when the user asks about [specific topic] or needs to [specific task]. ## 操作步骤 1. First, check if [prerequisite] is available 2. Run `command --with-flags` 3. Parse the output and present results ## 常见陷阱 - Common failure: [description]. Fix: [solution] - Watch out for [edge case] ## 验证方式 Run `check-command` to confirm the result is correct. ``` ### 3. 添加参考文件(可选) {#3-add-reference-files-optional} 技能可以包含 Agent 按需加载的支持文件: ``` my-skill/ ├── SKILL.md # 主要skill文档 ├── references/ │ ├── api-docs.md # API参考agent可以咨询 │ └── examples.md # 输入示例/outputs ├── templates/ │ └── config.yaml # agent 可以使用的模板文件 └── scripts/ └── setup.sh # agent 可以执行的脚本 ``` 在 `SKILL.md` 中引用这些文件: ```markdown For API details, load the reference: `skill_view("my-skill", "references/api-docs.md")` ``` ### 4. 测试 {#4-test-it} 启动新会话并尝试你的技能: ```bash hermes chat -q "/my-skill help me with the thing" ``` 技能会自动出现——无需注册。只需将其放入 `~/.hermes/skills/` 目录,即可立即生效。 :::info Agent 也可以使用 `skill_manage` 自行创建和更新技能。在解决复杂问题后,Hermes 通常会提议将该方法保存为技能以备下次使用。 ::: --- ## 按平台管理技能 {#per-platform-skill-management} 控制哪些技能在哪些平台上可用: ```bash hermes skills ``` 这将打开一个交互式 TUI 界面,可按平台(CLI、Telegram、Discord 等)启用或禁用技能。当你希望某些技能仅在特定上下文中可用时非常有用——例如,将开发类技能从 Telegram 中移除。 --- ## 技能 vs 记忆 {#skills-vs-memory} 两者都可在会话间持久化,但用途不同: | | 技能 | 记忆 | |---|---|---| | **内容** | 过程性知识——如何做事 | 事实性知识——事物是什么 | | **加载时机** | 按需加载,仅在相关时 | 自动注入每个会话 | | **大小** | 可以很大(数百行) | 应该紧凑(仅关键事实) | | **成本** | 未加载时不消耗令牌 | 每次会话都有少量但持续的令牌消耗 | | **示例** | “如何部署到 Kubernetes” | “用户偏好深色模式,位于 PST 时区” | | **创建者** | 你、Agent 或从中心安装 | Agent 根据对话内容生成 | **经验法则**:如果你会把它放在参考文档中,那就是技能;如果你会把它写在便利贴上,那就是记忆。 --- ## 使用建议 {#tips} **保持技能专注**。一个试图涵盖“全部 DevOps”的技能会过于冗长且模糊。而一个专注于“将 Python 应用部署到 Fly.io”的技能则足够具体,真正有用。 **让 Agent 创建技能**。在完成复杂多步骤任务后,Hermes 通常会提议将该流程保存为技能。请接受——这些由 Agent 生成的技能会完整记录整个工作流,包括途中发现的陷阱。 **使用分类**。将技能组织到子目录中(如 `~/.hermes/skills/devops/`、`~/.hermes/skills/research/` 等)。这有助于保持列表清晰,并帮助 Agent 更快找到相关技能。 **在技能过时后及时更新。** 如果你使用某个技能时遇到该技能未涵盖的问题,请告知 Hermes 用你学到的新知识更新该技能。未得到维护的技能会变成负担。 --- *有关完整的技能参考信息——包括前言字段、条件激活、外部目录等——请参阅 [技能系统](/docs/user-guide/features/skills)。* --- ### xAI Grok OAuth(SuperGrok / X Premium+) - URL: https://hermesagent.org.cn/docs/guides/xai-grok-oauth - Path: guides/xai-grok-oauth.md - Category: guides - Description: 通过 SuperGrok 或 X Premium+ 浏览器 OAuth 登录,在 Hermes Agent 中使用 Grok 模型、xAI 搜索、TTS、图像、视频和转写能力。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/xai-grok-oauth.md - Translated At: 2026-05-30T10:05:00.000+08:00 - Headings: 适合谁? | 登录流程 | 和 X Search 的关系 | 安全注意事项 | 参考链接 # xAI Grok OAuth(SuperGrok / X Premium+) {#xai-grok-oauth} Hermes 支持通过浏览器 OAuth 登录 xAI Grok。你可以使用 SuperGrok 订阅,也可以使用绑定 X Premium+ 的 X 账号。完成登录后,不需要再配置 `XAI_API_KEY`,Hermes 会在后台刷新会话。 同一个 OAuth bearer token 也会被 Hermes 直接复用于 xAI 的其他能力面,包括 TTS、图像生成、视频生成和转写。 ## 适合谁? {#who-should-use} 如果你已经为 SuperGrok 或 X Premium+ 付费,但不想单独申请 xAI API Key,这条路径最合适。 如果你已经有 `XAI_API_KEY`,也可以继续走 API Key 路线。OAuth 的优势是少管理一个 Key,缺点是需要浏览器登录和会话刷新。 ## 登录流程 {#login-flow} 典型流程如下: ```bash hermes setup ``` 在 provider 或 xAI 相关步骤中选择 Grok OAuth,然后按浏览器提示登录 `accounts.x.ai`。登录完成后,Hermes 会保存可刷新的会话信息。 如果你在远程服务器上操作,需要确保 OAuth 回调地址能被浏览器访问。必要时使用 SSH 端口转发。 ## 和 X Search 的关系 {#x-search} 登录完成后,Hermes 的 [X Search](/docs/user-guide/features/x-search) 可以复用同一组 xAI 凭据。也就是说,聊天、X 搜索、TTS 和媒体能力可以走同一个登录关系。 这对日常使用很方便:你不需要为“聊天模型”和“X 搜索工具”维护两套配置。 ## 安全注意事项 {#security} v0.15.0 之后,官方对 xAI OAuth 做了几处加固,包括固定 OAuth `base_url` 到 x.ai origin,避免把 OAuth 凭据转发到恶意主机。 你仍然应该注意: - 不要把 OAuth token、session 文件或调试日志发给他人; - 不要随意设置来源不明的 xAI base URL; - 远程服务器登录时,确认端口转发只暴露给可信环境。 ## 参考链接 {#references} - [官方原文:xAI Grok OAuth](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/guides/xai-grok-oauth.md) - [X Search](/docs/user-guide/features/x-search) - [v0.15.0 xAI 集成说明](/docs/releases/v0-15-0#xai-integration) --- ### 集成 - URL: https://hermesagent.org.cn/docs/integrations - Path: integrations/index.md - Category: integrations - Description: Hermes Agent 可连接外部系统,用于 AI 推理、工具服务器、IDE 工作流、程序化访问等。这些集成扩展了 Hermes 的能力范围,使其可在更多场景中运行。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/integrations/index.md - Translated At: 2026-04-11T03:33:30.338Z - Headings: AI 提供商与路由 | 工具服务器(MCP) | 网络搜索后端 | 浏览器自动化 | 语音与 TTS 提供商 | IDE 与编辑器集成 | 程序化访问 | 记忆与个性化 | 消息平台 | 智能家居自动化 | 插件 | 训练与评估 # 集成 {#integrations} Hermes Agent 可连接外部系统,用于 AI 推理、工具服务器、IDE 工作流、程序化访问等。这些集成扩展了 Hermes 的能力范围,使其可在更多场景中运行。 ## AI 提供商与路由 {#ai-providers--routing} Hermes 原生支持多个 AI 推理提供商。可通过 `hermes model` 交互式配置,或在 `config.yaml` 中设置。 - **[AI 提供商](/docs/user-guide/features/provider-routing)** — OpenRouter、Anthropic、OpenAI、Google 以及任何兼容 OpenAI 的端点。Hermes 可自动检测各提供商的功能,如视觉能力、流式传输和工具使用。 - **[提供商路由](/docs/user-guide/features/provider-routing)** — 对 OpenRouter 请求所使用的底层提供商进行细粒度控制。通过排序、白名单、黑名单和显式优先级排序,优化成本、速度或质量。 - **[备用提供商](/docs/user-guide/features/fallback-providers)** — 当主模型出现错误时,自动切换到备用 LLM 提供商。支持主模型回退以及独立的辅助任务回退(用于视觉、压缩和网页提取)。 ## 工具服务器(MCP) {#tool-servers-mcp} - **[MCP 服务器](/docs/user-guide/features/mcp)** — 通过 Model Context Protocol 连接 Hermes 与外部工具服务器。无需编写原生 Hermes 工具,即可访问 GitHub、数据库、文件系统、浏览器栈、内部 API 等工具。支持 stdio 和 SSE 传输方式,并支持按服务器过滤可用 Tool,以及基于能力的资源/提示注册。 ## 网络搜索后端 {#web-search-backends} `web_search` 和 `web_extract` 工具支持四种后端提供商,可通过 `config.yaml` 或 `hermes tools` 配置: | 后端 | 环境变量 | 搜索 | 提取 | 爬取 | |------|----------|------|------|------| | **Firecrawl**(默认) | `FIRECRAWL_API_KEY` | ✔ | ✔ | ✔ | | **Parallel** | `PARALLEL_API_KEY` | ✔ | ✔ | — | | **Tavily** | `TAVILY_API_KEY` | ✔ | ✔ | ✔ | | **Exa** | `EXA_API_KEY` | ✔ | ✔ | — | 快速设置示例: ```yaml web: backend: firecrawl # firecrawl |平行|塔维利 |埃克萨 ``` 如果未设置 `web.backend`,系统将根据可用的 API 密钥自动检测后端。也支持通过 `FIRECRAWL_API_URL` 自托管 Firecrawl。 ## 浏览器自动化 {#browser-automation} Hermes 内置完整的浏览器自动化功能,提供多种后端选项,用于网站导航、表单填写和信息提取: - **Browserbase** — 受管理的云浏览器,具备反机器人防护、验证码破解和住宅代理功能 - **Browser Use** — 另一种云浏览器提供商 - **本地 Chrome(通过 CDP)** — 使用 `/browser connect` 连接到正在运行的 Chrome 实例 - **本地 Chromium** — 通过 `agent-browser` CLI 使用无头本地浏览器 有关设置与使用,请参阅 [浏览器自动化](/docs/user-guide/features/browser)。 ## 语音与 TTS 提供商 {#voice--tts-providers} 跨所有消息平台的文本转语音(TTS)与语音转文本(STT): | 提供商 | 质量 | 成本 | API 密钥 | |--------|------|------|----------| | **Edge TTS**(默认) | 良好 | 免费 | 无需 | | **ElevenLabs** | 优秀 | 付费 | `ELEVENLABS_API_KEY` | | **OpenAI TTS** | 良好 | 付费 | `VOICE_TOOLS_OPENAI_KEY` | | **MiniMax** | 良好 | 付费 | `MINIMAX_API_KEY` | | **NeuTTS** | 良好 | 免费 | 无需 | 语音转文本支持三个提供商:本地 Whisper(免费,本地运行)、Groq(快速云端)和 OpenAI Whisper API。语音消息转录功能支持 Telegram、Discord、WhatsApp 及其他消息平台。详情请参阅 [语音与 TTS](/docs/user-guide/features/tts) 和 [语音模式](/docs/user-guide/features/voice-mode)。 ## IDE 与编辑器集成 {#ide--editor-integration} - **[IDE 集成(ACP)](/docs/user-guide/features/acp)** — 在支持 ACP 的编辑器(如 VS Code、Zed、JetBrains 系列)中使用 Hermes Agent。Hermes 作为 ACP 服务器运行,在编辑器内渲染聊天消息、工具活动、文件差异和终端命令。 ## 程序化访问 {#programmatic-access} - **[API 服务器](/docs/user-guide/features/api-server)** — 将 Hermes 暴露为兼容 OpenAI 的 HTTP 端点。任何支持 OpenAI 格式的前端(如 Open WebUI、LobeChat、LibreChat、NextChat、ChatBox)均可连接并使用 Hermes 作为后端,享受其完整工具集。 ## 记忆与个性化 {#memory--personalization} - **[内置记忆](/docs/user-guide/features/memory)** — 通过 `MEMORY.md` 和 `USER.md` 文件实现持久化、有条理的记忆。Agent 维护有限范围的个人笔记和用户资料数据,跨会话保持。 - **[记忆提供者](/docs/user-guide/features/memory-providers)** — 插入外部记忆后端以实现更深层次的个性化。支持七种提供商:Honcho(辩证推理)、OpenViking(分层检索)、Mem0(云端提取)、Hindsight(知识图谱)、Holographic(本地 SQLite)、RetainDB(混合搜索)和 ByteRover(基于 CLI)。 ## 消息平台 {#messaging-platforms} Hermes 作为网关机器人在 15+ 消息平台上运行,所有配置均通过相同的 `gateway` 子系统完成。 - **[Telegram](/docs/user-guide/messaging/telegram)**,**[Discord](/docs/user-guide/messaging/discord)**,**[Slack](/docs/user-guide/messaging/slack)**,**[WhatsApp](/docs/user-guide/messaging/whatsapp)**,**[Signal](/docs/user-guide/messaging/signal)**,**[Matrix](/docs/user-guide/messaging/matrix)**,**[Mattermost](/docs/user-guide/messaging/mattermost)**,**[Email](/docs/user-guide/messaging/email)**,**[SMS](/docs/user-guide/messaging/sms)**,**[DingTalk](/docs/user-guide/messaging/dingtalk)**,**[Feishu/Lark](/docs/user-guide/messaging/feishu)**,**[WeCom](/docs/user-guide/messaging/wecom)**,**[Weixin](/docs/user-guide/messaging/weixin)**,**[BlueBubbles](/docs/user-guide/messaging/bluebubbles)**,**[Home Assistant](/docs/user-guide/messaging/homeassistant)**,**[Webhooks](/docs/user-guide/messaging/webhooks)** 有关平台对比表和设置指南,请参阅 [消息网关概览](/docs/user-guide/messaging)。 ## 智能家居自动化 {#home-automation} - **[Home Assistant](/docs/user-guide/messaging/homeassistant)** — 通过四个专用工具(`ha_list_entities`、`ha_get_state`、`ha_list_services`、`ha_call_service`)控制智能家居设备。当配置 `HASS_TOKEN` 时,Home Assistant 工具集将自动激活。 ## 插件 {#plugins} - **[插件系统](/docs/user-guide/features/plugins)** — 在不修改核心代码的情况下,通过自定义工具、生命周期钩子和 CLI 命令扩展 Hermes。插件从 `~/.hermes/plugins/`、项目本地的 `.hermes/plugins/` 以及 pip 安装的入口点中发现。 - **[构建插件](/docs/guides/build-a-hermes-plugin)** — 创建 Hermes 插件(包含工具、钩子和 CLI 命令)的逐步指南。 ## 训练与评估 {#training--evaluation} - **[强化学习训练](/docs/reference/toolsets-reference)** — 从 Agent 会话中生成轨迹数据,用于强化学习和模型微调。支持 Atropos 环境,并可自定义奖励函数。 - **[批处理](/docs/user-guide/features/batch-processing)** — 并行运行 Agent 处理数百个提示,生成结构化的 ShareGPT 格式轨迹数据,用于训练数据生成或评估。 --- ### Nous Portal - URL: https://hermesagent.org.cn/docs/integrations/nous-portal - Path: integrations/nous-portal.md - Category: integrations - Description: Nous Portal 是运行 Hermes Agent 的官方推荐入口:一个订阅覆盖 300+ 模型、Tool Gateway 与 Nous Chat。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/integrations/nous-portal.md - Translated At: 2026-05-30T10:05:00.000+08:00 - Headings: Portal 解决什么问题? | 包含哪些能力? | 推荐使用流程 | 什么时候仍然需要其他 provider? | 参考链接 # Nous Portal {#nous-portal} [Nous Portal](https://portal.nousresearch.com) 是 Nous Research 的统一订阅入口,也是官方推荐的 Hermes Agent 运行方式。它把模型、Tool Gateway 和 Nous Chat 放在一个 OAuth 登录后面,减少你分别管理 OpenAI、Anthropic、搜索 API、图像生成和浏览器 provider 的负担。 如果只想先跑起来,最快路径是: ```bash hermes setup --portal ``` 这个命令会打开 Portal OAuth,把 Nous 写成默认推理 provider,并开启 Tool Gateway。完成后就可以直接运行: ```bash hermes chat ``` ## Portal 解决什么问题? {#why-portal} 没有 Portal 时,你通常需要分别准备模型 API Key、搜索 API Key、图像生成 Key、浏览器服务 Key,还要处理额度、账单和配置文件。 Portal 的价值是把这些入口收拢起来。可以把它理解为 Hermes 的“总插座”:模型和工具能力通过同一个订阅和登录关系接入,配置更少,排错路径也更短。 ## 包含哪些能力? {#capabilities} 官方文档强调三类能力: - **300+ 模型**:通过一个订阅访问多个前沿模型; - **Tool Gateway**:将网页搜索、图像生成、TTS、浏览器自动化等工具能力接入 Hermes; - **Nous Chat**:同一账号体系下的聊天产品入口。 Portal 订阅用户还可以获得 token-billed provider 的折扣,具体以官方 Portal 页面为准。 ## 推荐使用流程 {#recommended-flow} 新用户可以按下面顺序配置: 1. 安装 Hermes Agent。 2. 运行 `hermes setup --portal`。 3. 在浏览器中完成 OAuth 登录。 4. 运行 `hermes portal status` 检查 provider 和 Tool Gateway 状态。 5. 运行 `hermes chat` 开始第一轮对话。 如果你在远程服务器或 SSH 环境中使用,需要浏览器回调时可以参考 [OAuth over SSH](/docs/guides/oauth-over-ssh) 或官方 SSH 端口转发说明。 ## 什么时候仍然需要其他 provider? {#when-other-providers} Portal 是推荐入口,但不是唯一入口。你仍然可以同时配置 OpenRouter、OpenAI-compatible、本地模型或 xAI OAuth。常见原因包括: - 公司内部已有模型网关; - 某个模型只在特定 provider 可用; - 本地开发需要离线或低成本模型; - 想为辅助模型配置更便宜的 provider。 Hermes 的 provider 路由允许你混合使用这些来源。 ## 参考链接 {#references} - [官方原文:Nous Portal](https://github.com/NousResearch/hermes-agent/blob/main/website/docs/integrations/nous-portal.md) - [运行 Hermes Agent with Nous Portal](/docs/guides/run-hermes-with-nous-portal) - [配置模型](/docs/user-guide/configuring-models) --- ### AI 提供商 - URL: https://hermesagent.org.cn/docs/integrations/providers - Path: integrations/providers.md - Category: integrations - Description: 本页介绍如何为 Hermes Agent 配置推理提供商——从 OpenRouter 和 Anthropic 等云 API,到 Ollama 和 vLLM 等自托管端点,再到高级路由和降级配置。使用 Hermes 至少需要配置一个提供商。 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/integrations/providers.md - Translated At: 2026-04-11T03:35:27.393Z - Headings: 推理提供商 | Anthropic(原生) | GitHub Copilot | 一级中文 AI 服务商 | xAI (Grok) 提示缓存 | Hugging Face 推理提供者 | 自定义与自托管 LLM 提供商 | 通用设置 | 使用 /model 切换模型 | Ollama — 本地模型,零配置 | vLLM — 高性能 GPU 推理 | SGLang — 基于 RadixAttention 的快速服务 # AI 提供商 {#ai-providers} 本页介绍如何为 Hermes Agent 配置推理提供商——从 OpenRouter 和 Anthropic 等云 API,到 Ollama 和 vLLM 等自托管端点,再到高级路由和降级配置。使用 Hermes 至少需要配置一个提供商。 ## 推理提供商 {#inference-providers} 您需要至少一种方式连接到大语言模型(LLM)。可使用 `hermes model` 命令交互式切换提供商和模型,或直接进行配置: | 提供商 | 设置方式 | |--------|----------| | **Nous Portal** | `hermes model`(OAuth,订阅制) | | **OpenAI Codex** | `hermes model`(ChatGPT OAuth,使用 Codex 模型) | | **GitHub Copilot** | `hermes model`(OAuth 设备码流程,`COPILOT_GITHUB_TOKEN`、`GH_TOKEN` 或 `gh auth token`) | | **GitHub Copilot ACP** | `hermes model`(启动本地 `copilot --acp --stdio`) | | **Anthropic** | `hermes model`(通过 Claude Code 认证使用 Claude Pro/Max,或 Anthropic API 密钥,或手动设置令牌) | | **OpenRouter** | 在 `~/.hermes/.env` 中设置 `OPENROUTER_API_KEY` | | **AI Gateway** | 在 `~/.hermes/.env` 中设置 `AI_GATEWAY_API_KEY`(提供者:`ai-gateway`) | | **z.ai / GLM** | 在 `~/.hermes/.env` 中设置 `GLM_API_KEY`(提供者:`zai`) | | **Kimi / Moonshot** | 在 `~/.hermes/.env` 中设置 `KIMI_API_KEY`(提供者:`kimi-coding`) | | **MiniMax** | 在 `~/.hermes/.env` 中设置 `MINIMAX_API_KEY`(提供者:`minimax`) | | **MiniMax 中国区** | 在 `~/.hermes/.env` 中设置 `MINIMAX_CN_API_KEY`(提供者:`minimax-cn`) | | **阿里云** | 在 `~/.hermes/.env` 中设置 `DASHSCOPE_API_KEY`(提供者:`alibaba`,别名:`dashscope`、`qwen`) | | **Kilo Code** | 在 `~/.hermes/.env` 中设置 `KILOCODE_API_KEY`(提供者:`kilocode`) | | **OpenCode Zen** | 在 `~/.hermes/.env` 中设置 `OPENCODE_ZEN_API_KEY`(提供者:`opencode-zen`) | | **OpenCode Go** | 在 `~/.hermes/.env` 中设置 `OPENCODE_GO_API_KEY`(提供者:`opencode-go`) | | **DeepSeek** | 在 `~/.hermes/.env` 中设置 `DEEPSEEK_API_KEY`(提供者:`deepseek`) | | **Hugging Face** | 在 `~/.hermes/.env` 中设置 `HF_TOKEN`(提供者:`huggingface`,别名:`hf`) | | **Google / Gemini** | 在 `~/.hermes/.env` 中设置 `GOOGLE_API_KEY`(或 `GEMINI_API_KEY`)(提供者:`gemini`) | | **自定义端点** | `hermes model` → 选择“自定义端点”(保存在 `config.yaml` 中) | :::tip 模型密钥别名 在 `model:` 配置节中,您可以使用 `default:` 或 `model:` 作为模型 ID 的键名。`model: { default: my-model }` 和 `model: { model: my-model }` 两种写法效果完全相同。 ::: :::info Codex 说明 OpenAI Codex 提供商通过设备码进行认证(打开一个 URL,输入代码)。Hermes 将生成的凭据存储在自己的认证存储中,路径为 `~/.hermes/auth.json`,并且当存在时可从 `~/.codex/auth.json` 导入现有的 Codex CLI 凭据。无需安装 Codex CLI。 ::: :::warning 即使使用 Nous Portal、Codex 或自定义端点,某些工具(如视觉、网页摘要、MoA)仍会使用一个独立的“辅助”模型——默认通过 OpenRouter 使用 Gemini Flash。设置 `OPENROUTER_API_KEY` 可自动启用这些工具。您也可以配置这些工具使用的模型和提供商——详见 [辅助模型](/docs/user-guide/configuration#auxiliary-models)。 ::: ### Anthropic(原生) {#anthropic-native} 直接通过 Anthropic API 使用 Claude 模型——无需 OpenRouter Agent。支持三种认证方式: ```bash # 使用 API 密钥(按 token 付费) export ANTHROPIC_API_KEY=*** hermes chat --provider anthropic --model claude-sonnet-4-6 # 首选:通过“0”进行身份验证 # Hermes 将在可用时直接使用 Claude Code 的凭证存储 hermes model # 使用设置令牌手动覆盖(后备“0”遗留) export ANTHROPIC_TOKEN=*** # setup-token 或手动 OAuth token hermes chat --provider anthropic # 自动检测 Claude Code 凭证(如果您已经使用 Claude Code) hermes chat --provider anthropic # 自动读取Claude Code凭证文件 ``` 当通过 `hermes model` 选择 Anthropic OAuth 时,Hermes 优先使用 Claude Code 自身的凭证存储,而不是将令牌复制到 `~/.hermes/.env`。这能保持可刷新的 Claude 凭证持续可刷新。 或永久设置: ```yaml model: provider: "anthropic" default: "claude-sonnet-4-6" ``` :::tip 别名 `--provider claude` 和 `--provider claude-code` 也可作为 `--provider anthropic` 的简写。 ::: ### GitHub Copilot {#github-copilot} Hermes 将 GitHub Copilot 作为一级提供商支持,提供两种模式: **`copilot` —— 直接使用 Copilot API**(推荐)。利用您的 GitHub Copilot 订阅,通过 Copilot API 访问 GPT-5.x、Claude、Gemini 等多种模型。 ```bash hermes chat --provider copilot --model gpt-5.4 ``` **认证选项**(按以下顺序检查): 1. `COPILOT_GITHUB_TOKEN` 环境变量 2. `GH_TOKEN` 环境变量 3. `GITHUB_TOKEN` 环境变量 4. `gh auth token` CLI 回退 如果未找到令牌,`hermes model` 将提供 **OAuth 设备码登录**——与 Copilot CLI 和 opencode 使用相同的流程。 :::warning 令牌类型 Copilot API **不支持**传统的个人访问令牌(`ghp_*`)。支持的令牌类型: | 类型 | 前缀 | 获取方式 | |------|--------|------------| | OAuth 令牌 | `gho_` | `hermes model` → GitHub Copilot → 使用 GitHub 登录 | | 细粒度 PAT | `github_pat_` | GitHub 设置 → 开发者设置 → 细粒度令牌(需具备 **Copilot Requests** 权限) | | GitHub App 令牌 | `ghu_` | 通过 GitHub App 安装获取 | 如果您的 `gh auth token` 返回的是 `ghp_*` 令牌,请使用 `hermes model` 通过 OAuth 进行认证。 ::: **API 路由**:GPT-5+ 模型(除 `gpt-5-mini` 外)自动使用 Responses API。其余所有模型(GPT-4o、Claude、Gemini 等)使用 Chat Completions。模型会从实时 Copilot 目录中自动检测。 **`copilot-acp` —— Copilot ACP Agent 后端**。作为子进程启动本地 Copilot CLI: ```bash hermes chat --provider copilot-acp --model copilot-acp # 需要 PATH 中的 GitHub Copilot CLI 和现有的 `copilot login` session ``` **永久配置:** ```yaml model: provider: "copilot" default: "gpt-5.4" ``` | 环境变量 | 说明 | |---------------------|-------------| | `COPILOT_GITHUB_TOKEN` | Copilot API 的 GitHub 令牌(优先级最高) | | `HERMES_COPILOT_ACP_COMMAND` | 覆盖 Copilot CLI 二进制文件路径(默认:`copilot`) | | `HERMES_COPILOT_ACP_ARGS` | 覆盖 ACP 参数(默认:`--acp --stdio`) | ### 一级中文 AI 服务商 {#first-class-chinese-ai-providers} 这些服务商已内置支持,并拥有专用的提供者 ID。设置 API 密钥后,使用 `--provider` 选择: ```bash # z.ai / 智普AI GLM hermes chat --provider zai --model glm-5 # 要求:“0”中的“1” # 基米 / 登月人工智能 hermes chat --provider kimi-coding --model kimi-for-coding # 要求:“0”中的“1” # MiniMax(全局端点) hermes chat --provider minimax --model MiniMax-M2.7 # 要求:“0”中的“1” # MiniMax(中国端点) hermes chat --provider minimax-cn --model MiniMax-M2.7 # 要求:“0”中的“1” # 阿里云 / DashScope (Qwen models) hermes chat --provider alibaba --model qwen3.5-plus # 要求:“0”中的“1” ``` 或在 `config.yaml` 中永久设置提供者: ```yaml model: provider: "zai" # 或:kimi编码、minimax、minimax-cn、阿里巴巴 default: "glm-5" ``` 可通过 `GLM_BASE_URL`、`KIMI_BASE_URL`、`MINIMAX_BASE_URL`、`MINIMAX_CN_BASE_URL` 或 `DASHSCOPE_BASE_URL` 环境变量覆盖基础 URL。 :::note Z.AI 端点自动检测 使用 Z.AI / GLM 提供者时,Hermes 会自动探测多个端点(全球、中国、代码专用变体),以找到可接受你 API 密钥的端点。你无需手动设置 `GLM_BASE_URL` —— 工作中的端点将被自动探测并缓存。 ::: ### xAI (Grok) 提示缓存 {#xai-grok-prompt-caching} 当使用 xAI 作为提供者(任何包含 `x.ai` 的基础 URL)时,Hermes 会自动启用提示缓存,通过在每个 API 请求中发送 `x-grok-conv-id` 头部来实现。这会将请求路由到会话期间的同一服务器,使 xAI 的基础设施能够重用缓存的系统提示和对话历史。 无需任何配置 —— 只要检测到 xAI 端点且存在会话 ID,缓存就会自动激活。这可显著降低多轮对话的延迟和成本。 ### Hugging Face 推理提供者 {#hugging-face-inference-providers} [Hugging Face 推理提供者](https://huggingface.co/docs/inference-providers) 通过统一的 OpenAI 兼容端点(`router.huggingface.co/v1`)将请求路由至 20 多个开源模型。请求会自动路由到最快可用的后端(如 Groq、Together、SambaNova 等),并支持自动故障转移。 ```bash # 使用任何可用的 model hermes chat --provider huggingface --model Qwen/Qwen3-235B-A22B-Thinking-2507 # 要求:“0”中的“1” # 短别名 hermes chat --provider hf --model deepseek-ai/DeepSeek-V3.2 ``` 或在 `config.yaml` 中永久设置: ```yaml model: provider: "huggingface" default: "Qwen/Qwen3-235B-A22B-Thinking-2507" ``` 在 [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) 获取你的令牌 —— 确保启用“对推理提供者发起调用”权限。免费套餐包含(每月 $0.10 信用额度,提供方费率无加价)。 你可以在模型名称后附加路由后缀:`:fastest`(默认)、`:cheapest`,或 `:provider_name` 以强制使用特定后端。 基础 URL 可通过 `HF_BASE_URL` 覆盖。 ## 自定义与自托管 LLM 提供商 {#custom--self-hosted-llm-providers} Hermes Agent 可与 **任何 OpenAI 兼容的 API 端点** 配合使用。只要服务器实现了 `/v1/chat/completions`,你就可以将其指向 Hermes。这意味着你可以使用本地模型、GPU 推理服务器、多提供者路由器或任何第三方 API。 ### 通用设置 {#general-setup} 配置自定义端点的三种方式: **交互式设置(推荐):** ```bash hermes model # 选择“0” # 输入:API 底座 URL、API 密钥、Model 名称 ``` **手动配置(`config.yaml`):** ```yaml # 在“0”中 model: default: your-model-name provider: custom base_url: http://localhost:8000/v1 api_key: your-key-or-leave-empty-for-local ``` :::warning 旧版环境变量 `.env` 中的 `OPENAI_BASE_URL` 和 `LLM_MODEL` 已**移除**。Hermes 的任何部分均不再读取它们 —— `config.yaml` 是模型和端点配置的唯一来源。如果你的 `.env` 中存在过时条目,将在下次执行 `hermes setup` 或配置迁移时自动清除。请使用 `hermes model` 或直接编辑 `config.yaml`。 ::: 两种方法均会持久化至 `config.yaml`,该文件是模型、提供者和基础 URL 的唯一真相来源。 ### 使用 `/model` 切换模型 {#switching-models-with-model} 自定义端点配置完成后,你可以在会话中随时切换模型: ``` /model custom:qwen-2.5 # 在您的自定义端点上切换到 model /model custom # 从端点自动检测model /model openrouter:claude-sonnet-4 # 切换回云端 provider ``` 如果你已配置了**命名的自定义提供者**(见下文),请使用三重语法: ``` /model custom:local:qwen-2.5 # 使用“0”自定义“1”和“2”“3”-2.5 /model custom:work:llama3 # 将 "work" 自定义 Provider 与 llama3 一起使用 ``` 切换提供者时,Hermes 会将基础 URL 和提供者持久化到配置中,确保更改在重启后仍然有效。当从自定义端点切换到内置提供者时,过时的基础 URL 会自动清除。 :::tip `/model custom`(无模型名称)会查询你的端点的 `/models` API,并在仅加载一个模型时自动选择该模型。适用于运行单个模型的本地服务器。 ::: 以下所有操作均遵循相同模式 —— 只需更改 URL、密钥和模型名称即可。 --- ### Ollama — 本地模型,零配置 {#ollama-—-local-models-zero-config} [Ollama](https://ollama.com/) 通过一条命令即可在本地运行开源权重模型。适用于:快速本地实验、对隐私敏感的工作、离线使用。支持通过 OpenAI 兼容 API 调用工具。 ```bash # 安装并运行 model ollama pull qwen2.5-coder:32b ollama serve # 在端口 11434 上启动 ``` 然后配置 Hermes: ```bash hermes model # 选择“0” # 输入“1”:“0” # 跳过API密钥(Ollama不需要) # 输入 模型 名称(例如 qwen2.5-coder:32b) ``` 或直接配置 `config.yaml`: ```yaml model: default: qwen2.5-coder:32b provider: custom base_url: http://localhost:11434/v1 context_length: 32768 # 请参阅下面的警告 ``` :::caution Ollama 默认上下文长度极低 Ollama **不会**默认使用模型的完整上下文窗口。根据你的显存情况,默认值如下: | 可用显存 | 默认上下文 | |----------------|----------------| | 少于 24 GB | **4,096 个 token** | | 24–48 GB | 32,768 个 token | | 48 GB 以上 | 256,000 个 token | 对于需要工具调用的 Agent 使用,**至少需要 16k–32k 的上下文**。在 4k 时,系统提示 + 工具模式本身可能就填满窗口,导致没有空间用于对话。 **如何增加上下文长度**(任选其一): ```bash # 选项 1:通过环境变量设置服务器范围(推荐) OLLAMA_CONTEXT_LENGTH=32768 ollama serve # 选项 2:对于 systemd 管理的 Ollama sudo systemctl edit ollama.service # 添加:环境="OLLAMA_CONTEXT_LENGTH=32768" # 然后: sudo systemctl daemon-reload && sudo systemctl restart ollama # 选项 3:将其烘焙为自定义 模型(持久 per-模型) echo -e "FROM qwen2.5-coder:32b\nPARAMETER num_ctx 32768" > Modelfile ollama create qwen2.5-coder-32k -f Modelfile ``` **你无法通过 OpenAI 兼容 API**(`/v1/chat/completions`)**设置上下文长度**。必须在服务器端或通过 Modelfile 进行配置。这是将 Ollama 与 Hermes 等工具集成时最常见的困惑来源。 ::: **验证你的上下文长度是否正确设置:** ```bash ollama ps # 查看 CONTEXT 列 — 它应该显示您的配置值 ``` :::tip 使用 `ollama list` 查看可用模型。通过 `ollama pull ` 从 [Ollama 库](https://ollama.com/library) 下载任意模型。Ollama 会自动处理 GPU 分载——大多数设置无需额外配置。 ::: --- ### vLLM — 高性能 GPU 推理 {#vllm-—-high-performance-gpu-inference} [vLLM](https://docs.vllm.ai/) 是生产环境 LLM 服务的标准选择。适用于:在 GPU 硬件上实现最大吞吐量、服务大模型、连续批处理。 ```bash pip install vllm vllm serve meta-llama/Llama-3.1-70B-Instruct \ --port 8000 \ --max-model-len 65536 \ --tensor-parallel-size 2 \ --enable-auto-tool-choice \ --tool-call-parser hermes ``` 然后配置 Hermes: ```bash hermes model # 选择“0” # 输入网址:http://localhost:8000/v1 # 跳过 API 密钥(如果您用 --api-key 配置了 vLLM,则输入 1) # 输入模型名称:meta-flame/Llama-3.1-70B-Instruct ``` **上下文长度**:vLLM 默认读取模型的 `max_position_embeddings`。如果超过 GPU 内存,会报错并提示你降低 `--max-model-len`。你也可以使用 `--max-model-len auto` 自动找出能适配的最大值。设置 `--gpu-memory-utilization 0.95`(默认为 0.9)可进一步压缩上下文以节省显存。 **工具调用需要显式启用标志:** | 标志 | 用途 | |------|------| | `--enable-auto-tool-choice` | 用于支持 `tool_choice: "auto"`(Hermes 中的默认行为) | | `--tool-call-parser ` | 模型工具调用格式的解析器 | 支持的解析器:`hermes`(Qwen 2.5,Hermes 2/3)、`llama3_json`(Llama 3.x)、`mistral`、`deepseek_v3`、`deepseek_v31`、`xlam`、`pythonic`。若未使用这些标志,工具调用将无法工作——模型会将工具调用输出为文本。 :::tip vLLM 支持人类可读的大小单位:`--max-model-len 64k`(小写 k = 1000,大写 K = 1024)。 ::: --- ### SGLang — 基于 RadixAttention 的快速服务 {#sglang-—-fast-serving-with-radixattention} [SGLang](https://github.com/sgl-project/sglang) 是 vLLM 的替代方案,采用 RadixAttention 实现 KV 缓存复用。适用于:多轮对话(前缀缓存)、约束解码、结构化输出。 ```bash pip install "sglang[all]" python -m sglang.launch_server \ --model meta-llama/Llama-3.1-70B-Instruct \ --port 30000 \ --context-length 65536 \ --tp 2 \ --tool-call-parser qwen ``` 然后配置 Hermes: ```bash hermes model # 选择“0” # 输入“1”:“0” # 输入模型名称:meta-flame/Llama-3.1-70B-Instruct ``` **上下文长度**:SGLang 默认从模型配置中读取。可使用 `--context-length` 覆盖。若需超过模型声明的最大值,请设置 `SGLANG_ALLOW_OVERWRITE_LONGER_CONTEXT_LEN=1`。 **工具调用**:使用 `--tool-call-parser` 并配合对应模型家族的解析器:`qwen`(Qwen 2.5)、`llama3`、`llama4`、`deepseekv3`、`mistral`、`glm`。缺少此标志时,工具调用将以纯文本形式返回。 :::caution SGLang 默认最大输出 token 数为 128 如果响应看起来被截断,请在请求中添加 `max_tokens`,或在服务器上设置 `--default-max-tokens`。若请求中未指定,SGLang 的默认值仅为每响应 128 个 token。 ::: --- ### llama.cpp / llama-server — CPU 与 Metal 推理 {#llamacpp--llama-server-—-cpu--metal-inference} [llama.cpp](https://github.com/ggml-org/llama.cpp) 可在 CPU、Apple Silicon(Metal)和消费级 GPU 上运行量化模型。适用于:无需数据中心 GPU 运行模型、Mac 用户、边缘部署。 ```bash # 构建并启动llama-server cmake -B build && cmake --build build --config Release ./build/bin/llama-server \ --jinja -fa \ -c 32768 \ -ngl 99 \ -m models/qwen2.5-coder-32b-instruct-Q4_K_M.gguf \ --port 8080 --host 0.0.0.0 ``` **上下文长度(`-c`)**:近期版本默认值为 `0`,表示从 GGUF 元数据中读取模型训练时的上下文长度。对于训练上下文超过 128k 的模型,这可能导致内存溢出(OOM),因尝试分配完整的 KV 缓存。请显式设置 `-c` 为所需值(32k–64k 是 Agent 使用的好范围)。若使用并行槽位(`-np`),总上下文将分配给各槽位——例如 `-c 32768 -np 4` 时,每个槽位仅获得 8k。 然后配置 Hermes 指向它: ```bash hermes model # 选择“0” # 输入“1”:“0” # 跳过API密钥(本地服务器不需要) # 输入 model 名称 — 或留空以自动检测是否仅加载一个 model ``` 这会将端点保存至 `config.yaml`,以在会话间持久化。 :::caution `--jinja` 对工具调用是必需的 若缺少 `--jinja`,llama-server 会完全忽略 `tools` 参数。模型会尝试在响应文本中写入 JSON 形式的工具调用,但 Hermes 无法识别为工具调用——你将看到原始 JSON 如 `{"name": "web_search", ...}` 作为消息打印,而非实际搜索。 原生工具调用支持(最佳性能):Llama 3.x、Qwen 2.5(含 Coder)、Hermes 2/3、Mistral、DeepSeek、Functionary。其他所有模型使用通用处理器,虽可用但效率较低。完整支持列表请参见 [llama.cpp 函数调用文档](https://github.com/ggml-org/llama.cpp/blob/master/docs/function-calling)。 可通过检查 `http://localhost:8080/props` 验证工具支持是否启用——`chat_template` 字段应存在。 ::: :::tip 从 [Hugging Face](https://huggingface.co/models?library=gguf) 下载 GGUF 模型。Q4_K_M 量化格式在质量与内存占用之间提供了最佳平衡。 ::: --- ### LM Studio — 带本地模型的桌面应用 {#lm-studio-—-desktop-app-with-local-models} [LM Studio](https://lmstudio.ai/) 是一款带有图形界面的桌面应用程序,用于运行本地模型。适用于:偏好可视化界面的用户、快速测试模型、macOS/Windows/Linux 上的开发者。 从 LM Studio 应用启动服务器(开发者选项卡 → 启动服务器),或使用命令行: ```bash lms server start # 在端口 1234 上启动 lms load qwen2.5-coder --context-length 32768 ``` 然后配置 Hermes: ```bash hermes model # 选择“0” # 输入“1”:“0” # 跳过API密钥(LM Studio不需要) # 输入model名称 ``` :::caution 上下文长度默认值通常为 2048 LM Studio 会从模型元数据中读取上下文长度,但许多 GGUF 模型报告的默认值较低(2048 或 4096)。**请始终在 LM Studio 模型设置中显式设置上下文长度**: 1. 点击模型选择器旁边的齿轮图标 2. 将“上下文长度”设置为至少 16384(建议设置为 32768) 3. 重新加载模型以使更改生效 或者使用命令行:`lms load model-name --context-length 32768` 要为每个模型设置持久化默认值:我的模型标签页 → 模型旁边的齿轮图标 → 设置上下文大小。 ::: **工具调用**:自 LM Studio 0.3.6 起支持。经过原生工具调用训练的模型(如 Qwen 2.5、Llama 3.x、Mistral、Hermes)会自动检测并显示工具徽章。其他模型将使用通用回退方案,可能可靠性较低。 --- ### WSL2 网络配置(Windows 用户) {#wsl2-networking-windows-users} 由于 Hermes Agent 需要 Unix 环境,Windows 用户需在 WSL2 中运行它。如果你的模型服务器(Ollama、LM Studio 等)运行在 **Windows 主机**上,需要桥接网络差距——WSL2 使用虚拟网络适配器并拥有独立子网,因此 WSL2 内部的 `localhost` 指向的是 Linux 虚拟机,**而非** Windows 主机。 :::tip 两者都在 WSL2?没问题。 如果模型服务器也运行在 WSL2 中(如 vLLM、SGLang 和 llama-server 常见情况),`localhost` 可正常工作——它们共享同一网络命名空间。可跳过本节。 ::: #### 方案一:镜像网络模式(推荐) {#option-1-mirrored-networking-mode-recommended} 适用于 **Windows 11 22H2 及以上版本**,镜像模式可实现 Windows 与 WSL2 之间的双向 `localhost` 通信——最简单的解决方案。 1. 创建或编辑 `%USERPROFILE%\.wslconfig`(例如 `C:\Users\YourName\.wslconfig`): ```ini [wsl2] networkingMode=mirrored ``` 2. 从 PowerShell 重启 WSL: ```powershell wsl --shutdown ``` 3. 重新打开你的 WSL2 终端。现在 `localhost` 可访问 Windows 服务: ```bash curl http://localhost:11434/v1/models # Ollama on Windows — works ``` :::note Hyper-V 防火墙 在某些 Windows 11 版本中,Hyper-V 防火墙默认会阻止镜像连接。如果启用镜像模式后 `localhost` 仍无法使用,请在 **管理员 PowerShell** 中运行以下命令: ```powershell Set-NetFirewallHyperVVMSetting -Name '{40E0AC32-46A5-438A-A0B2-2B479E8F2E90}' -DefaultInboundAction Allow ``` ::: #### 方案二:使用 Windows 主机 IP(Windows 10 / 较旧版本) {#option-2-use-the-windows-host-ip-windows-10--older-builds} 若无法使用镜像模式,请在 WSL2 中查找 Windows 主机 IP,并使用该 IP 替代 `localhost`: ```bash # 获取Windows主机IP(WSL2的虚拟网络默认gateway) ip route show | grep -i default | awk '{ print $3 }' # 示例输出:172.29.192.1 ``` 在 Hermes 配置中使用该 IP: ```yaml model: default: qwen2.5-coder:32b provider: custom base_url: http://172.29.192.1:11434/v1 # Windows 主机 IP,而不是本地主机 ``` :::tip 动态辅助工具 主机 IP 在 WSL2 重启后可能发生变化。你可以在 shell 中动态获取它: ```bash export WSL_HOST=$(ip route show | grep -i default | awk '{ print $3 }') echo "Windows host at: $WSL_HOST" curl http://$WSL_HOST:11434/v1/models # 测试Ollama ``` 或使用机器的 mDNS 名称(需在 WSL2 中安装 `libnss-mdns`): ```bash sudo apt install libnss-mdns curl http://$(hostname).local:11434/v1/models ``` ::: #### 服务器绑定地址(NAT 模式必需) {#server-bind-address-required-for-nat-mode} 如果你使用 **方案二**(NAT 模式,使用主机 IP),则运行在 Windows 上的模型服务器必须接受来自 `127.0.0.1` 以外的连接。默认情况下,大多数服务器仅监听 localhost——在 NAT 模式下,WSL2 的连接来自不同的虚拟子网,将被拒绝。在镜像模式下,`localhost` 会直接映射,因此默认的 `127.0.0.1` 绑定仍可正常工作。 | 服务器 | 默认绑定地址 | 如何修复 | |--------|-------------|------------| | **Ollama** | `127.0.0.1` | 启动 Ollama 前设置 `OLLAMA_HOST=0.0.0.0` 环境变量(Windows 系统设置 → 环境变量,或编辑 Ollama 服务) | | **LM Studio** | `127.0.0.1` | 在开发者标签页 → 服务器设置中启用 **“在局域网中提供服务”** | | **llama-server** | `127.0.0.1` | 在启动命令中添加 `--host 0.0.0.0` | | **vLLM** | `0.0.0.0` | 默认已绑定到所有接口 | | **SGLang** | `127.0.0.1` | 在启动命令中添加 `--host 0.0.0.0` | **Windows 上的 Ollama(详细说明)**:Ollama 作为 Windows 服务运行。要设置 `OLLAMA_HOST`: 1. 打开 **系统属性** → **环境变量** 2. 添加新的 **系统变量**:`OLLAMA_HOST` = `0.0.0.0` 3. 重启 Ollama 服务(或重启系统) #### Windows 防火墙 {#windows-firewall} Windows 防火墙将 WSL2 视为独立网络(无论在 NAT 模式还是镜像模式下)。如果在完成上述步骤后连接仍失败,请为模型服务器的端口添加防火墙规则: ```powershell # 在管理中运行 PowerShell — 将 PORT 替换为您服务器的端口 New-NetFirewallRule -DisplayName "Allow WSL2 to Model Server" -Direction Inbound -Action Allow -Protocol TCP -LocalPort 11434 ``` 常见端口:Ollama `11434`,vLLM `8000`,SGLang `30000`,llama-server `8080`,LM Studio `1234`。 #### 快速验证 {#quick-verification} 从 WSL2 内部测试是否可以访问你的模型服务器: ```bash # 将 URL 替换为您的服务器地址和端口 curl http://localhost:11434/v1/models # 镜像模式 curl http://172.29.192.1:11434/v1/models # NAT模式(使用你的实际主机IP) ``` 如果返回包含模型列表的 JSON 响应,则说明配置正确。请将此 URL 用作 Hermes 配置中的 `base_url`。 --- ### 本地模型故障排除 {#troubleshooting-local-models} 这些问题会影响使用 Hermes 时的**所有**本地推理服务器。 #### “连接被拒绝”:从 WSL2 访问运行在 Windows 主机上的模型服务器 {#connection-refused-from-wsl2-to-a-windows-hosted-model-server} 如果你在 WSL2 中运行 Hermes,而模型服务器在 Windows 主机上,WSL2 默认的 NAT 网络模式下 `http://localhost:` 将无法工作。请参阅上方的 [WSL2 网络配置](#wsl2-networking-windows-users) 获取解决方案。 #### 工具调用以文本形式出现,而非执行 {#tool-calls-appear-as-text-instead-of-executing} 模型输出类似 `{"name": "web_search", "arguments": {...}}` 的消息,但并未实际调用工具。 **原因:** 你的服务器未启用工具调用功能,或模型通过服务器的工具调用实现不支持该功能。 | 服务器 | 修复方法 | |--------|--------| | **llama.cpp** | 在启动命令中添加 `--jinja` | | **vLLM** | 添加 `--enable-auto-tool-choice --tool-call-parser hermes` | | **SGLang** | 添加 `--tool-call-parser qwen`(或相应解析器) | | **Ollama** | 工具调用默认已启用 —— 请确保你的模型支持(使用 `ollama show model-name` 检查) | | **LM Studio** | 更新至 0.3.6 或更高版本,并使用原生支持工具调用的模型 | #### 模型似乎忘记上下文或给出不连贯的响应 {#model-seems-to-forget-context-or-give-incoherent-responses} **原因:** 上下文窗口太小。当对话超过上下文限制时,大多数服务器会静默丢弃较早的消息。Hermes 的系统提示 + 工具模式定义本身即可占用 4k–8k 个 token。 **诊断:** ```bash # 检查 Hermes 认为 context 是什么 # 查看启动行:“0” # 检查您服务器的实际 context # Ollama:ollama ps(上下文支柱) # llama.cpp:卷曲http://localhost:8080/props | jq '.default_generation_settings.n_ctx' # vLLM:检查启动参数中的--max-model-len ``` **修复:** 为 Agent 使用至少 **32,768 个 token** 的上下文。请参见上文各服务器部分,了解具体配置标志。 #### 启动时出现 "Context limit: 2048 tokens" {#context-limit-2048-tokens-at-startup} Hermes 会自动从服务器的 `/v1/models` 端点检测上下文长度。如果服务器报告的值过低(或根本未报告),Hermes 将使用模型声明的限制,这可能是错误的。 **修复:** 在 `config.yaml` 中显式设置: ```yaml model: default: your-model provider: custom base_url: http://localhost:11434/v1 context_length: 32768 ``` #### 响应在句子中间被截断 {#responses-get-cut-off-mid-sentence} **可能原因:** 1. **服务器输出上限(`max_tokens`)过低** —— SGLang 默认每响应限制为 128 个 token。请在服务器上设置 `--default-max-tokens`,或在 `config.yaml` 中通过 `model.max_tokens` 配置 Hermes。注意:`max_tokens` 仅控制响应长度,与对话历史长度无关(后者由 `context_length` 控制)。 2. **上下文耗尽** —— 模型已填满其上下文窗口。请增加 `model.context_length` 或在 Hermes 中启用 [上下文压缩](/docs/user-guide/configuration#context-compression)。 --- ### LiteLLM 代理 —— 多提供商网关 {#litellm-proxy-—-multi-provider-gateway} [LiteLLM](https://docs.litellm.ai/) 是一个兼容 OpenAI 的 Agent,可将 100 多个大模型提供商统一为单一 API。适用于:无需更改配置即可在不同提供商间切换、负载均衡、故障转移链、预算控制。 ```bash # 安装并启动 pip install "litellm[proxy]" litellm --model anthropic/claude-sonnet-4 --port 4000 # 或者使用多个 models 的配置文件: litellm --config litellm_config.yaml --port 4000 ``` 然后通过 `hermes model` → 自定义端点 → `http://localhost:4000/v1` 配置 Hermes。 示例 `litellm_config.yaml`(含故障转移): ```yaml model_list: - model_name: "best" litellm_params: model: anthropic/claude-sonnet-4 api_key: sk-ant-... - model_name: "best" litellm_params: model: openai/gpt-4o api_key: sk-... router_settings: routing_strategy: "latency-based-routing" ``` --- ### ClawRouter —— 成本优化路由 {#clawrouter-—-cost-optimized-routing} [ClawRouter](https://github.com/BlockRunAI/ClawRouter) 由 BlockRunAI 开发,是一个本地路由 Agent,可根据查询复杂度自动选择模型。它在 14 个维度上对请求进行分类,并将任务路由至最经济的可用模型。支付方式为 USDC 加密货币(无需 API 密钥)。 ```bash # 安装并启动 npx @blockrun/clawrouter # 在端口 8402 上启动 ``` 然后通过 `hermes model` → 自定义端点 → `http://localhost:8402/v1` → 模型名称 `blockrun/auto` 配置 Hermes。 路由配置文件: | 配置文件 | 策略 | 节省成本 | |---------|--------|--------| | `blockrun/auto` | 质量与成本的平衡 | 74–100% | | `blockrun/eco` | 尽可能便宜 | 95–100% | | `blockrun/premium` | 最佳质量模型 | 0% | | `blockrun/free` | 仅限免费模型 | 100% | | `blockrun/agentic` | 针对工具使用优化 | 变化 | :::note ClawRouter 需要在 Base 或 Solana 网络上使用已充值 USDC 的钱包进行支付。所有请求均通过 BlockRun 的后端 API 路由。运行 `npx @blockrun/clawrouter doctor` 可检查钱包状态。 ::: --- ### 其他兼容提供商 {#other-compatible-providers} 任何具备 OpenAI 兼容 API 的服务均可使用。部分流行选项如下: | 服务商 | 基础 URL | 备注 | |--------|----------|------| | [Together AI](https://together.ai) | `https://api.together.xyz/v1` | 云端托管开源模型 | | [Groq](https://groq.com) | `https://api.groq.com/openai/v1` | 超高速推理 | | [DeepSeek](https://deepseek.com) | `https://api.deepseek.com/v1` | DeepSeek 模型 | | [Fireworks AI](https://fireworks.ai) | `https://api.fireworks.ai/inference/v1` | 快速开源模型托管 | | [Cerebras](https://cerebras.ai) | `https://api.cerebras.ai/v1` | 芯片级规模推理 | | [Mistral AI](https://mistral.ai) | `https://api.mistral.ai/v1` | Mistral 模型 | | [OpenAI](https://openai.com) | `https://api.openai.com/v1` | 直接访问 OpenAI | | [Azure OpenAI](https://azure.microsoft.com) | `https://YOUR.openai.azure.com/` | 企业级 OpenAI | | [LocalAI](https://localai.io) | `http://localhost:8080/v1` | 自托管,多模型支持 | | [Jan](https://jan.ai) | `http://localhost:1337/v1` | 桌面应用,支持本地模型 | 可通过 `hermes model` → 自定义端点,或在 `config.yaml` 中配置任意上述服务: ```yaml model: default: meta-llama/Llama-3.1-70B-Instruct-Turbo provider: custom base_url: https://api.together.xyz/v1 api_key: your-together-key ``` --- ### 上下文长度检测 {#context-length-detection} :::note 两个设置,容易混淆 **`context_length`** 是 **总上下文窗口** —— 输入与输出 token 的总预算(例如 Claude Opus 4.6 为 200,000)。Hermes 使用此值判断何时压缩历史记录,并验证 API 请求。 ::: **`model.max_tokens`** 是**输出上限**——模型在单次响应中最多可生成的 token 数量。它与对话历史的长度无关。行业标准名称 `max_tokens` 常常引起混淆;Anthropic 的原生 API 已将其更名为 `max_output_tokens` 以更清晰地表达含义。 当自动检测无法正确识别窗口大小时,请设置 `context_length`。 仅当需要限制单次响应的长度时,才设置 `model.max_tokens`。 ::: Hermes 使用多源解析链来检测模型和提供商的正确上下文窗口: 1. **配置覆盖** —— `config.yaml` 中的 `model.context_length`(优先级最高) 2. **按模型自定义提供商** —— `custom_providers[].models..context_length` 3. **持久化缓存** —— 之前发现的值(重启后仍保留) 4. **端点 `/models`** —— 查询服务器 API(本地或自定义端点) 5. **Anthropic `/v1/models`** —— 查询 Anthropic API 获取 `max_input_tokens`(仅限 API 密钥用户) 6. **OpenRouter API** —— 从 OpenRouter 实时获取模型元数据 7. **Nous Portal** —— 将 Nous 模型 ID 与 OpenRouter 元数据进行后缀匹配 8. **[models.dev](https://models.dev)** —— 社区维护的注册表,包含 3800+ 模型、100+ 服务商的提供商特定上下文长度 9. **回退默认值** —— 基于广泛模型家族模式的默认值(128K 为默认) 对于大多数设置,系统可开箱即用。该系统具备提供商感知能力——同一模型在不同服务商处可能具有不同的上下文限制(例如,`claude-opus-4.6` 在 Anthropic 直连时为 1M,但在 GitHub Copilot 上为 128K)。 如需显式设置上下文长度,请在模型配置中添加 `context_length`: ```yaml model: default: "qwen3.5:9b" base_url: "http://localhost:8080/v1" context_length: 131072 # tokens ``` 对于自定义端点,也可为每个模型设置上下文长度: ```yaml custom_providers: - name: "My Local LLM" base_url: "http://localhost:11434/v1" models: qwen3.5:27b: context_length: 32768 deepseek-r1:70b: context_length: 65536 ``` `hermes model` 在配置自定义端点时会提示输入上下文长度。留空则启用自动检测。 :::tip 何时手动设置 - 使用 Ollama 并设置了低于模型最大值的 `num_ctx` - 希望将上下文限制在模型最大值以下(例如,在 128K 模型上设为 8K 以节省 VRAM) - 运行在不暴露 `/v1/models` 的 Agent 之后 ::: --- ### 命名的自定义提供商 {#named-custom-providers} 如果你使用多个自定义端点(例如本地开发服务器和远程 GPU 服务器),可以在 `config.yaml` 中将它们定义为命名的自定义提供商: ```yaml custom_providers: - name: local base_url: http://localhost:8080/v1 # api_key 省略 — Hermes 使用 "no-key-required" 作为无密钥本地服务器 - name: work base_url: https://gpu-server.internal.corp/v1 api_key: corp-api-key api_mode: chat_completions # 可选,从 URL 自动检测 - name: anthropic-proxy base_url: https://proxy.example.com/anthropic api_key: proxy-key api_mode: anthropic_messages # 适用于 Anthropic 兼容代理 ``` 在会话中随时切换,使用三重语法: ``` /model custom:local:qwen-2.5 # 使用“0”端点和“1”-2.5 /model custom:work:llama3-70b # 使用 llama3-70b 的“0”端点 /model custom:anthropic-proxy:claude-sonnet-4 # 使用代理 ``` 你也可以通过交互式 `hermes model` 菜单选择命名的自定义提供商。 --- ### 选择合适的配置方案 {#choosing-the-right-setup} | 使用场景 | 推荐方案 | |----------|----------| | **只想让它正常工作** | OpenRouter(默认)或 Nous Portal | | **本地模型,简单配置** | Ollama | | **生产级 GPU 服务** | vLLM 或 SGLang | | **Mac / 无 GPU 环境** | Ollama 或 llama.cpp | | **多提供商路由** | LiteLLM Proxy 或 OpenRouter | | **成本优化** | ClawRouter 或 OpenRouter 配合 `sort: "price"` | | **最大隐私保护** | Ollama、vLLM 或 llama.cpp(完全本地) | | **企业级 / Azure 环境** | Azure OpenAI 自定义端点 | | **中文 AI 模型** | z.ai(GLM)、Kimi/Moonshot 或 MiniMax(一级支持提供商) | :::tip 你可以随时通过 `hermes model` 切换提供商——无需重启。无论使用哪个提供商,你的对话历史、记忆和技能都会持续保留。 ::: ## 可选 API 密钥 {#optional-api-keys} | 功能 | 服务商 | 环境变量 | |------|--------|----------| | 网页抓取 | [Firecrawl](https://firecrawl.dev/) | `FIRECRAWL_API_KEY`, `FIRECRAWL_API_URL` | | 浏览器自动化 | [Browserbase](https://browserbase.com/) | `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID` | | 图像生成 | [FAL](https://fal.ai/) | `FAL_KEY` | | 高级 TTS 语音 | [ElevenLabs](https://elevenlabs.io/) | `ELEVENLABS_API_KEY` | | OpenAI TTS + 语音转录 | [OpenAI](https://platform.openai.com/api-keys) | `VOICE_TOOLS_OPENAI_KEY` | | 强化学习训练 | [Tinker](https://tinker-console.thinkingmachines.ai/) + [WandB](https://wandb.ai/) | `TINKER_API_KEY`, `WANDB_API_KEY` | | 跨会话用户建模 | [Honcho](https://honcho.dev/) | `HONCHO_API_KEY` | | 语义长期记忆 | [Supermemory](https://supermemory.ai) | `SUPERMEMORY_API_KEY` | ### 自托管 Firecrawl {#self-hosting-firecrawl} 默认情况下,Hermes 使用 [Firecrawl 云 API](https://firecrawl.dev/) 进行网页搜索和抓取。如果你更倾向于本地运行 Firecrawl,可以将 Hermes 指向自托管实例。详见 Firecrawl 的 [SELF_HOST.md](https://github.com/firecrawl/firecrawl/blob/main/SELF_HOST) 获取完整设置说明。 **你将获得:** 无需 API 密钥,无速率限制,无按页计费,完全数据主权。 **你将失去:** 云版本使用 Firecrawl 的专有“Fire-engine”技术实现高级反机器人绕过(Cloudflare、CAPTCHA、IP 轮换)。自托管版本使用基础的 fetch + Playwright,因此部分受保护网站可能无法成功访问。搜索使用 DuckDuckGo 而非 Google。 **设置步骤:** 1. 克隆并启动 Firecrawl Docker 堆栈(5 个容器:API、Playwright、Redis、RabbitMQ、PostgreSQL —— 需要约 4-8 GB 内存): ```bash git clone https://github.com/firecrawl/firecrawl cd firecrawl # In .env, set: USE_DB_AUTHENTICATION=false, HOST=0.0.0.0, PORT=3002 docker compose up -d ``` 2. 将 Hermes 指向你的实例(无需 API 密钥): ```bash hermes config set FIRECRAWL_API_URL http://localhost:3002 ``` 如果你的自托管实例启用了认证,也可以设置 `FIRECRAWL_API_KEY` 和 `FIRECRAWL_API_URL`。 ## OpenRouter 提供商路由 {#openrouter-provider-routing} 使用 OpenRouter 时,你可以控制请求在各个提供者之间的路由方式。在 `~/.hermes/config.yaml` 中添加一个 `provider_routing` 部分: ```yaml provider_routing: sort: "throughput" # "price"(默认)、"throughput" 或 "latency" # only: ["anthropic"] # 只使用这些提供者 # ignore: ["deepinfra"] # 跳过这些 Providers # order: ["anthropic", "google"] # 按此顺序尝试 Providers # require_parameters: true # 仅使用支持所有请求参数的 Providers # data_collection: "deny" # 排除可能存储 /train 数据的 Providers ``` **快捷方式:** 在任何模型名称后附加 `:nitro` 以按吞吐量排序(例如 `anthropic/claude-sonnet-4:nitro`),或附加 `:floor` 以按价格排序。 ## 备用模型 {#fallback-model} 配置一个备用提供者/模型,当你的主模型出现故障时(如速率限制、服务器错误、认证失败),Hermes 会自动切换到该备用模型: ```yaml fallback_model: provider: openrouter # 必需的 model: anthropic/claude-sonnet-4 # 必需的 # base_url: http://localhost:8000/v1 # 可选,用于自定义端点 # api_key_env: MY_CUSTOM_KEY # 可选,自定义端点 API 密钥的环境变量名称 ``` 启用后,备用模型会在会话过程中自动切换,而不会丢失你的对话记录。每个会话中最多触发一次。 支持的提供者:`openrouter`、`nous`、`openai-codex`、`copilot`、`copilot-acp`、`anthropic`、`huggingface`、`zai`、`kimi-coding`、`minimax`、`minimax-cn`、`deepseek`、`ai-gateway`、`opencode-zen`、`opencode-go`、`kilocode`、`alibaba`、`custom`。 :::tip 备用模型仅通过 `config.yaml` 配置 —— 没有对应的环境变量。有关其触发条件、支持的提供者以及与辅助任务和委托交互的完整说明,请参阅 [备用提供者](/docs/user-guide/features/fallback-providers)。 ::: ## 智能模型路由 {#smart-model-routing} 可选的“廉价 vs 强大”路由功能,使 Hermes 能够在处理复杂任务时保持使用主模型,同时将非常简短或简单的请求转发给更廉价的模型。 ```yaml smart_model_routing: enabled: true max_simple_chars: 160 max_simple_words: 28 cheap_model: provider: openrouter model: google/gemini-2.5-flash # base_url: http://localhost:8000/v1 # 可选的自定义端点 # api_key_env: MY_CUSTOM_KEY # 该端点的 API 密钥的可选环境变量名称 ``` 工作原理: - 如果某次交互简短、单行且不包含代码/工具/调试类内容,Hermes 可能会将其路由到 `cheap_model` - 如果该次交互看起来较复杂,Hermes 会继续使用主模型/提供者 - 如果廉价路径无法干净地处理请求,Hermes 会自动回退到主模型 此策略设计得较为保守,适用于快速、低风险的交互,例如: - 简短的事实性问题 - 快速重写 - 轻量级摘要 它会避免将以下类型的提示进行路由: - 编码/调试任务 - 工具密集型请求 - 长文本或多行分析请求 当你希望在不完全更换默认模型的前提下降低延迟或成本时,可使用此功能。 --- ## 参考 {#see-also} - [配置](/docs/user-guide/configuration) —— 通用配置(目录结构、配置优先级、终端后端、内存、压缩等) - [环境变量](/docs/reference/environment-variables) —— 所有环境变量的完整参考 --- ### 社区日报工作流 - URL: https://hermesagent.org.cn/docs/operations/community-daily-workflow - Path: operations/community-daily-workflow.md - Category: operations - Description: 社区日报已经从旧的“bot 目录里生成 report,再手工复制到站点”的方式,重构为一条固定流水线:apps/daily editor 工作台负责日常操作,content/daily/issues/ .issue.json 是社区站唯一公开数据源,var/daily/ 保存所有私有运行期数据。 # 社区日报工作流 社区日报已经从旧的“bot 目录里生成 report,再手工复制到站点”的方式,重构为一条固定流水线:`apps/daily-editor` 工作台负责日常操作,`content/daily/issues/*.issue.json` 是社区站唯一公开数据源,`var/daily/` 保存所有私有运行期数据。 每天使用时,从仓库根目录运行: ```bash pnpm daily:workbench ``` 在工作台首页创建当天 Issue。`issueDate` 是发布日期;如果是周一,默认素材日期是上周五、周六、周日。创建后进入 Issue 页面,依次执行“抽取素材”“生成候选”“人工精选”“发布到站点”。发布会把结构化 Issue 写到 `content/daily/issues/.issue.json`,并在 `static/reports/daily/` 生成可预览的 HTML、Markdown 和公众号富文本辅助产物。 人工精选后可以点击“联网校验精选”。该步骤只校验精选稿,不处理候选池;它会用 Tavily 搜索公开网页,再用当前模型生成校验结论、风险提示、证据链接和建议改写。需要先在环境变量里提供 `TAVILY_API_KEY`。发布时如果有未校验或存疑项,只弹窗警告,不阻止发布。 命令行也保留了明确入口: ```bash pnpm daily:status pnpm daily:materials -- 2026-05-26 pnpm daily:factcheck -- 2026-05-27 pnpm daily:publish -- 2026-05-26 pnpm daily:publish -- 2026-05-26 --screenshots ``` 其中 `daily:materials` 会把微信、飞书、QQ 三端 daily JSON 归一到 `var/daily/raw/.materials.json`。`daily:publish` 默认只生成 HTML,不依赖 Chrome;加 `--screenshots` 时会调用 Playwright/Chrome 生成 PNG 海报和封面。 旧文件 `src/data/dailyReports.json` 已从站点源中移除,不再参与日报页面、feed 或 AI asset 生成。旧的 `bot/wechat-summary-bot/md/.detailed.md` 也不再是单一来源,渲染器会优先从 `content/daily/issues/.issue.json` 生成详版 Markdown。 模型列表和默认并发配置在 `content/daily/config.json` 中维护;工作台会读取这个配置,并允许在 UI 中临时改用其他模型。 --- ### CLI 命令参考 - URL: https://hermesagent.org.cn/docs/reference/cli-commands - Path: reference/cli-commands.md - Category: reference - Description: Hermes 终端命令及命令组的权威参考 - Upstream Source: https://github.com/NousResearch/hermes-agent/blob/main/website/docs/reference/cli-commands.md - Translated At: 2026-04-11T03:37:25.649Z - Headings: 全局入口点 | 全局选项 | 顶层命令 | hermes chat | hermes model | /model 斜杠命令(会话中) | hermes gateway | hermes setup | hermes whatsapp | hermes login / hermes logout (已弃用) | hermes auth | hermes status # CLI 命令参考 {#cli-commands-reference} 本页面涵盖您从 shell 中运行的 **终端命令**。 有关聊天中的斜杠命令,请参阅 [斜杠命令参考](slash-commands)。 ## 全局入口点 {#global-entrypoint} ```bash hermes [global-options] [subcommand/options] ``` ### 全局选项 {#global-options} | 选项 | 描述 | |------|------| | `--version`, `-V` | 显示版本并退出。 | | `--profile `, `-p ` | 为本次调用选择要使用的 Hermes 配置文件。覆盖由 `hermes profile use` 设置的持久默认值。 | | `--resume `, `-r ` | 通过 ID 或标题恢复之前的会话。 | | `--continue [name]`, `-c [name]` | 恢复最近的会话,或恢复与标题匹配的最近会话。 | | `--worktree`, `-w` | 为并行 Agent 工作流启动一个隔离的 git 工作树。 | | `--yolo` | 跳过危险命令的审批提示。 | | `--pass-session-id` | 将会话 ID 包含在 Agent 的系统提示中。 | ## 顶层命令 {#top-level-commands} | 命令 | 用途 | |------|------| | `hermes chat` | 与 Agent 进行交互式或单次对话。 | | `hermes model` | 交互式选择默认提供者和模型。 | | `hermes gateway` | 运行或管理消息网关服务。 | | `hermes setup` | 交互式设置向导,用于全部或部分配置。 | | `hermes whatsapp` | 配置并配对 WhatsApp 桥接。 | | `hermes auth` | 管理凭据 — 添加、列出、删除、重置、设置策略。处理 Codex/Nous/Anthropic 的 OAuth 流程。 | | `hermes login` / `logout` | **已弃用** — 请改用 `hermes auth`。 | | `hermes status` | 显示 Agent、认证和平台状态。 | | `hermes cron` | 检查并触发定时调度器。 | | `hermes webhook` | 管理事件驱动激活的动态 Webhook 订阅。 | | `hermes doctor` | 诊断配置和依赖项问题。 | | `hermes dump` | 可复制粘贴的设置摘要,用于支持/调试。 | | `hermes logs` | 查看、实时跟踪和过滤 Agent/网关/错误日志文件。 | | `hermes config` | 显示、编辑、迁移和查询配置文件。 | | `hermes pairing` | 批准或撤销消息配对码。 | | `hermes skills` | 浏览、安装、发布、审计和配置技能。 | | `hermes honcho` | 管理 Honcho 跨会话记忆集成。 | | `hermes memory` | 配置外部记忆提供者。 | | `hermes acp` | 以 ACP 服务器模式运行 Hermes,用于编辑器集成。 | | `hermes mcp` | 管理 MCP 服务器配置,并以 MCP 服务器模式运行 Hermes。 | | `hermes plugins` | 管理 Hermes Agent 插件(安装、启用、禁用、移除)。 | | `hermes tools` | 配置各平台启用的工具。 | | `hermes sessions` | 浏览、导出、清理、重命名和删除会话。 | | `hermes insights` | 显示 token/成本/活动分析。 | | `hermes claw` | OpenClaw 迁移辅助工具。 | | `hermes profile` | 管理配置文件 — 多个隔离的 Hermes 实例。 | | `hermes completion` | 输出 shell 补全脚本(bash/zsh)。 | | `hermes version` | 显示版本信息。 | | `hermes update` | 拉取最新代码并重新安装依赖项。 | | `hermes uninstall` | 从系统中移除 Hermes。 | ## `hermes chat` {#hermes-chat} ```bash hermes chat [options] ``` 常用选项: | 选项 | 描述 | |------|------| | `-q`, `--query "..."` | 单次、非交互式提示。 | | `-m`, `--model ` | 覆盖本次运行的模型。 | | `-t`, `--toolsets ` | 启用逗号分隔的工具集。 | | `--provider ` | 强制指定提供者:`auto`、`openrouter`、`nous`、`openai-codex`、`copilot-acp`、`copilot`、`anthropic`、`huggingface`、`zai`、`kimi-coding`、`minimax`、`minimax-cn`、`deepseek`、`ai-gateway`、`opencode-zen`、`opencode-go`、`kilocode`、`alibaba`。 | | `-s`, `--skills ` | 为会话预加载一个或多个技能(可重复或以逗号分隔)。 | | `-v`, `--verbose` | 详细输出。 | | `-Q`, `--quiet` | 程序化模式:抑制横幅/旋转图标/工具预览。 | | `--resume ` / `--continue [name]` | 直接从 `chat` 命令中恢复会话。 | | `--worktree` | 为此运行创建一个隔离的 git 工作树。 | | `--checkpoints` | 在破坏性文件更改前启用文件系统检查点。 | | `--yolo` | 跳过审批提示。 | | `--pass-session-id` | 将会话 ID 传递到系统提示中。 | | `--source ` | 会话来源标签,用于过滤(默认:`cli`)。使用 `tool` 表示第三方集成,不应出现在用户会话列表中。 | | `--max-turns ` | 每轮对话的最大工具调用迭代次数(默认:90,或配置中的 `agent.max_turns`)。 | 示例: ```bash hermes hermes chat -q "Summarize the latest PRs" hermes chat --provider openrouter --model anthropic/claude-sonnet-4.6 hermes chat --toolsets web,terminal,skills hermes chat --quiet -q "Return only JSON" hermes chat --worktree -q "Review this repo and open a PR" ``` ## `hermes model` {#hermes-model} 交互式提供者 + 模型选择器。 ```bash hermes model ``` 在以下情况下使用此命令: - 切换默认提供者 - 在模型选择过程中登录 OAuth 支持的提供者 - 从提供者特定的模型列表中选择 - 配置自定义/自托管端点 - 将新默认值保存到配置中 ### `/model` 斜杠命令(会话中) {#model-slash-command-mid-session} 在不离开会话的情况下切换模型: ``` /model # 显示当前 Model 和可用选项 /model claude-sonnet-4 # 切换 Model(自动识别 Provider) /model zai:glm-5 # 切换 Provider 和 Model /model custom:qwen-2.5 # 使用自定义端点上的 Model /model custom # 从自定义端点自动检测 Model /model custom:local:qwen-2.5 # 使用具名自定义 Provider /model openrouter:anthropic/claude-sonnet-4 # 切回云端 Model ``` 提供方和基础 URL 的更改会自动保存到 `config.yaml` 中。当切换出自定义端点时,旧的基础 URL 会被清除,以防止泄露到其他提供方。 ## `hermes gateway` {#hermes-gateway} ```bash hermes gateway ``` 子命令: | 子命令 | 描述 | |--------|------| | `run` | 在前台运行网关。 | | `start` | 启动已安装的网关服务。 | | `stop` | 停止服务。 | | `restart` | 重启服务。 | | `status` | 显示服务状态。 | | `install` | 作为用户服务安装(Linux 上为 `systemd`,macOS 上为 `launchd`)。 | | `uninstall` | 移除已安装的服务。 | | `setup` | 交互式消息平台设置。 | ## `hermes setup` {#hermes-setup} ```bash hermes setup [model|terminal|gateway|tools|agent] [--non-interactive] [--reset] ``` 使用完整向导,或直接跳转到某个部分: | 部分 | 描述 | |------|------| | `model` | 提供方和模型设置。 | | `terminal` | 终端后端和沙箱设置。 | | `gateway` | 消息平台设置。 | | `tools` | 按平台启用/禁用工具。 | | `agent` | Agent 行为设置。 | 选项: | 选项 | 描述 | |------|------| | `--non-interactive` | 使用默认值 / 环境变量,不进行提示。 | | `--reset` | 在设置前将配置重置为默认值。 | ## `hermes whatsapp` {#hermes-whatsapp} ```bash hermes whatsapp ``` 运行 WhatsApp 配对/设置流程,包括模式选择和二维码配对。 ## `hermes login` / `hermes logout` *(已弃用)* {#hermes-login--hermes-logout-deprecated} :::caution `hermes login` 已移除。请使用 `hermes auth` 管理 OAuth 凭证,使用 `hermes model` 选择提供方,或使用 `hermes setup` 进行完整交互式设置。 ::: ## `hermes auth` {#hermes-auth} 管理同一提供方的凭证池以实现密钥轮换。详见 [凭证池](/docs/user-guide/features/credential-pools) 获取完整文档。 ```bash hermes auth # 启动交互式向导 hermes auth list # 显示所有凭证池 hermes auth list openrouter # 显示指定 Provider hermes auth add openrouter --api-key sk-or-v1-xxx # 添加 API key hermes auth add anthropic --type oauth # 添加 OAuth 凭证 hermes auth remove openrouter 2 # 按索引删除 hermes auth reset openrouter # 清除冷却状态 ``` 子命令:`add`、`list`、`remove`、`reset`。若未指定子命令,则启动交互式管理向导。 ## `hermes status` {#hermes-status} ```bash hermes status [--all] [--deep] ``` | 选项 | 描述 | |------|------| | `--all` | 以可共享的脱敏格式显示所有详细信息。 | | `--deep` | 执行更深入的检查,可能耗时更长。 | ## `hermes cron` {#hermes-cron} ```bash hermes cron ``` | 子命令 | 描述 | |--------|------| | `list` | 显示已安排的任务。 | | `create` / `add` | 从提示创建一个计划任务,可选地通过重复 `--skill` 附加一个或多个技能。 | | `edit` | 更新任务的调度、提示、名称、交付方式、重复次数或附加技能。支持 `--clear-skills`、`--add-skill` 和 `--remove-skill`。 | | `pause` | 暂停任务但不删除。 | | `resume` | 恢复暂停的任务,并计算其下一次未来运行时间。 | | `run` | 在下一个调度器 tick 触发任务。 | | `remove` | 删除已安排的任务。 | | `status` | 检查 cron 调度器是否正在运行。 | | `tick` | 执行所有到期的任务一次后退出。 | ## `hermes webhook` {#hermes-webhook} ```bash hermes webhook ``` 管理用于事件驱动 Agent 激活的动态 Webhook 订阅。需要在配置中启用 Webhook 平台——若未配置,将打印设置说明。 | 子命令 | 描述 | |--------|------| | `subscribe` / `add` | 创建一个 Webhook 路由。返回 URL 和 HMAC 密钥,用于在您的服务上配置。 | | `list` / `ls` | 显示所有 Agent 创建的订阅。 | | `remove` / `rm` | 删除一个动态订阅。配置文件中的静态路由不受影响。 | | `test` | 发送测试 POST 请求以验证订阅是否正常工作。 | ### `hermes webhook subscribe` {#hermes-webhook-subscribe} ```bash hermes webhook subscribe [options] ``` | 选项 | 描述 | |------|------| | `--prompt` | 包含 `{dot.notation}` 负载引用的提示模板。 | | `--events` | 以逗号分隔的要接受的事件类型(例如 `issues,pull_request`)。空值 = 所有事件。 | | `--description` | 人类可读的描述。 | | `--skills` | 以逗号分隔的技能名称,用于 Agent 运行时加载。 | | `--deliver` | 交付目标:`log`(默认)、`telegram`、`discord`、`slack`、`github_comment`。 | | `--deliver-chat-id` | 用于跨平台交付的目标聊天/频道 ID。 | | `--secret` | 自定义 HMAC 密钥。若省略则自动生成。 | 订阅会持久化保存至 `~/.hermes/webhook_subscriptions.json`,并由 Webhook 适配器热重载,无需重启网关。 ## `hermes doctor` {#hermes-doctor} ```bash hermes doctor [--fix] ``` | 选项 | 描述 | |------|------| | `--fix` | 尽可能尝试自动修复。 | ## `hermes dump` {#hermes-dump} ```bash hermes dump [--show-keys] ``` 输出您整个 Hermes 设置的紧凑、纯文本摘要。专为复制粘贴到 Discord、GitHub 问题或 Telegram 中请求支持而设计——无 ANSI 颜色,无特殊格式,仅包含数据。 | 选项 | 描述 | |------|------| | `--show-keys` | 显示脱敏的 API 密钥前缀(前 4 个和后 4 个字符),而非仅显示 `set`/`not set`。 | ### 包含内容 {#what-it-includes} | 区段 | 详情 | |------|------| | **头部** | Hermes 版本、发布日期、git 提交哈希 | | **环境** | 操作系统、Python 版本、OpenAI SDK 版本 | | **身份** | 活跃配置文件名称、HERMES_HOME 路径 | | **模型** | 配置的默认模型和提供方 | | **终端** | 后端类型(本地、docker、ssh 等) | | **API 密钥** | 所有 22 个提供方/工具 API 密钥的存在性检查 | | **功能** | 已启用的工具集、MCP 服务器数量、记忆提供方 | | **服务** | 网关状态、配置的消息平台 | | **工作负载** | 定时任务数量、已安装技能数量 | | **配置覆盖** | 与默认值不同的任何配置值 | ### 示例输出 {#example-output} ``` --- hermes dump --- version: 0.8.0 (2026.4.8) [af4abd2f] os: Linux 6.14.0-37-generic x86_64 python: 3.11.14 openai_sdk: 2.24.0 profile: default hermes_home: ~/.hermes model: anthropic/claude-opus-4.6 provider: openrouter terminal: local api_keys: openrouter set openai not set anthropic set nous not set firecrawl set ... features: toolsets: all mcp_servers: 0 memory_provider: built-in gateway: running (systemd) platforms: telegram, discord cron_jobs: 3 active / 5 total skills: 42 config_overrides: agent.max_turns: 250 compression.threshold: 0.85 display.streaming: True --- end dump --- ``` ### 使用场景 {#when-to-use} - 在 GitHub 上报告 bug —— 将转储内容粘贴到问题中 - 在 Discord 中寻求帮助 —— 以代码块形式分享 - 与他人设置进行对比 - 当某项功能异常时快速进行健康检查 :::tip `hermes dump` 专为共享设计。如需交互式诊断,请使用 `hermes doctor`。如需可视化概览,请使用 `hermes status`。 ::: ## `hermes logs` {#hermes-logs} ```bash hermes logs [log_name] [options] ``` 查看、实时跟踪和过滤 Hermes 日志文件。所有日志均存储在 `~/.hermes/logs/`(非默认配置文件则为 `/logs/`)。 ### 日志文件 {#log-files} | 名称 | 文件 | 记录内容 | |------|------|----------| | `agent`(默认) | `agent.log` | 所有 Agent 活动 —— API 调用、工具分发、会话生命周期(INFO 及以上级别) | | `errors` | `errors.log` | 仅记录警告和错误 —— `agent.log` 的过滤子集 | | `gateway` | `gateway.log` | 消息网关活动 —— 平台连接、消息分发、Webhook 事件 | ### 选项 {#options} | 选项 | 描述 | |------|------| | `log_name` | 要查看的日志:`agent`(默认)、`errors`、`gateway`,或 `list` 以显示可用文件及其大小。 | | `-n`, `--lines ` | 显示的行数(默认:50)。 | | `-f`, `--follow` | 实时跟踪日志,类似 `tail -f`。按 Ctrl+C 停止。 | | `--level ` | 显示的最低日志级别:`DEBUG`、`INFO`、`WARNING`、`ERROR`、`CRITICAL`。 | | `--session ` | 过滤包含会话 ID 子串的日志行。 | | `--since