前阵子跟一位做研发效能的朋友聊天他说现在团队里最耗人的环节不是写代码而是等代码评审。一个PR挂两三天没人看是常事就算有人review了也经常是看个大概就approve真正的问题反而沉淀不下来。我理解他的处境因为我自己也经历过这个阶段——直到我给团队的GitHub仓库接入了基于Hermes的自动化代码评审系统让大模型以智能体Agent的方式参与PR审查情况才明显改善。这篇文章不是搬运什么高大上的概念而是把我从选型、架构到踩坑的完整过程记录下来给同样想给PR评审提效的团队一个能直接照着搭的参考。文章里会涉及Hermes这个开源智能体框架的部署方式、它和GitHub API的交互逻辑、Prompt模板的设计思路以及我在实际运行中遇到的问题和调优经验。无论你是研发效能工程师、技术负责人还是单纯对“AI写代码评审意见”这件事感兴趣的开发者这篇文章应该都能给你一些可落地的思路。1. 整体设计与方案选型1.1 为什么给PR配上自动化评审代码评审这件事理论上是在提质量、守基线但实际上它经常成为研发流程里的瓶颈。PR越多每个PR的等待时间越长评审者一看diff过大、情绪先崩一半草草扫一眼就approve等于没审。另一方面人的注意力是有限的看前面十几个文件时还精神抖擞看到后面十几个文件时已经处于“差不多就行了”的状态。这就是我决定引入自动化评审的起点——不是取代人而是先把那些需要耐心、细致、重复劳动的部分接过去。自动化评审能覆盖的恰恰是人工最容易漏掉的部分边界条件没处理、异常路径没覆盖、敏感信息被打进日志、新引入的依赖存在已知漏洞。这些东西不像缩进和命名那样一眼能看到但它们才是上线后真正会出事故的地方。Hermes做这件事的优势在于它不是一套写死的规则引擎而是能理解PR上下文、能调用工具、能按照指令输出结构化结果的智能体。这意味着它可以真正“读”diff而不是靠正则去匹配问题模式。1.2 为什么选Hermes而不是现成Code Review工具市面上不是没有现成的自动化代码评审工具SonarQube、Codacy、CodeRabbit这些我都试过。它们各有长处比如SonarQube在静态分析和规则覆盖上非常成熟CodeRabbit能直接在PR上评论但用下来总有几个绕不过去的痛点。最核心的问题是“死板”。规则引擎只能发现你预先定义好的问题而代码里的坑往往是业务相关的、上下文相关的规则根本描述不出来。举个例子一个支付模块的PR把金额计算从BigDecimal换成了double静态规则不一定能识别出这是精度风险但一个能读懂业务上下文的大模型可以。第二个痛点是定制成本高很多工具想注入团队自己的规范、架构约束、常见反模式清单需要写插件或者用它们特定格式的规则维护成本并不低。而Hermes这种Agent框架的玩法完全不同你给他一个角色、一堆上下文、一份团队规范它能自己“思考”怎么审。相当于你雇了一个懂业务、懂规范的reviewer而不是买了一个只会背答案的扫描器。当然选择Hermes还有一个很现实的考虑自托管、数据可控。代码是公司最核心的资产我不想把所有diff都丢给一个第三方的SaaS服务去分析。Hermes本身是开源框架模型可以接私有化部署的推理服务整个链路的数据流都是可控的。这一点对中大型团队来说可能比功能本身更重要。1.3 一套PR评审系统的最小闭环长什么样把整套系统拆开看其实就是一个非常标准的数据处理闭环触发、取数、推理、回写。触发环节靠GitHub的Webhook或者GitHub Actions的pull_request事件来监听PR动作取数环节拿到PR的标题、描述、文件变更列表和完整diff推理环节Hermes作为Agent把这些信息整理成上下文交给大模型去分析产出评审意见回写环节通过GitHub API把评审意见以Review或评论的形式贴回PR页面。这个概念模型非常重要。很多人在搭类似系统时一上来就陷入“怎么让模型给出高质量意见”的纠结但其实前面两个环节没做好后面模型再强也白搭。就像你让一个资深工程师去评审但你只把目标文件路径告诉他不给他看diff和需求背景他能审出什么所以这套系统里我最先花时间打磨的其实是“怎么把PR的信息完整、准确地喂给Hermes”而不是急着调Prompt。下面几个小节我会把每个环节的关键细节展开讲。2. 核心细节解析Hermes如何读懂一个PR2.1 从Webhook事件到上下文构建GitHub的pull_request事件会在不同时机触发常见的有opened新建PR、synchronize提交更新、review_requested请求评审。我在设计时并没有让Hermes在每次事件触发时都全量跑一遍而是做了区分opened时做完整评审synchronize时只评审增量变更review_requested时如果之前已经评论过就静默跳过。这个策略有效避免了“每次提交都疯狂刷屏”的尴尬也省了不少模型调用费用。触发之后的关键操作是拉数据。这里有一个顺序问题GitHub事件payload里其实只带了PR的元信息不包含完整的diff内容所以必须用API去拉。我常用的几个接口和参数如下拉取PR详情GET /repos/{owner}/{repo}/pulls/{number}用来拿标题、描述、基础分支、目标分支等信息。拉取文件变更列表GET /repos/{owner}/{repo}/pulls/{number}/files返回每个文件的文件名、状态、新增行数、删除行数和patch片段。拉取提交历史GET /repos/{owner}/{repo}/pulls/{number}/commits用来理解这个PR的开发过程。这里有一个容易踩的坑files接口返回的patch有时候是被截断的尤其当文件变更特别大时。GitHub API对单文件patch长度有上限如果你直接拿这个片段塞给模型可能看不出关键问题。我的做法是检测到patch内容不完整时再单独用GitHub的compare接口拉一次完整diffGET /repos/{owner}/{repo}/compare/{base}...{head}这样能拿到全量变更。2.2 三个关键信息源PR描述、Diff、Commit历史喂给Hermes的上下文不是越多越好而是越“有效”越好。我总结了三个必带的信息源缺一个都会明显影响评审质量。第一个是PR描述。一个认真写的PR描述本身就包含了改动的动机、影响范围、测试计划这些东西对评审至关重要。但现实是很多PR描述就一句话“fix bug”遇到这种情况我会让Hermes先从commit message里尝试推断意图甚至允许它追问作者补充信息。第二个是diff本身。这是评审的主体也是最需要做加工的部分。直接把几万行的diff一股脑丢给模型效果通常很差一是上下文窗口不够二是在海量改动里模型的注意力会被稀释。我的做法是先让Hermes做一次“预筛选”按文件类型、改动量、风险等级分类把高风险的改动比如涉及鉴权、支付、并发控制、数据迁移的代码优先提取出来再针对这些重点文件做深度评审。低风险文件比如改名、格式化、配置文件统一给一个轻量结论即可。第三个是commit历史。这是很多人会忽略的信息源。PR是一个演进过程单个提交可能是有问题的但最终合入状态可能已经修正了。Hermes在评审时如果只看最终diff可能会误报“这个错误是从上一版引入的”这种半对半错的问题而结合commit历史它能判断某个问题是否已经在中途被修复过避免重复评论低级问题。2.3 Prompt模板设计与评审规则落地Prompt设计是整套系统里最微妙的部分。坦白说第一次写评审Prompt时我犯了所有新手都会犯的错——要求太多太全结果模型输出了一堆正确的废话。“注意代码质量”“关注潜在问题”“给出建议”这种话说了等于没说。后来我总结出一个有效套路给角色、给流程、给边界、给格式。角色要具体。不要写“你是一个代码审查助手”而是要写“你是一名拥有十年经验的资深后端工程师擅长发现并发、性能、安全方面的问题”。角色越具体模型调用知识的方式就越接近那个角色的判断习惯。流程要固定。让Hermes按“先概括PR目标 → 再按文件逐个分析 → 最后汇总风险和阻塞项”的顺序输出。固定流程的好处是评审结果稳定不会这次输出一段总结下次输出十条零散评论。边界要清晰。明确告诉模型“哪些不该管”。比如缩进、命名风格这类问题除非严重到影响阅读否则不要提。因为这类低价值评论会拉低整个系统的信任度开发者的注意力是有限的被噪声刷屏之后真正的严重警告反而会被无视。这是我在实际运行中感受最深的一点。格式要结构化。让每个问题都包含文件路径、行号、严重级别、问题描述、修复建议。只有形成了固定格式后续才能做统计分析才能对接门禁系统才能让开发者快速定位问题。下面是我整理后一直在用的一份精简版Prompt模板供你参考你是一位资深软件架构师正在为一个团队执行代码评审。请严格按以下步骤进行 ## 输入信息 - PR标题{title} - PR描述{body} - 变更文件{files} - Diff片段{diff} ## 评审步骤 1. 用一句话概括这个PR想解决的问题。 2. 逐个分析变更文件重点检查逻辑正确性、并发安全、边界条件、安全风险、性能隐患、测试覆盖。 3. 在所有分析完成后汇总为评审结论。 ## 输出格式 对每个问题输出如下结构的条目 - 位置文件路径:行号 - 级别严重 / 建议 / 疑问 - 描述问题是什么为什么是问题 - 建议给出具体的修复方案或示例代码 ## 约束 - 忽略缩进、命名风格、格式化等非功能性意见。 - 不要重复多个提交中已经修复过的问题。 - 如果某个文件没有实质性问题不要强行评论。 - 如未发现严重问题请在最后明确写明“本轮未发现阻塞性问题”。这份模板不复杂但该有的约束都有了。我第一次上线时用的是冗长版本模型输出反而发散换成这个精简版本之后评审意见的可读性和采纳率都提升了一个档次。3. 实操过程从安装Hermes到自动评论上PR3.1 环境准备与Hermes安装部署先交代一下我部署Hermes的环境一台普通的8核16G云服务器Ubuntu 22.04Docker已安装。我个人建议有条件的话用Docker部署原因是Hermes依赖的Python环境和底层库比较多直接装在宿主机上容易污染系统环境升级回滚也麻烦。当然如果你只是本地试玩直接用pip装也没问题。以我用的版本为例基础安装命令如下# 方式一pip安装 pip install hermes-agent # 方式二Docker部署 docker pull hermes-agent:latest docker run -it --name hermes \ -e LLM_API_KEYyour_key \ -e GITHUB_TOKENyour_token \ hermes-agent:latest --help安装完成后先跑一下hermes --help看看CLI入口是否正常。不同发行版的命令入口可能有细微差异有报错的话以项目仓库README里的说明为准。装好之后先别急着配PR审查建议先用自带的交互模式跑一次最简单的对话确认Hermes能正常调用大模型接口。我见过很多同学一上来就配全套YAML结果跑不通都不知道是哪一层的锅。先验证底层连通性再往上搭业务这个排错顺序能省掉大量时间。3.2 配置GitHub访问凭证Hermes要读取PR信息、提交评论必须通过GitHub API进行身份认证。这里有两种方式我分别说下使用场景。第一种是使用个人访问令牌PAT在GitHub账号的Settings → Developer settings → Personal access tokens里创建。创建时勾选repo相关权限尤其是repo和pull_requests权限。这种方式配置最简单但令牌挂在个人账号下处理组织仓库PR时会有权限边界问题而且如果创建者的账号被禁用系统就瘫痪了。我建议个人实验或小团队自用用PAT就够了。第二种是创建GitHub App权限更细可以精确到只读代码、写入PR评论而且运行在应用身份下不依赖任何个人账号。这种方式适合组织级使用也更容易通过权限策略保证安全。配置过程稍微复杂一些需要先注册App、生成私钥、安装到目标仓库然后把私钥信息传给Hermes。如果你管理的仓库比较多或者对权限隔离很敏感强烈建议用GitHub App方案。无论用哪种方式凭证都建议通过环境变量或独立的密钥管理服务注入不要硬编码在配置文件里。下面是我推荐的配置方式export GITHUB_TOKENghp_xxxxx export LLM_API_KEYsk-xxxxx然后在Hermes的配置文件里通过环境变量名引用不直接写明文。3.3 编写PR评审Agent的完整配置示例拿到令牌之后关键的步骤是写Hermes的配置文件。这个文件定义了Agent的角色、模型参数、评审策略、输出方式等核心行为。我用的配置如下重点字段的用途我在后面逐个解释llm: provider: deepseek # 可替换为 openai、anthropic 或本地推理服务 model: deepseek-chat api_key_env: LLM_API_KEY temperature: 0.2 # 评审场景尽量低,减少随机性 max_tokens: 4000 github: token_env: GITHUB_TOKEN api_base: https://api.github.com agent: name: pr-reviewer system_prompt_file: ./prompts/pr_reviewer.md max_diff_length: 30000 # 超长diff截断阈值,按字符计 context_units: - pr_description - commits - diff - related_issues review: comment_style: review_thread # 以GitHub Review Thread形式输出 max_comments: 20 # 单次评审最多评论数 skip_major_version_diff: false skip_paths: - *.lock - package-lock.json - go.sum danger_only: false配置里几个关键点我展开说一下。temperature评审任务需要相对确定、严谨的输出温度设太低会显得机械设太高容易胡说。我实测0.2是个不错的平衡点写代码时我可能用0.7但评审意见我更希望它“稳”。max_diff_length这个阈值关系到成本和质量。diff太大时直接截断会产生垃圾评审我的方案是不硬截断而是让Hermes先做分文件分析再把结论合并。如果你的配置里没有分文件处理能力那宁可让单文件diff小一点也不要一口吃成胖子。skip_paths把锁文件和带hash的依赖文件从评审范围里排除省token又省评论额度。第一次跑的时候我忘了配这个结果每个package-lock.json都收到几十条先生成建议直接把真实的评审意见淹没在噪声里翻车翻得很惨。3.4 用GitHub Actions自动化触发配置文件准备好了怎么把“每次新PR产生”和“Hermes跑一次评审”关联起来有两种思路一种是自己在服务器上监听Webhook另一种是直接在仓库里放一个GitHub Actions工作流。我倾向后者因为Actions本身就是GitHub托管的运行环境不用自己维护监听服务而且Secret管理、权限控制都是现成的。这是我的workflow示例name: Hermes PR Review on: pull_request: types: [opened, synchronize] jobs: hermes-review: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - name: Checkout code uses: actions/checkoutv4 with: fetch-depth: 0 - name: Set up Python uses: actions/setup-pythonv5 with: python-version: 3.11 - name: Install Hermes run: pip install hermes-agent - name: Run Hermes PR review env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} LLM_API_KEY: ${{ secrets.LLM_API_KEY }} run: | hermes pr-review \ --repo ${{ github.repository }} \ --pr ${{ github.event.pull_request.number }} - name: Post review comment uses: actions/github-scriptv7 with: script: | const fs require(fs); const body fs.readFileSync(review_output.md, utf8); await github.rest.pulls.createReview({ owner: context.repo.owner, repo: context.repo.repo, pull_number: context.issue.number, body: body.substring(0, 65000), event: COMMENT });这段workflow有几个细节值得注意。permissions字段里pull-requests: write必须显式声明否则默认的GITHUB_TOKEN没有写入PR评论的权限。fetch-depth: 0是为了让Hermes能拿到完整的git历史如果只保留latest commit部分需要对比历史提交的评审逻辑就会失效。另外on.pull_request.types我只保留了opened和synchronize。这样设计是刻意的PR刚开时做一次全面评审后续每次push新commit时再做一次增量评审既不会漏又不会在每次标签变更、标题修改时重复跑。3.5 评审结果回写与质量控制Hermes跑完之后核心问题是结果怎么呈现给开发者。我建议用GitHub官方的Review功能而不是普通评论。因为Review功能可以关联到具体的commit和代码行还能把评论折叠成“review thread”开发者可以直接在页面里逐个回复交互体验好很多。我在workflow里用的就是pulls.createReview接口。这个环节还要考虑一个噪音控制问题同一个PR反复被synchronize如果每次都全量评论评论数会爆炸。我的解决方案是让Hermes把每次评审的结论摘要和已评论的问题ID记录到本地状态文件在PR更新后只提交“新增问题”和“已修复问题”的变化而不是重复罗列旧问题。这个状态管理逻辑写在Hermes的Agent脚本里本质上就是维护一个以PR编号为维度的状态缓存。质量控制的另一个手段是“人工抽查反馈闭环”。自动化评审上线初期我每周会抽几个PR对比Hermes的评审意见和资深工程师的意见统计漏报率和误报率。发现问题就往Prompt里补约束或加few-shot示例。这个迭代过程很重要因为大模型的评审能力是可以通过Prompt调优持续提升的不调就浪费了。4. 常见问题与排查技巧实录4.1 高频报错速查表这套系统跑了大半年我把遇到过的典型问题整理成了一张速查表。这些坑不是网上抄来的都是我一行一行查日志试出来的现象可能原因排查思路403 / 401 认证失败Token权限不足、过期、或GitHub App安装未授权目标仓库先确认Token在curl -H Authorization: Bearer $TOKEN https://api.github.com/user下能通再看scope最后检查App对仓库的访问权限评论没有出现在PR上Actions job缺pull-requests: write权限或createReview接口调用参数不对打开Actions日志看返回错误重点看Resource not accessible by integration一类报错Hermes报上下文长度超限diff过大超过模型上下文窗口调大max_diff_length不是根本解建议改成按文件粒度分批分析再汇总每push一次就重复评论没有状态缓存逻辑在Agent脚本里维护“已评论问题ID集合”只提交增量意见评审内容泛泛而谈Prompt角色不具体约束太少按2.3节的模板重写Prompt给角色、给流程、给边界、给格式模型乱报问题上下文里缺少PR描述和commit背景确认context_units里开启了pr_description和commits单文件patch内容不完整GitHub API对超大diff有截断换用compare接口拉完整diff或让Hermes直接checkout目标分支本地对比4.2 评审质量不及预期的调优思路“评审质量不高”是上线后最常听到的反馈具体表现就是误报多、漏报也多。我调优时一般按照下面的顺序来排查效果比较明显。先看上下文是否完整。我见过很多人调了半天Prompt结果问题出在PR描述和commit历史根本没喂进去模型只能蒙。优先确认Hermes拿到的数据是不是完整、准确的。第二步看温度参数。温度过高会让模型在“可提可不提”的问题上产生大量发散意见把评审结果调成0.2以下往往立竿见影。第三是看Prompt约束。如果模型总在纠结变量命名、代码风格这类琐碎问题就在Prompt里明确禁止如果模型总是漏掉并发、安全这类深层次问题就需要提供针对性的few-shot示例先喂一两个典型漏洞案例给模型“打样”。最后还可以考虑换更强的模型。我实测过同一个Prompt在小模型上输出质量明显低于大模型尤其对于需要多步推理的跨文件评审任务模型的逻辑能力差距是实打实的。4.3 实用避坑清单最后分享几个长期运行后才领悟到的细节每条都是拿实际故障换来的。第一不要在主干分支上直接测试。刚部署时我在项目的master分支上实验了一次结果Hermes把存量代码的所有潜在问题全评论了一遍几百条噪音评论差点把PR页面刷爆。稳妥的做法是先在测试仓库或draft PR上跑通确认评论策略和噪音控制没问题了再放到正式流程上。第二关注敏感数据。如果你使用的是云端大模型API送进去的diff必须经过脱敏检查。一个常见场景是代码里出现了数据库连接串、云厂商AccessKey这些信息会被随diff一起发给模型服务。我的做法是在喂给模型之前做一层脱敏替换用占位符替换疑似密钥的字符串。即使你觉得“模型不会泄露数据”也挡不住这种信息的合规风险。这一点对自托管系统尤其需要重视。第三给Hermes设置明确的“红线”提示。比如“如果发现硬编码密钥、SQL注入、越权访问等安全问题必须标记为严重级别并在结论开头单独列出。”这种明确的安全红线能显著提升高价值问题的召回率而且它们通常是人工评审时最想第一时间看到的东西。5. 更进一步的扩展方向5.1 把评审结论接进门禁机制评论只是“告知”门禁才是“约束”。我目前的方案是让Hermes在评审结束后输出一份机器可读的JSON摘要包含是否发现严重问题、严重问题条数、哪些文件存在高风险等。这份JSON可以被CI脚本读取当严重问题数量超过阈值时直接在GitHub的required checks里标记为失败阻止PR合入。这个机制要做到可配置。比如新建的draft PR不设门禁普通PR只有严重级别问题才阻断核心模块的PR要求所有问题必须闭环才允许合并。这套规则我用一个简单的配置文件维护Hermes只负责产结果门禁逻辑完全独立方便调整和回滚。5.2 让评审Agent积累团队规范一篇好的博客值得一个赞但一套好用的评审系统最花时间的不是部署而是让Agent“懂你的团队”。我建议把团队的编码规范、架构约束、常见反模式案例整理成文档挂到Hermes的上下文目录里让它在每次评审之前自动加载。这样随着团队踩坑经验的积累评审Agent的“团队记忆”也在不断更新。我就在自己的项目里维护了一个team_rules目录里面按模块分类放着“服务间调用必须走网关”“数据库字段不允许直接删除只能标记废弃”“金额字段一律用Decimal”之类的硬性约定。这些内容写进Prompt会显得臃肿但作为附加上下文单独加载效果非常好Hermes在评审时真的会把它们当作判断依据。这套系统从我搭起来到现在已经跑了几个月最直观的感受是开发同学真正花在“等review”上的时间明显少了评审意见的质量也比之前纯人工时期更稳定。踩坑踩多了以后我最大的体会是自动化评审的核心不在模型多聪明而在你把评审的边界定义得多清楚。给Hermes一个明确的角色、一份团队规范、几条硬性红线它能跑得比大多数泛泛而谈的工具靠谱得多。如果你也在给团队搭类似的自动化评审链路或者已经在用其他Agent框架做PR审查欢迎一起交流实际运行中的经验和坑。这套路子里值得打磨的细节还有很多后面我会继续分享从门禁机制到评审质量评估的下一阶段实践。