
GitHub 上做开源或团队协作的朋友基本都有一个共同感受PRPull Request审查就像项目的“质检关”可这关过得实在不轻松。我最近在内部项目里捣鼓了一套基于 Hermes 智能体的自动化代码审查方案把 GitHub PR 的审查流程从“人工肉眼盯 diff”变成了“智能体自动过一遍人只留在最关键的设计决策环节”效果比预期好不少。这篇文章就把整个思路、环境搭建、核心实现、实操过程和踩坑记录完整写一遍适合那些 PR 量不小、又想守住代码质量底线的开发者和技术团队参考。Hermes 在这里指的是一个可私有化部署的智能体Agent框架它本身不自带“审查能力”真正管用的是你在里面配置的技能Skill和审查规则。换句话说Hermes 是一副骨架你得往里面喂规则、喂上下文、喂 API Token它才能帮你把 GitHub PR 里的问题一条条揪出来。下面我从头到尾拆开讲。1. 为什么要把 PR 审查交给 Hermes 智能体1.1 人工审查正在拖累团队的四个隐形问题先说个真实场景。团队五个人平均每个 PR 改动 300 行reviewer 往往要花 30 到 60 分钟才能把代码看完、理解上下文、把意见写得有理有据。如果一天有 10 个 PR光是等待审查和反复沟通就要占掉一个人半天的工作量。这还只是时间成本。更麻烦的是标准不统一。老张强调代码要精简小李重视注释完整王姐盯的是边界条件三个人审同一个 PR给出的意见经常打架。新来的同事看了更崩溃他不知道到底该听谁的项目代码风格就这样慢慢变成了“四不像”。还有一类低级错误特别容易逃过人工眼睛比如密码硬编码、密钥泄漏进仓库、忘记处理空指针、依赖引入过期版本。这类问题在 diff 里有时候就一两行reviewer 看快了很容易漏掉但它们往往就是线上事故的导火索。最后一个问题是上下文断裂。人工审查的时候reviewer 不太可能主动去查这个 PR 涉及的历史背景、相关 issue、之前的设计文档所以经常给出“只见树木不见森林”的意见。而这些问题恰恰是自动化智能体最容易补齐的短板。1.2 Hermes 智能体到底能做什么我在第一次接触 Hermes 这类智能体的时候第一反应是“这不就是个能跑脚本的机器人吗”后来配置完技能模块才发现它的核心价值在于能把“工具调用”和“语义理解”结合起来。具体的说Hermes 能在 PR 触发后自动完成五件事第一拉取 PR 的元信息和完整 diff第二按文件类型和变更范围匹配对应的审查规则第三对新增或修改的代码做静态扫描命中我们预设的规则库第四把 diff 和项目历史上下文丢给大模型引擎做语义层面的分析判断逻辑缺陷、边界遗漏、设计一致性问题第五把结果以评论、行内注释或 Check 报告的形式回写到 GitHub。它和传统工具的差别在于SonarQube、ESLint 这类工具能查出“语法层面”的毛病但对“这个函数在执行顺序上有个隐患”、“这块逻辑和项目里的缓存方案不一致”这类问题就无能为力。Hermes 因为接了语义模型层恰好能把这两层能力叠加起来用这才是自动审查真正的价值所在。2. 环境准备Hermes Agent 的安装与 GitHub 接入2.1 Hermes Agent 部署方式怎么选部署 Hermes Agent 这件事不同团队诉求不一样我建议按照规模来定没必要一上来就上微服务。最轻量的方式是本地安装。如果你是个人开发者或者三五人的小团队直接在一台 Linux 服务器或者本地开发机上装 Hermes用命令行启动一个 Worker 进程让它监听仓库的 Webhook 或者轮询 GitHub API 就行。安装本身不复杂准备好 Python 3.9 环境拉取 Hermes 的发布包配置好依赖初始化仓库账号基本上十分钟能搞定。如果团队规模大一些、任务量重推荐使用 Docker 部署。Hermes 官方仓库里带了 Dockerfile 和 docker-compose 配置把应用容器、数据库用来存历史审查记录、队列组件用来处理并发请求一并编排好。这样做的好处是升级和回滚非常方便而且 Worker 可以水平扩展。两种方式的核心区别在于资源占用和管理成本。本地安装适合随时改代码、调试技能配置的场景Docker 部署则更接近生产环境适合稳定跑服务。我自己是先在本地把 Skill 调通再打包成镜像扔到服务器上两边不耽误。2.2 打通 GitHubToken 权限设计是安全底线Hermes 要读 PR、写评论、更新状态必须拿到 GitHub 的访问凭证。这里用到的标准方式是创建 Personal Access TokenPAT但 Token 的权限范围一定要遵循最小化原则。我踩过的坑是第一次图省事勾了 repo 全权限后来 Token 不小心被推到公开仓库凌晨三点收到 GitHub 的安全告警邮件那滋味真不好受。正确做法是如果你只想读取 PR 信息和写审查评论只勾选repo读、pull_requests写、statuses写这三个范围。如果要走 Check Run 报告方式还要加上checks: write权限。Token 的存放也有讲究不要硬编码在配置文件里更不要提交到代码仓库。我通常用环境变量或者密钥管理服务来保存启动 Hermes 时动态读入。GitHub 端到端传输用 HTTPS配置里不要关闭证书校验。如果公司内部用的是私有化部署的 GitHub Enterprise只要在 Hermes 配置里把github_base_url指向自己的域名就可以其余逻辑完全一致。2.3 审查规则文件Hermes 的“大脑”从哪来Hermes 最核心的部分是它的技能配置也就是 Skill。刚接触的时候觉得这个概念有点虚后来理解了Skill 本质上就是一组“触发条件 审查动作 输出模板”的组合。我的配置文件采用 YAML 格式大致结构是这样的skills: - name: review_security trigger: file_patterns: - **/*.py - **/*.js event: pull_request rules: - id: RULE-001 description: 检查是否包含硬编码密钥 pattern: (?i)(api[_-]?key|password|secret)\\s*[:]\\s*[\][^\] level: error - id: RULE-002 description: 检查是否使用不安全的函数 pattern: \\b(eval|exec)\\s*\\( level: warning model: provider: deepseek task: review temperature: 0.2 output: format: github_review_comment这个文件解决的是“谁触发、查什么、怎么查、结果怎么写”四个问题。很多团队上手 Hermes 之后觉得效果不好大多是因为规则写得粗糙——规则太少漏报多规则太严误报多所以规则的迭代要做好长期的心理准备。3. 核心实现Hermes 自动审查 PR 的完整链路3.1 用 GitHub Actions 把 Hermes 接入 PR 流程Hermes 本身不直接挂在 GitHub 上它需要一条“输入通道”。最推荐的方式是配置 GitHub Actions在 PR 创建或更新时自动把事件推给 Hermes。我在仓库.github/workflows/review.yml里写了这么一份配置name: Hermes PR Review on: pull_request: types: [opened, synchronize, reopened] issue_comment: types: [created] jobs: trigger-review: runs-on: ubuntu-latest if: | (github.event_name pull_request) || (github.event_name issue_comment contains(github.event.comment.body, /hermes-review)) steps: - name: 通知 Hermes 审查 run: | curl -X POST https://your-hermes-server/api/review \ -H Authorization: Bearer ${{ secrets.HERMES_API_KEY }} \ -H Content-Type: application/json \ -d { repo: ${{ github.repository }}, pr_number: ${{ github.event.pull_request.number }}, user: ${{ github.actor }} }这里有一个细节值得注意我加了/hermes-review这个斜杠命令作为手动触发的开关。这样改动很小的 PR 不想走完整审查流程reviewer 可以在评论区发一句/hermes-review skip跳过或者主动指定让 Hermes 再查一遍。这也是一个比较讨巧的设计避免机器人每次把所有 PR 都查一遍引发开发者的逆反情绪。3.2 Hermes 审查逻辑的四层拆解Hermes 收到触发请求之后内部实际是分层执行的。你可以理解为一条流水线每一层只干一件事。第一层是数据采集层。它先根据仓库名和 PR 编号调用 GitHub 的 API拿回 PR 标题、描述、提交列表、文件变更列表再逐个请求每个文件的 diff。注意 GitHub 的 diff 对大 PR 有限制超过一定行数的文件可能拿不全这个在 5.3 里我会详细说。第二层是规则匹配层。它把 diff 按文件类型拆开后缀名是.py就走 Python 规则集后缀名是.js就走 JavaScript 规则集。这一步是纯静态扫描不调模型速度快、成本低。也就是说规则匹配层的效率非常高短则几秒长则几十秒就能把明显的安全问题、风格问题过滤出来。第三层是语义分析层。这一步会把每个变更文件里相关的函数上下文、调用关系、最近的提交信息甚至关联的 issue 标题都拼成一段结构化文本然后发给大模型接口让它判断逻辑漏洞、边界遗漏、设计不一致等问题。模型输出的 JSON 结果会转换成标准审查意见。第四层是输出层。Hermes 会把规则层和语义层的结果合并按照文件、行号排序过滤掉重复项再通过 GitHub API 的createReviewComment和createCheckRun方法写到 PR 页面上。到这里整个链路就完整跑通了。3.3 审查结果怎么做到“可信任”自动化审查最大的敌人是“狼来了”——如果机器人经常报一些废话、错报开发者就会无视它的存在。所以我特别在意结果的可信度设计。在 Hermes 里每条规则命中后都会带一个置信度字段这个字段是由规则类型和模型输出共同决定的。比如硬编码密钥这种模式匹配规则置信度直接给 1.0而模型分析出来的“可能存在逻辑问题”置信度可能只有 0.6 到 0.8这时 Hermes 不会直接给 error 级别而是用 warning 级别输出并且生成一段带推理过程的说明文字方便开发者判断。另外过滤机制也很重要。我在输出层配置了去重逻辑如果两条规则命中的代码片段重叠超过 80%只保留严重级别更高的一条如果模型给出的意见和规则层重复只保留规则层结果。这样可以基本杜绝同一个问题被机器人用两种方式反复提的情况。4. 实操记录一次完整的 PR 自动审查过程4.1 典型配置实战用 Docker 启动 Hermes 服务以 Docker 部署为例我先把整个服务编排好。注意到热词里有 “docker hermes” 和 “hermes 安装部署”这里就重点演示一下容器化部署的操作。项目根目录放一个docker-compose.ymlversion: 3.8 services: hermes-db: image: postgres:14-alpine environment: POSTGRES_DB: hermes POSTGRES_USER: hermes POSTGRES_PASSWORD: ${HERMES_DB_PASSWORD} volumes: - hermes_db_data:/var/lib/postgresql/data hermes-worker: build: . command: hermes worker start environment: HERMES_GITHUB_TOKEN: ${HERMES_GITHUB_TOKEN} HERMES_GITHUB_BASE_URL: ${HERMES_GITHUB_BASE_URL:-https://api.github.com} HERMES_MODEL_API_KEY: ${HERMES_MODEL_API_KEY} depends_on: - hermes-db hermes-api: build: . command: hermes api serve --port 8080 ports: - 8080:8080 depends_on: - hermes-worker volumes: hermes_db_data:这套编排的核心逻辑是API 服务负责接收 GitHub Actions 的 HTTP 触发请求Worker 负责消费队列中的审查任务PostgreSQL 用来存历史记录和状态信息。三个服务独立的部署方式让后续扩容变得非常简单比如审查量大时多起几个 Worker 就行。启动命令就一行docker-compose up -d --build启动后可以用docker-compose logs -f hermes-worker看 Worker 的日志确认服务已经连上 GitHub API。初次启动不出意外的话控制台会打出一段初始化信息表示技能配置已加载、模型接口连通性检测通过。4.2 一次真实的 Python PR 审查执行记录配置好之后我在测试仓库开了一个 Python PR故意注入三类问题一个硬编码的数据库密码、一个使用eval()的代码片段、一段明显重复的函数逻辑。PR 刚创建GitHub Actions 的 workflow 就触发了大约 5 秒后 Hermes API 收到请求Worker 开始拉取 diff。整个处理过程我观察了日志规则匹配层花了大约 1.8 秒语义分析层花了 12 秒最后结果回写到 GitHub。最终 PR 页面上出现了三条评论第一条是高亮的RULE-001命中直接指出了password sk_live_xxx这一行级别是 error第二条是RULE-002命中指出eval(input())存在代码注入风险级别也是 error第三条是语义审查模型给出的意见它提示我重构那段重复的验证逻辑并给出了具体的合并建议。整个过程从 PR 创建到审查完成花了不到 20 秒。我让同事再人工审一遍他基本只需要看那三条评论十分钟之内就能把问题确认完。和之前动辄半小时起步的流程相比效率提升是实打实的。4.3 效率、成本和准确率的三方权衡当然自动化审查不是免费的。模型调用按 token 计费规则匹配需要占用一定的 CPUDocker 容器和数据库也要持续消耗内存。我统计了一下一个规模为 500 行的 PR一次完整审查大约消耗 8000 个输入 token 和 2000 个输出 token按照当前市面上的模型定价单次成本约合人民币几毛钱。但这里有一个容易被忽略的经济账如果人工审查一次需要 40 分钟按开发人力成本折算下来一次审查的人力成本少说几十元。让 Hermes 先用几分钟把 80% 的机械性问题扫掉人工只专注于最关键的 20% 逻辑和设计问题成本和效率的账是划算的。准确率方面我做了三个星期的测试规则层的准确率非常高几乎没有误报模型层的误报率大约在 15% 左右但只要把输出级别控制在 warning并且附上推理过程开发者的接受度还是相当高的。5. 常见问题与排查技巧实录5.1 容器化部署最常见的三个坑Docker 部署 Hermes 时最容易踩的坑是环境变量引用问题。docker-compose.yml里用了${HERMES_GITHUB_TOKEN}这样的变量但如果你没有在 shell 里 exportCompose 会把它当成空字符串传入容器。结果就是 Hermes 启动正常但调用 GitHub API 时一直报 401 认证错误。这个问题的排查方法很简单在启动前用docker-compose config命令检查一遍渲染后的环境变量确认值是否被正确替换。第二个坑是网络代理问题。容器内部访问 GitHub API 时如果宿主机处在受限网络环境下需要使用代理服务但容器本身拿不到宿主机的代理配置。解决办法是在docker-compose.yml里显式传入HTTP_PROXY和HTTPS_PROXY环境变量这样 Hermes 才能通过代理正常访问外部 API。第三个坑是数据库权限问题。PostgreSQL 容器初次启动时会创建数据库和数据目录但如果数据卷的属主和容器内进程的 UID 不一致会出现 Permission Denied 导致数据库一直重启。解决办法是在宿主机上把数据目录的权限改成 777或者启动容器时通过--user参数指定对应的 UID。5.2 漏报误报怎么治理自动化审查跑起来之后最怕两件事该查的没查到和不该报的老瞎报。从我的经验看针对漏报应该在规则层和维护策略上做文章而不是一味增加规则条数。比如我每两周会从线上事故中提取一次关键词把它们补充进规则库形成“事故驱动”的规则迭代闭环。针对误报关键是给规则设置合理的级别和触发范围。比如某些规则只对核心目录生效对测试目录直接豁免某些警告级别的问题不要做成强阻塞而是以建议形式在评论区列出。这样既能减少开发者对机器人的反感也能保持规则的长期效力。还有一个小技巧遇到模型语义层给出的模糊意见可以让 Hermes 在评论里追加一句“本条建议由 AI 生成仅供人工 reviewer 参考”并给出置信度数值。这么一个小小的改变开发者的信任度提升非常明显。5.3 GitHub API 限流与超大 PR 问题GitHub 的 REST API 按每小时请求数做了限制个人 Token 普通请求限制为 5000 次/时。单看数字似乎够用但如果你启用了轮询模式一分钟内扫一遍所有待审查 PR高峰期很容易直接把额度打满。我的解决方案是尽量采用 Webhook Actions 的触发方式而不是让 Hermes 持续轮询。这样只有 PR 真正变化的时候才消耗 API 调用平时完全不占额度。另外代码变更获取尽量用application/vnd.github.diff这种轻量化格式减少不必要的元数据请求。超大 PR 是另一个头疼问题。我碰到一次 PR 改了 3000 行GitHub 返回的 diff 被截断导致 Hermes 只分析了前一部分代码。解决办法是引入分页拉取逻辑把超大的 diff 按文件或者按 commit 拆成多段逐段审查、最后汇总。配置里也可以设置一个阈值超过 2000 行的大 PR 不自动审查改为人工触发避免流程耗时太长和 token 成本飙升。5.4 多语言项目的规则冲突处理一个仓库同时包含 Python、JavaScript、SQL 和 Dockerfile 的项目在规则层很容易出现“同一条规则在不同语言上的命中语义不同”的问题。比如eval()在 JavaScript 里是危险操作在 Python 里同样危险但它俩的上下文和修复建议不一样。Hermes 的规则文件是按语言分目录配置的千万不要把所有规则写到一个文件里。我在实践中用了这样的目录结构thinking/ # 这是规划目录忽略实际上我用的结构是rules/ python/ security.yaml style.yaml javascript/ security.yaml style.yaml dockerfile/ best_practice.yaml触发时 Hermes 会根据文件后缀只加载合适的规则集。这样不但能避免不同语言之间的规则干扰还让规则文件本身的维护变得简单清晰。6. 值得一试的扩展方向与个人心得整套 Hermes 自动化 PR 审查方案跑通之后可以探索的扩展方向还挺多的。比如我把“审查历史”和“代码质量趋势”结合起来每周生成一份各模块缺陷密度报告定期发现哪些模块经常出问题再反推代码重构优先级。Hermes 还可以对接飞书或钉钉机器人审查完成之后把结论推送到即时通讯群省去反复刷新页面的等待感。从维护者的角度来看我特别建议团队在铺开自动化审查时不要急着一口气吃成胖子。先选择一种语言、一类问题比如安全漏洞试点跑两周看看团队接受度和误报率再慢慢扩展规则范围。相比一步到位这样循序渐进的方式反而更容易在团队里形成稳定的使用习惯。最后再说一句实在话Hermes 这类自动化审查工具定位是给你干活、帮你扫雷但真正决定代码质量的还是人的设计能力和责任心。把重复劳动交给机器人把人从流水线上解放出来去思考更有价值的问题这才是我们折腾这套自动化方案的初衷。