1. 从提示词到产线:为什么代码审查需要多智能体
代码审查这件事,做过几年开发的人都有体会——它从来不是“看一眼代码有没有语法错误”这么简单。一个合格的审查者需要在几分钟内同时完成好几件事:判断这段逻辑是否覆盖了边界条件、命名是否表意清晰、有没有隐藏的性能陷阱、是否违反了团队约定、测试用例是否充分、以及最容易被忽略的——这段代码三个月后别人还能不能看懂。人类审查者做这些事靠的是经验积累和上下文直觉,但人有个致命问题:会累、会漏、会碍于情面放水。
LinkedIn 工程团队搞的那套多智能体代码审查系统,本质上就是在解决这个“人会累”的问题。他们不是简单调一个 API 让大模型看看代码,而是把审查这件事拆成了多个角色,每个角色有自己的提示词、自己的关注面、自己的输出格式,最后再汇总成一份可操作的审查意见。这套思路在业内通常被称为“多智能体协作”,但落到代码审查这个具体场景里,它其实更像是一个流水线上的质检工位——每个工位只盯一个维度,但合起来覆盖了整条产线的质量要求。
我最初接触这个方向是在一个十几人规模的研发团队里,当时我们尝试用单模型做代码审查,效果很不稳定。同一个 PR,有时候能挑出空指针风险,有时候连明显的资源泄漏都视而不见。后来分析原因才发现,单模型在面对长 diff 时注意力会被稀释,而且“审查代码”这个提示词本身太宽泛,模型不知道优先看什么。LinkedIn 这套多智能体方案给我的启发是:与其让一个模型做所有事,不如让多个模型各做一件事,每个模型的提示词都收窄到具体维度,输出也结构化,最后用规则或另一个模型来汇总。
这套方案适合谁来参考?我认为三类人最值得看:一是正在搭建内部代码审查工具链的工程效能团队,二是想用 AI 辅助自己 review 代码但不知道怎么设计提示词的普通开发者,三是做 AI Agent 编排、想了解多智能体在真实产线怎么落地的人。它不要求你一开始就上全套基础设施,哪怕你只是在本地用几个提示词模板手动跑一遍,也能感受到“分维度审查”和“一锅炖审查”的差距。
2. 多智能体拆解:每个角色到底在干什么
2.1 为什么不是“一个超级提示词”搞定所有事
很多人第一反应是:我写一个超长的提示词,把命名规范、安全漏洞、性能问题、测试覆盖全列进去,让模型一次性输出不就行了?我试过,结论是——在短 diff 上勉强能用,一旦 diff 超过两三百行,模型就开始“选择性失明”。这不是模型能力问题,而是注意力机制和上下文窗口的固有特性。你把十个维度的要求塞进一个提示词,模型在生成时会在这些维度之间来回跳跃,最后每个维度都只覆盖了一部分。
LinkedIn 的做法是把审查维度拆开,每个维度对应一个独立的智能体。常见的拆分方式包括:逻辑正确性审查、安全性审查、性能与资源审查、可读性与命名审查、测试覆盖审查。每个智能体拿到的是同一份 diff,但提示词完全不同。逻辑审查的提示词会强调“找出边界条件遗漏和状态不一致”,安全审查的提示词会强调“检查输入校验、权限判断和敏感数据暴露”,性能审查则会关注“循环内重复计算、不必要的内存分配、N+1 查询”。
这种拆分的核心优势在于:每个智能体的提示词可以写得非常具体,甚至可以附带该维度的检查清单和反例。比如安全审查智能体的提示词里可以直接写“如果看到字符串拼接 SQL,必须标记为高风险;如果看到用户输入直接拼进命令,必须标记为严重”。这种具体程度在单提示词里是做不到的,因为会和其他维度的要求互相干扰。
2.2 智能体之间的协作模式:并行还是串行
拆成多个智能体之后,下一个问题是怎么组织它们。LinkedIn 的方案里我观察到两种模式并存:并行审查和串行审查。并行是指所有智能体同时拿到 diff,各自独立输出审查意见,最后汇总。串行是指前一个智能体的输出会作为后一个智能体的输入,比如先做逻辑审查,再把逻辑审查的结论交给安全审查做二次判断。
并行模式的好处是快,适合在 CI 流水线里做第一道过滤。串行模式的好处是深,适合在合并前做最终把关。实际产线里通常是混合的:并行跑一轮快速审查,把明显问题挑出来;然后对高风险 PR 再跑一轮串行深度审查。这里有个经验:并行审查的智能体数量不要超过五个,否则汇总阶段的噪声会很大,审查意见之间互相矛盾的情况会显著增加。
还有一个容易被忽略的点是智能体之间的“通信协议”。如果每个智能体输出的格式都不一样,汇总起来会非常痛苦。LinkedIn 的做法是强制所有智能体输出结构化结果,通常是一个 JSON 数组,每个元素包含文件路径、行号、问题类型、严重程度、建议修改方案。这个结构统一之后,汇总智能体或者规则引擎就能很容易地做去重、排序和优先级合并。
2.3 提示词设计的核心原则:收窄、举例、给格式
多智能体方案里,提示词的质量直接决定审查质量。我总结下来有三个原则最关键。第一是收窄,每个智能体的提示词只关注一个维度,不要贪多。第二是举例,在提示词里给出该维度的正例和反例,模型对例子的敏感度远高于抽象描述。第三是给格式,明确告诉模型输出应该长什么样,包括字段名、字段类型、严重程度的枚举值。
举个例子,逻辑审查智能体的提示词可以这样写:你是一个专门审查逻辑正确性的资深工程师,只关注边界条件、状态一致性和错误处理,不要评论命名和格式。如果发现数组访问没有判空,标记为 high;如果发现异常被吞掉没有日志,标记为 medium。输出格式为 JSON 数组,每个元素包含 file、line、severity、issue、suggestion 五个字段。这种提示词写出来之后,模型的输出稳定性会大幅提升。
还有一个实操心得:提示词里要明确告诉模型“如果某个维度没有问题,返回空数组,不要强行找问题”。我早期版本的提示词没有这句话,结果模型为了“交差”经常编造一些不存在的问题,浪费了大量审查时间。加上这句话之后,误报率明显下降。
3. 从本地脚本到产线流水线:落地路径拆解
3.1 最小可行版本:本地手动跑通多智能体审查
如果你不想一上来就搞复杂的基础设施,可以先在本地用最朴素的方式跑通流程。准备一个 Python 脚本,读取 git diff,然后依次调用多个提示词模板,每个模板对应一个审查维度。调用方式可以用任何你熟悉的大模型 API,关键是把 diff 和提示词拼在一起发出去,拿到结构化输出后打印出来。
这个阶段不需要考虑并发和缓存,重点是验证提示词的效果。我建议先拿自己过去一周的 PR 做测试,看看每个智能体能不能稳定地挑出你当时确实犯过的错误。如果某个智能体总是漏报或者误报,就回去改它的提示词,加例子、加反例、加格式约束。这个迭代过程通常需要两到三轮,每轮改完都要用同一批 PR 做回归测试,确保改动没有引入新的问题。
本地版本还有一个好处是可以快速对比不同模型的效果。同一个提示词,换一个模型跑,输出质量可能差很多。我实测下来,逻辑审查和性能审查对模型能力要求较高,安全审查和命名审查相对宽松一些。你可以根据每个维度的实际表现来分配模型资源,重要的维度用更强的模型,辅助维度用轻量模型。
3.2 接入 CI:让审查在每次提交时自动触发
本地跑通之后,下一步是接入 CI 流水线。通常的做法是在 PR 创建或更新时触发一个 job,这个 job 拉取 diff,调用审查服务,然后把结果以评论形式贴回 PR。这里有几个工程细节需要注意。第一是 diff 的获取方式,不要用 git diff 的原始输出,最好用 git diff --unified=0 或者解析成结构化格式,否则模型会被大量的上下文行干扰。第二是超时控制,审查服务不能阻塞 CI 太久,一般设置 60 到 120 秒的超时,超时后降级为只跑快速审查。
第三是结果去重和合并。多个智能体可能对同一行代码提出相似意见,汇总时需要做去重。简单的做法是按文件路径和行号分组,同一组内保留严重程度最高的那条。复杂一点的做法是用一个汇总智能体来做语义去重,但这样会增加延迟和成本。我的经验是先用规则去重,规则覆盖不了的再交给汇总智能体。
还有一个产线特有的问题:误报处理。任何自动审查工具都会有误报,关键是给开发者一个方便的反馈渠道。LinkedIn 的方案里有一个“忽略此建议”的按钮,开发者点击后这条建议会被记录,后续同类建议会被降权。这个反馈闭环非常重要,没有它,开发者很快会对审查结果失去信任,直接全部忽略。
3.3 产线级优化:缓存、并发和成本控制
当审查量上来之后,成本和延迟会成为主要矛盾。优化手段主要有三个方向。第一是缓存,同一个 diff 的审查结果可以缓存起来,如果 PR 只是 rebase 或者改了 commit message,diff 没变,就直接复用缓存结果。第二是并发,多个智能体的调用可以并行发出,把总延迟从串行的 N 倍降到接近单次调用的水平。第三是分级,不是每个 PR 都需要跑全套审查,可以根据改动文件类型和改动量来决定跑哪些智能体。
成本控制还有一个容易被忽略的点:提示词的长度。diff 本身可能很长,如果每个智能体都把完整 diff 塞进提示词,token 消耗会非常大。实际产线里通常会对 diff 做预处理,比如只保留改动行和前后各三行上下文,或者按文件切分,每个文件单独审查。LinkedIn 的方案里还用了 diff 摘要技术,先用一个轻量模型把 diff 压缩成一段描述,再把描述发给审查智能体,这样能大幅降低 token 消耗,但会损失一些细节,适合对精度要求不高的维度。
4. 实操中踩过的坑和排查技巧
4.1 智能体输出格式不稳定怎么办
这是最常见的问题。你明明在提示词里写了“输出 JSON”,但模型有时候会在 JSON 外面包一层解释文字,有时候字段名拼错,有时候严重程度用了不在枚举值里的词。解决办法分三层。第一层是在提示词里加更强的格式约束,比如“只输出 JSON,不要有任何其他文字,第一个字符必须是 [,最后一个字符必须是 ]”。第二层是在代码里做容错解析,用正则提取 JSON 部分,字段名做模糊匹配,严重程度做映射。第三层是加一个格式修复智能体,把不合规的输出丢给它,让它转成标准格式。
我实测下来,第一层能解决百分之八十的问题,第二层解决百分之十五,剩下百分之五才需要第三层。所以不要一上来就搞格式修复智能体,先把提示词和解析逻辑做好。
4.2 多个智能体意见冲突怎么处理
比如逻辑审查智能体说某段代码有边界问题,性能审查智能体说这段代码没问题,你该信谁?我的处理原则是:严重程度高的优先,安全审查的结论优先于其他维度,逻辑审查的结论优先于性能审查。如果两个智能体对同一行代码给出了矛盾的建议,就在 PR 评论里同时展示两条,让开发者自己判断。不要试图用规则自动裁决所有冲突,有些冲突本身就是有价值的信号,说明这段代码确实值得多看一眼。
4.3 开发者不信任自动审查结果怎么办
这个问题比技术问题更难解决。我的经验是:第一,不要一开始就全量开启,先在小范围团队里试用,收集反馈,把误报率降到可接受水平再推广。第二,审查意见要给出具体的修改建议,不要只说“这里有问题”,要说“建议改成这样”。第三,允许开发者一键忽略,并且忽略后不再重复提醒。第四,定期回顾被忽略的建议,如果某类建议被大量忽略,说明提示词需要调整。
还有一个技巧是让审查结果可解释。每条建议都附带“为什么这么判断”的简短说明,比如“检测到数组访问前没有判空,根据历史数据这类问题在线上导致过空指针异常”。这种解释能显著提升开发者的信任度。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决建议 |
|---|---|---|---|
| 审查结果为空 | diff 获取失败或提示词过于严格 | 检查 diff 是否为空,检查提示词是否要求“无问题返回空数组” | 打印 diff 长度,放宽提示词中的判定条件 |
| 误报率高 | 提示词过于宽泛或缺少反例 | 检查提示词是否收窄到单一维度,是否给了反例 | 增加反例,明确“以下情况不算问题” |
| 输出格式混乱 | 提示词格式约束不够强 | 检查是否明确要求纯 JSON 输出 | 加强格式约束,增加容错解析 |
| 审查延迟高 | 串行调用或 diff 过长 | 检查调用方式是否并行,diff 是否做了预处理 | 改为并行调用,对 diff 做摘要或切分 |
| 同一问题重复报告 | 多个智能体覆盖了同一维度 | 检查各智能体的提示词是否有重叠 | 调整提示词边界,汇总阶段做去重 |
| 开发者大量忽略 | 建议不可操作或误报多 | 检查建议是否具体,误报率是否过高 | 增加修改建议,允许一键忽略并记录反馈 |
5. 提示词模板参考与迭代方法
5.1 逻辑审查智能体提示词模板
你是一个专门审查逻辑正确性的资深工程师。只关注边界条件、状态一致性、错误处理和资源管理,不要评论命名、格式和性能。如果发现数组或对象访问前没有判空,标记为 high。如果发现异常被捕获但没有日志或没有重新抛出,标记为 medium。如果发现循环条件可能导致死循环,标记为 high。如果某个维度没有问题,返回空数组,不要强行找问题。输出格式为 JSON 数组,每个元素包含 file、line、severity、issue、suggestion 五个字段。只输出 JSON,不要有任何其他文字。
这个模板的关键在于“只关注”和“不要评论”这两个约束,它们把智能体的注意力锁死在逻辑维度上。severity 的枚举值也要在提示词里明确,避免模型自创等级。
5.2 安全审查智能体提示词模板
你是一个专门审查安全问题的资深工程师。只关注输入校验、权限判断、敏感数据暴露和注入风险,不要评论命名、格式和性能。如果发现用户输入直接拼接到 SQL 或命令中,标记为 critical。如果发现敏感数据被写入日志或返回给前端,标记为 high。如果发现权限判断缺失或可以被绕过,标记为 critical。如果某个维度没有问题,返回空数组。输出格式为 JSON 数组,字段同上。只输出 JSON。
安全审查的严重程度整体要比其他维度高一档,因为安全问题的后果通常更严重。critical 这个等级只在安全维度使用,这样汇总时可以优先处理。
5.3 提示词迭代的实操方法
提示词不是写一次就完事的,需要持续迭代。我的做法是建立一个“审查案例库”,每次发现误报或漏报,就把对应的代码片段和期望的审查结果记录下来。迭代提示词时,用这个案例库做回归测试,确保改动解决了目标问题,同时没有破坏已有的正确行为。案例库不需要很大,积累到三五十个案例就能覆盖大部分常见场景。
迭代频率建议是每两周一次,每次只改一个智能体的提示词,改完跑一遍案例库,观察通过率变化。如果通过率下降,就回滚。这种小步快跑的方式比一次性大改要稳妥得多。
6. 多智能体方案的成本与收益权衡
6.1 什么团队适合上多智能体审查
多智能体审查不是没有成本的。它需要你维护多个提示词、一个汇总逻辑、一套反馈机制,还要承担比单模型更高的 token 消耗。所以它更适合那些已经有了一定工程效能基础、PR 量大、且对代码质量有持续要求的团队。如果团队只有三五个人,PR 一周不到十个,那用单模型加一个好提示词就够了,没必要上多智能体。
另一个判断标准是误报容忍度。多智能体方案在降低漏报的同时,通常会带来更多误报,因为多个智能体各自判断,总有一些会过度敏感。如果团队对误报非常敏感,那可能需要先优化单模型方案,把误报降到很低之后再考虑多智能体。
6.2 成本控制的几个实用手段
第一,按需触发。不是每个 PR 都跑全套审查,可以根据改动文件类型来决定。比如只改了文档,就跳过所有审查;只改了测试,就只跑逻辑审查。第二,分级模型。安全审查和逻辑审查用强模型,命名审查和格式审查用轻量模型。第三,缓存复用。同一个 diff 的审查结果缓存起来,避免重复计算。第四,diff 预处理。只保留改动行和必要上下文,减少 token 消耗。
我实测下来,这四种手段组合使用,能把多智能体审查的成本控制在单模型方案的 1.5 到 2 倍左右,但漏报率能降低一半以上。对于中大型团队来说,这个投入产出比是划算的。
6.3 收益的衡量方式
衡量多智能体审查的收益,不能只看“发现了多少问题”,还要看“这些问题如果漏到线上会造成多大损失”。我的做法是跟踪两个指标:一是审查阶段发现的问题数量,二是线上因代码问题导致的故障数量。如果前者上升、后者下降,说明审查有效。如果前者上升但后者没变,说明审查可能在挑一些无关紧要的问题,需要调整提示词的严重程度判定。
还有一个软性指标是开发者的反馈。定期收集开发者对审查结果的评价,看看他们认为哪些建议有价值、哪些是噪声。这个反馈比任何技术指标都更能反映审查系统的实际价值。
7. 从代码审查延伸:多智能体还能用在哪
代码审查只是多智能体协作的一个应用场景,这套“分维度、并行审查、结构化汇总”的思路可以迁移到很多其他领域。比如文档审查,可以拆成事实核查、逻辑连贯性、术语一致性、格式规范几个智能体。比如需求评审,可以拆成完整性、可行性、优先级、依赖关系几个智能体。甚至在设计评审里,也可以拆成视觉一致性、交互合理性、无障碍访问几个维度。
迁移的关键在于找到合适的维度拆分方式。拆分的原则是:每个维度有明确的判断标准,维度之间尽量正交,每个维度的输出可以结构化。只要满足这三点,就可以套用多智能体的框架。我在实际项目里试过把这套思路用在 API 设计评审上,拆成命名规范、参数设计、错误码、版本兼容性四个智能体,效果比单模型评审好很多,尤其是错误码和版本兼容性这两个容易被人类忽略的维度。
最后分享一个我在迭代提示词时的小技巧:把每个智能体的提示词当成一个“新人培训手册”来写。想象你带了一个刚入职的工程师,你要告诉他只看什么、不看什么、什么情况算严重、什么情况可以放过。用这种心态写出来的提示词,通常比抽象描述有效得多。