背景
最近想在 macOS 上把 Hermes Agent 跑起来,目标是让一个 AI 代理能直接操作本地文件 + 接飞书/微信 + 调一堆 skill 自动干活。官方文档写得很顺,但实际一路踩了 8 个坑,有的坑排查到半夜,这里把每个坑的报错样本、我误判的方向、最终解法完整记下来,给后面想装的同学省点时间。
环境:macOS 14.5、Python 3.11.9(用 pyenv 管理)、Hermes 0.x 拉的是 main 分支,模型走 OpenRouter。
坑 1:pip 装到系统 Python,permission denied 排了一晚上
报错
ERROR: Could not install packages due to an OSError: [Errno 13] Permission denied: '/Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/hermes_agent'
我以为的原因:权限不够,加 sudo。 实际:pip 默认指向系统 Python 2.7 或 Apple 自带 Python,框架目录不让随便写。 解法:老老实实用 venv。
python3.11 -m venv ~/.venvs/hermes
source ~/.venvs/hermes/bin/activate
pip install -U hermes-agent
经验:装任何 agent 框架前先 which python && which pip 确认指向 venv,别相信 python3 的默认符号链接。
坑 2:venv 激活后,terminal 工具仍调系统 Python
症状:激活了 venv,在外面 pip show hermes-agent 能看到包,但一启动 hermes 就报 ModuleNotFoundError: No module named 'hermes_tools'。
根因:我的 IDE 终端和 shell 启动器用的是不同的 rc 文件(zsh vs zshrc profile 段),venv 激活只对当前 shell 生效。
解法:把 source ~/.venvs/hermes/bin/activate 写进 ~/.zshrc 顶部,或者用 direnv 做 per-project 切换。
经验:Agent 类工具对执行环境敏感,务必统一 shell 配置,别让 IDE / iTerm / VSCode 走三套 PATH。
坑 3:gateway 起在 4317 端口,但本机已有进程占用
报错
[gateway] bind 0.0.0.0:4317 failed: address already in use
查占用:lsof -iTCP:4317 -sTCP:LISTEN,发现是之前装的一个本地 LLM 推理服务占着。
解法:Hermes 的 gateway 端口在 ~/.hermes/config.yaml 里能改,我改成 4388,记得把客户端连接地址也一起改。
gateway:
host: 127.0.0.1
port: 4388
经验:macOS 上开发工具起得多了,端口冲突是日常。常用端口 3000/4317/5000/7860/8000/8080 都先扫一遍。
坑 4:profile 隔离没生效,default 和 work 互相串 session
我以为:创建了 ~/.hermes/profiles/work/,往里塞了独立的 skills 和 memories,期望它和 default 完全隔离。
实际:session 仍然写到默认 profile 的 sqlite 里。
根因:profile 必须显式在启动时指定,或者用 HERMES_PROFILE=work hermes ... 设环境变量;光建目录不够。
解法:
export HERMES_PROFILE=work
hermes chat "今天处理什么"
或者直接在 config.yaml 里设 active_profile: work。
经验:profile 的隔离是显式激活的,不是目录存在就自动切换。文档里这行很容易看漏。
坑 5:Skill 加载失败,提示 SKILL.md frontmatter 解析错误
报错
[skills] failed to load 'my-skill': missing required field 'name' in frontmatter
我以为:我的 SKILL.md 写得有问题。
实际:frontmatter 里的 name 字段必须和目录名完全一致(全小写、连字符),而且必须在最顶部用 --- 包起来,冒号后面必须有空格,YAML 严格语法。
错误示例:
---
name: MySkill # 错,目录叫 my-skill
description: ...
---
正确:
---
name: my-skill
description: ...
---
经验:Skill 是 Hermes 的核心扩展点,frontmatter 解析错的话整个 skill 直接不加载,而且错误信息只在 debug 日志里。启动时加 hermes --log-level=debug 能看到。
坑 6:memory 工具调用成功,但下次 session 读不到
症状:memory(action='add', ...) 返回成功,数据库里也能查到记录,但新开一个 session 问"我之前让你记的 X 是什么" agent 一脸茫然。
根因:memory 分两个 store:user(用户画像,跨所有 session 注入)和 memory(代理自己的笔记)。我之前存的是 memory,而 system prompt 里只注入了 user store。
解法:用户偏好、长期事实 → target='user';任务进度、当次草稿 → target='memory',并且 memory 默认不主动注入,要用就在 prompt 里显式 session_search 拉。
经验:user 和 memory 不是同义词,scope 完全不一样,选错 store 等于白存。
坑 7:配了 OpenRouter,但模型调用一直 401
报错
[provider] openrouter returned 401: invalid api key
检查路径:
~/.hermes/.env里OPENROUTER_API_KEY=sk-or-...有没有(注意前缀是 sk-or-,不是 sk-)- key 是不是带空格(从网页复制经常带尾随空格)
- provider 配置里
provider: openrouter和model: anthropic/claude-sonnet-4的写法,有些版本要求带openrouter/前缀,有些不要求
解法:把 key 写进 ~/.hermes/.env 而不是 shell export,这样 hermes 启动时会自动 load;模型字段固定用 provider/model_name 的完整形式。
经验:多 provider 时代,key 的归属和 model 字符串的格式最容易出错。固定用一个 .env 文件,别散落在各处。
坑 8:MCP 工具声明成功但 list 出来是空
症状:hermes tools 能看到 mcp server 注册了,但 agent 实际调工具时一直说"no such tool"。
根因:MCP server 进程启动失败,错误在 stderr 里被吞了。
排查:
hermes mcp run my-server --verbose
直接看到是 Node 版本不对(npx 调一个要求 >=18 的包但本机 16)还是路径错了。 解法:
- macOS 上 nvm 管理 Node,固定到 20 LTS
- 启动命令里加
cwd显式指到 server 目录 - 权限不够就
chmod +xserver 的 entry 脚本
经验:MCP 这种"声明即存在"的协议,失败模式特别安静,verbose 模式是排查第一步。
总的复盘
8 个坑里,6 个是环境问题(Python 版本、端口、profile、shell、Node 版本),2 个是配置理解问题(memory scope、Skill frontmatter)。这其实是个普遍规律:Agent 框架最难的不是模型本身,而是它赖以运行的那一层基础设施。
几个通用建议:
- 安装前先固化环境 — pyenv + venv + nvm,别让系统 Python/Node 参与
- debug 日志默认开 — 很多"神秘失败"的真相在 stderr
- 小步验证 — 每装一步就
hermes --check或跑一个最小命令,别一锅端 - 隔离用 profile,别复制 home — Hermes 的 profile 设计就是为了这个
- Skill 写完先 hermes skills list 看一眼 — 确认加载成功再写内容
讨论点
我自己最纠结的是第 6 个 memory 那个:user 和 memory 的边界到底怎么划?哪些东西该进 user(跨所有 session 注入),哪些该留 memory(按需拉取)?
你们在实际项目里是怎么定这个边界的?有没有什么"宁滥勿缺"或者"宁缺勿滥"的实际经验?
来源:自己 macOS 上完整装过一遍,8 个坑全部真实复现。模型:由我的 content-agent 自动整理与撰写,所有命令和报错样本都是实操记录。