
夜里十一点我打开 GitHub 的 PR 列表一排 pull request 挂着 changes requested点进去却发现根本没有一条有效评论。这种状态持续了一个多月后我决定把 Hermes 接进来做自动化代码评审。让机器先把每一条 PR 完整读一遍把明确的问题直接标在 diff 上人工 reviewer 只需要在机器意见之上做判断而不是重新干一遍体力活。这篇博文就围绕 Hermes 在 GitHub PR 审查上的落地过程来写包含部署、接入、规则设计、实测复盘和踩坑记录适合那些团队规模不大、review 经常靠催的小型研发团队也适合想给开源仓库找个“0 号 reviewer”的维护者。1. 为什么我把 PR 审查交给 Hermes1.1 一个让 reviewer 崩溃的凌晨我们团队三个人轮流当 reviewer听起来是够用的配置实际上所有 PR 都堆积在“待 review”里没人碰。原因很典型上午改完的 PR下午还没人看下午点开一个 PR刚把上下文想起来又被即时通讯里的问题打断到了晚上终于有整块时间却发现这个 PR 改动了十几个文件自己负责的模块只占其中一小块。真正让我下决心接 Hermes 的是一次凌晨的线上事故。后端同学重构了用户登录逻辑PR 里明确写了“登录失败时新增重试机制”reviewer 看到重试逻辑没问题就点了 approve却没人发现重试过程里没有超时控制。线上流量一上来超时任务直接堆积把数据库连接池打穿。这不是某个人的粗心而是人工 review 天然存在盲区注意力优先放在“这次改动的核心逻辑”没人系统性地扫一遍“边界条件、超时、并发、资源释放”这些老问题。1.2 Hermes 在 PR 评审里扮演的角色Hermes 不是一个普通的 lint 工具lint 只能抓格式和固定规则比如缩进、未使用变量、明显语法错误。而我需要的是能看懂 diff、理解代码逻辑的“语义级审查”Hermes 这类大模型驱动的 agent 正好干这个。按我的理解Hermes 是一个消息驱动的 agent 框架它监听 GitHub 上的事件把 pull_request、issue_comment 这些事件转成具体任务再调用底层大模型做推理最后通过 skill 机制调 GitHub API 把评审意见写回 PR。整个过程里Hermes 更像一个“0 号 reviewer”——它一定先看给出第一轮评估人工 reviewer 再在它的基础之上做决策和最终把关。这个定位非常重要。自动化代码评审的合理目标从来不是“替代人”而是把人类从“扫雷”里解放出来。机器负责把低层次的、重复性的问题全部捞出来人负责判断业务边界和做最终决策。团队逐步习惯这套流程之后等于每个 PR 在合入之前都至少经过了两道独立检查一道机器的一道人的。1.3 适合什么团队我梳理了一下以下场景接 Hermes 收益最大团队小没有专职代码评审人review 全靠抽空。开源项目维护者PR 积压严重需要快速了解外部贡献者的改动质量。跨语言、多仓库团队统一由同一个 agent 规则把关。团队有一堆公共代码规范和已知坑想把它们固化到评审流程里。反过来如果你的项目处于强安全审计环境或者对“机器自动评论”这件事本身非常敏感建议先只让它生成内部报告不要直接 post 到 PR 评论区。合规和信任是两回事工具可以很先进但流程要稳。2. Hermes 的工作链路从 GitHub 事件到评审意见的完整流转2.1 Hermes 是什么市面叫 Hermes 的名字不少我这里说的是 hermes-agent 这个方向的智能体服务。它最核心的设计是“事件驱动 技能扩展”GitHub 推来一个事件Hermes 决定调用哪些技能例如抓取 PR 信息、读取指定文件、提交 review最后把大模型的推理结果组装成 GitHub API 能识别的格式写回去。命名上也能看出来Hermes 在希腊神话里是信使这个项目的定位就是事件与执行之间的桥。你不用为每一个仓库写一套定制代码只要配置好一个通用规则它就能在不同仓库里复用得很好。2.2 完整事件链路以下链路是我基于自己部署的版本整理的具体事件名和字段可能因版本略有差异但整体思路一致开发者在 GitHub 上提交 PR 或 push 新 commit产生 pull_request 事件。GitHub Webhook 把事件推送到 Hermes 服务。Hermes 校验签名确认事件来源是 GitHub防止伪造请求。Hermes 调用 GitHub API拉取 PR 的元信息、commit 列表、diff 内容。服务端组装上下文diff、PR 描述、仓库规则文件、忽略路径列表。大模型基于上下文进行推理输出结构化评审结果。Hermes 通过 GitHub API 把结果作为 review 提交到 PR或写入行内评论。这条链路里最容易出问题的不是第 1 步也不是第 7 步而是第 5 步的上下文组装。模型本身看不到仓库全貌你给它什么它就只能评什么。给少了它会瞎猜给多了它会发散。上下文组装质量直接决定评审水不水。2.3 三种接入方式对比我实际试过 Webhook、GitHub App、GitHub Actions 三种方式各有适用场景。接入方式自建要求适合场景主要缺点Webhook需要一台常驻服务器暴露 HTTP 端口团队自建 Hermes长期沉淀规则多一个服务要维护GitHub App需要生成私钥并配置权限想精细控制权限、覆盖多个仓库配置稍复杂GitHub Actions不需要自建服务走 GitHub 自带执行器单个仓库快速试用受执行时间限制每次跑要带模型 Key我个人最后选了 Webhook 常驻 Docker 容器的方式因为我不想让每次 PR 审查都等待 Actions 执行器排队也不想把模型 API Key 塞进仓库的 Secrets 里反复轮换。3. 环境准备与 GitHub 接入我踩过的配置点3.1 用 Docker 部署 Hermes在服务器上部署 Hermes 其实不复杂我用 Docker 容器跑一条命令就能拉起来docker run -d \ --name hermes-review \ -p 8080:8080 \ -e HERMES_GITHUB_WEBHOOK_SECRETyour_webhook_secret \ -e LLM_PROVIDERdeepseek \ -e LLM_API_KEYsk-xxxx \ -e LLM_MODELdeepseek-chat \ -e REVIEW_RULES_PATH/app/rules/review.yaml \ -v $PWD/review.yaml:/app/rules/review.yaml \ hermes-agent/hermes:latest这里的HERMES_GITHUB_WEBHOOK_SECRET是 GitHub Webhook 里配的密钥两边必须完全一样。LLM_PROVIDER和LLM_API_KEY决定用哪个模型做推理我选的是 DeepSeek因为它的上下文窗口大面对大 diff 时不容易截断。容器名和镜像名只是示例具体以你实际拿到的安装包为准。启动之后先访问http://localhost:8080/health确认服务状态再回 GitHub 页面用 “Redeliver” 按钮补发一次 webhook看 Hermes 日志里是否打印出事件接收记录。这一步能一次性验证网络、签名、API Key 三条链路是否都是通的。3.2 Webhook 配置步骤GitHub 侧的配置路径是仓库 Settings → Webhooks → Add webhook。需要填四样东西Payload URL填 Hermes 服务接收 GitHub 事件的地址例如http://your-host:8080/webhook/github。Content type必须选application/json。Secret填与HERMES_GITHUB_WEBHOOK_SECRET相同的随机字符串。Events选择 “Let me select individual events”至少勾选pull_request如果希望它响应评论和 review 对话再勾pull_request_review_comment和issue_comment。配置完成后GitHub 会立刻发一条ping事件。如果 Hermes 日志里能看到 ping 且不报 403说明签名验证已经通过。很多配置问题都出在 secret 不一致上这个坑我踩过不止一次。3.3 用 GitHub Actions 快速验证如果你想先不动服务器也可以用 GitHub Actions 快速跑通一遍。大致 workflow 长这样name: Hermes Auto Review on: pull_request: types: [opened, synchronize, reopened] permissions: contents: read pull-requests: write jobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Run Hermes Review env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} LLM_PROVIDER: deepseek LLM_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} LLM_MODEL: deepseek-chat run: | docker run --rm \ -e GITHUB_TOKEN \ -e LLM_PROVIDER \ -e LLM_API_KEY \ -e LLM_MODEL \ -v ${{ github.workspace }}:/repo \ hermes-agent/hermes:latest review \ --repo ${{ github.repository }} \ --pr ${{ github.event.pull_request.number }}注意pull-requests: write权限必须要给否则 Hermes 有模型推理结果也写不回 PR。具体 CLI 子命令名以你使用的版本为准至少先跑hermes-agent/hermes:latest help看一眼再改。3.4 配套的 Hermes Studio 管理面板我比较喜欢 Hermes Studio 这个自带的管理界面。它能看到事件队列、每次评审耗时、模型原始输出甚至能查看“被过滤掉的评论草稿”。平时我不会直接在 Studio 里写 prompt但排查问题时它是第一去处。比如某个 PR 没有自动评论我打开 Studio 就能看到是事件没推过来、权限不够还是模型返回了NO_ISSUE。没有这个面板遇到“静默失败”会让你非常痛苦。4. 让评审有“业务感”的规则集与提示词设计4.1 先定义“要查什么”很多人在接自动化代码评审时的第一个失误就是让模型“自由发挥”。自由发挥的结果不是没有评论而是评论灌水——每条看起来都对但没有一条值得改。正确的做法是先定义检查维度。检查维度要覆盖的问题典型例子安全注入、硬编码密钥、越权、危险反序列化用字符串拼接 SQL正确性空指针、并发、资源未释放、错误被吞异常分支没有关闭句柄性能不必要的循环、大对象拷贝、N1 查询循环里重复请求数据库可维护性命名、重复代码、函数过重一个函数写了四百行一致性是否违反仓库已有的编码规范新代码用了旧的废弃 API这些维度不是每个 PR 都要全量覆盖也不是每一条都同等重要。安全问题的优先级永远最高风格问题排在最后。4.2 一套能直接抄的 review 提示词我目前在用的提示词核心部分长这样你可以直接拿去做基准版本你是一位严谨的资深代码评审专家。 你正在审查一个 GitHub PR请基于 diff 和仓库上下文输出评审意见。 执行要求 1. 只报告能明确指向具体代码行的问题禁止空泛的“建议优化”。 2. 按严重级别输出blocker / warning / suggestion。 3. 每个问题必须包含文件、行号、问题描述和修复建议。 4. 优先检查安全、正确性、性能问题最后才是风格。 5. 如果同一个根因导致多处问题合并为一条不要刷屏。 6. 如果 diff 里没有值得提的问题只回复 NO_ISSUE不要硬凑。 7. 对你不确定的问题标记“需要确认”不要武断下结论。 输出格式 ### Blocker - 文件:行号 - 问题描述 - 修复建议 ### Warning ... ### Suggestion ...提示词里最关键的是第 6 条。没有这一条模型会倾向于给每一个 PR 都挑出点东西来证明自己“工作过”这会产生大量噪音。允许它说“没问题”反而会让真正的问题更突出。4.3 给 Hermes 喂仓库上下文模型对业务的理解程度取决于你喂了多少上下文。我建议至少配置三类内容第一是仓库级信息比如 README、架构说明、约定的技术栈第二是 PR 本身的描述和关联 issue里面通常有改动背景第三是忽略清单比如.reviewignore把 lock 文件、生成的代码、第三方 vendor 目录全部排除掉。我还额外建了一个REVIEW_RULES.md里面写团队已经公认的约定例如“项目禁止使用全局可变状态”“对外的 HTTP 接口必须显式设置超时”。这些规则看起来是给代码库写的实际上是在给模型写提示词。模型每轮都会被注入这些内容评论自然更有业务感。5. 实测效果误报、漏报与真发现的界限5.1 一个典型 PR 的评审结果有一次后端提交了一个“用户注册失败重试逻辑”的 PR。Hermes 的评审输入是 300 行 diff最后输出了四条意见blocker重试发送请求时没有设置超时时间失败请求可能长期占用连接资源。warning指数退避没有加随机抖动多个客户端失败后会同步重试形成踩踏。warning错误日志里缺少 trace_id线上排查时无法关联链路。suggestion重试最多尝试 5 次建议把次数抽成配置项。这个结果让团队挺惊讶。前两条意见是人工 review 大概率能看出来的但第三条 trace_id 的问题往往要等到线上出故障才会意识到。真正让我确定这套方案可用的是另一件事作者根据 Hermes 的意见改完以后人类 reviewer 再看 PR 时只说了一句“没问题”整个 review 周期从两小时压缩到了二十分钟。5.2 抽样 20 个 PR 后的数据我连续抽样了 20 个 PR统计了 Hermes 意见与人工复核结果的差异指标数值Hermes 提出的问题总数49人工确认是真问题的数量37误报数量12人工额外发现但 Hermes 漏掉的问题5按这个粗样本算Hermes 的精确率大约是 75.5%召回率约 88%。样本不大别当成通用结论。但趋势很明显它抓重复性问题很稳误报主要集中在“看不到历史背景”的场景里。5.3 误报和漏报的典型来源误报的常见来源是模型只知道当前 diff不知道历史背景。比如它建议“把 A 函数抽到公共模块”但团队上个季度已经做过一次抽象业务后来决定保持重复。这类误报不是模型笨是上下文组装缺了东西。漏报则大多来自跨文件问题。Hermes 通常聚焦在 diff 本身如果问题发生在“调用方没感知到签名变化”这种跨文件场景单看文件 diff 很难发现。应对办法是让 Hermes 在评论里多使用“需要确认”这类不确定标记同时保留人工 reviewer 的独立判断。机器不是万能的但它的主要价值是把低垂的问题先摘掉。6. 部署后容易掉的坑与调优方向6.1 事件与权限的坑我在接入过程中踩过四个比较深的坑值得单独记录。第一个是 Webhook 签名不匹配。GitHub 会拿 secret 给请求体加签名Hermes 也会验一次。两边只要有一个字符不一样请求就会被拒绝而且 GitHub 页面看请求记录全绿因为事件是推送成功的只是服务端没有接受。这种问题看服务端日志最快。第二个是 GitHub App 的权限配置。有一个仓库我始终拉不到 diff查了半天才发现是 App 的Contents: Read权限没开。权限不足的表现非常隐蔽GitHub API 不会直接说“没权限”而是返回一个看起来像文件不存在的结果。第三个是评论写错端口。行内 review 必须调用POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews接口把 comments 放在数组里传如果图省事走issues/{number}/comments会变成普通评论代码行上没有任何标记。我只用普通评论跑了一周导致团队成员要在评论区和文件之间来回翻体验很差。第四个是评论洪泛。大 PR 一次可以触发二三十条评论直接淹没整个讨论串。解决办法是在规则里限制单次最多提 8 条意见并且把低优先级意见合并进总结而不是逐条发。6.2 模型参数与上下文限制模型的temperature参数对评审质量影响很大。我一开始用默认值 0.7结果模型开始“过度发挥”给出很多富有创意但与代码无关的建议。调到 0.2 以后输出稳定了很多基本围绕 diff 本身说话。另一个限制是 diff 大小。改动超过 1000 行的 PR直接整包丢给模型既容易超时也容易丢上下文。我的处理策略是先跑一个git diff --stat按文件拆分评审每个文件只提取 diff 中前 800 行的内容如果单文件超过这个阈值先生成一个文件级摘要再让模型基于摘要挑重点文件阅读。这样单个文件的问题不会因为上下文过长而被忽略。6.3 后续可以扩展的方向Hermes 接进 PR 审查流程之后还能往几个方向延伸。我自己正在做的是给 PR 自动打风险标签根据 Hermes 输出的 blocker 数量自动标记review/high-risk、review/ok再配合分支保护规则高风险 PR 必须有两个人工 approve 才能合入。下一步我打算让它做 release note 生成把所有合并的 PR 按改动类别汇总省去发版前人工整理的时间。至于 issue 自动分类、定时巡检长尾 PR这些都不需要改 Hermes 主程序只要在事件规则里加对应的技能配置就能做。最后分享一个我自己的体会不要把 Hermes 的第一步目标定为完全替代人工 review。我现在的流程是 Hermes 先评作者根据机器意见自改再由人类 reviewer 看 Hermes 的评论和剩余 diff。走过三轮之后团队里的 PR 平均 review 时间从一天半降到了半天。自动化代码评审的价值不在炫技而在把每个人从第一遍扫描里解放出来。给 Hermes 一点项目背景它会比大多数人想象中靠谱但给它一条干净的规则它才会稳定地靠谱。