代码审查 Agent Harness 实战:AI 自动 Code Review

代码审查 Agent Harness 实战:AI 自动 Code Review
一、引言Code Review 的日常之痛如果你在团队里做过 Reviewer大概率经历过这些场景上午打开 GitHub10 个 PR 等着你每个 PR 上千行变更业务逻辑弯弯绕绕你一个一个文件翻看到眼睛发酸好不容易审到一半业务方过来说这个 PR 今天必须合你只能加速扫读结果低级 bug 溜进了生产环境更别提那些缩进混乱、命名随意、硬编码密钥的风格问题——你说吧显得啰嗦不说吧又膈应。这些痛背后是同一个矛盾好的 Code Review 需要深厚的知识储备和极大的耐心而人恰好在这两样上都有限度。AI 不会倦怠不会漏看一个空指针也不会对连续十次同样的缩进错误感到厌烦。问题只在于怎么让 AI 真正理解你的代码库、你的审查标准并且能安全地操作文件系统Solon AI Harness 给出的答案是用 Agent 封装审查能力用沙盒隔离风险用子代理拆分关注点用 StopLoop 防止失控。本文基于 Harness 构建一个可投入使用的自动 Code Review Agent完整代码均可运行你可以直接拿来做团队内部的 AI 审查 Bot。二、场景规划自动审查 PR 的完整流程先定义我们要做什么。假设团队使用 Git 工作流每次 PR 触发一个 Webhook我们需要检出目标分支的代码到沙盒工作区让 Agent 读取全部变更文件理解改动的上下文执行多维度审查正确性、安全、性能、代码风格输出结构化的审查报告包括问题位置、严重级别、修改建议整个流程的核心是第 2-3 步这正是 Harness Agent 的职责范围。我们不需要 Agent 替我们做 CI/CD只需要它像一个人肉 Reviewer 一样读代码、思考、写评论。Harness 为这个场景提供了几个关键能力能力对应配置解决什么问题文件工具集ToolPermission.TOOL_PIAgent 可以 read/write/edit 工作区文件沙盒隔离.sandboxEnabled(true)、sandboxSystemRestrict(true)防止 Agent 误操作宿主机子代理AgentDefinitioncreateSubagent把不同维度审查交给专门 Agent循环防护StopLoopInterceptor(5, 10)避免 Agent 陷入死循环会话压缩compressionThresholdsessionWindowSize长对话不爆 Token显式记忆.memoryEnabled(true)跨轮次保持上下文下面我们直接用代码实现。三、基础实现一个能审查 PR 的 Agent3.1 配置主引擎一切从HarnessEngine开始。我们需要指定工作区PR 代码所在目录和 Harness 的 Home 目录。importorg.noear.solon.ai.harness.HarnessEngine;importorg.noear.solon.ai.harness.permission.ToolPermission;importorg.noear.solon.ai.chat.ChatConfig;importorg.noear.solon.ai.agent.session.AgentSessionProvider;importorg.noear.solon.ai.agent.session.InMemoryAgentSession;importorg.noear.solon.ai.agent.react.intercept.StopLoopInterceptor;importjava.util.Map;importjava.util.concurrent.ConcurrentHashMap;publicclassCodeReviewApp{publicstaticvoidmain(String[]args){Stringworkspace/workspace/pr-1024;StringharnessHome.harness-home;AgentSessionProvidersessionProvidernewAgentSessionProvider(){privatefinalMapString,AgentSessionsessionMapnewConcurrentHashMap();OverridepublicAgentSessiongetSession(StringinstanceId){returnsessionMap.computeIfAbsent(instanceId,k-InMemoryAgentSession.of(k));}};HarnessEngineengineHarnessEngine.of(workspace,harnessHome).systemPrompt( 你是一个资深代码审查专家 CodeReviewer。 你的工作流程 1. 首先用 ls -R 列出工作区文件结构 2. 读取变更文件通常位于 src/ 下 3. 逐文件审查关注 - 逻辑正确性空指针、边界条件、并发隐患 - 安全性SQL 注入、硬编码密钥、权限绕过 - 性能不必要的循环、重复查询、内存泄漏 - 风格命名规范、异常处理、注释质量 4. 用 write 工具输出审查报告到 review-report.md 审查报告格式 ## 文件: {路径} ### [严重/一般/建议] {问题描述} - 位置: {行号} - 说明: {详细解释} - 建议: {修改方案} ).sessionProvider(sessionProvider).sessionWindowSize(20).compressionThreshold(100,512_000).maxTurns(30).autoRethink(true).toolsAdd(ToolPermission.TOOL_PI).modelAdd(newChatConfig().then(slf-{slf.setApiUrl(System.getenv(LLM_API_URL));slf.setApiKey(System.getenv(LLM_API_KEY));slf.setModel(deepseek-v4-flash);})).sandboxEnabled(true).sandboxSystemRestrict(true).stopLoopInterceptor(newStopLoopInterceptor(5,10)).memoryEnabled(true).build();// 执行审查AgentSessionsessionengine.getSession(pr-1024-review);varresultengine.prompt( 请审查以下 PR 变更内容 分支: feature/user-login - main 变更文件: - src/main/java/com/example/UserService.java - src/main/java/com/example/UserController.java - src/main/resources/application.yml 请按照系统提示词的流程进行全面审查并将报告写入 review-report.md。 ).session(session).call();System.out.println(审查完成result.getContent());}}这段代码定义了 Agent 的人格和边界。系统提示词是关键——它告诉 Agent 它是什么角色、应该按什么流程工作、输出什么格式。通过write工具让 Agent 自己生成审查报告到工作区方便后续 CI 流程读取。3.2 StopLoop 与沙盒安全兜底StopLoopInterceptor是 Harness 的安全阀。LLM 在推理中可能陷入重复循环——比如不断修正同一个问题、反复读取同一个文件。new StopLoopInterceptor(5, 10)的含义如果 Agent 连续 5 次输出语义上相似的内容或累计循环超过 10 次拦截器主动终止推理并返回当前结果。沙盒模式sandboxEnabled(true)确保所有文件操作被限制在工作区目录内。Agent 即使产生了幻觉想要写入系统目录沙盒会直接拒绝并返回权限错误。四、运行效果一次真实的审查输出假设 PR 中有一个典型的 Java 文件UserService.javapublicclassUserService{privateJdbcTemplatejdbc;publicUserfindUser(Stringid){Stringsqlselect * from users where id id;// SQL 注入returnjdbc.queryForObject(sql,User.class);}publicvoidupdateUser(Useruser){Stringsqlupdate users set name ? where id ?;jdbc.update(sql,user.getName());// 缺少 id 参数}}Agent 生成的审查报告review-report.md大致如下## 文件: src/main/java/com/example/UserService.java ### [严重] SQL 注入漏洞 - 位置: 第 6 行 - 说明: 使用字符串拼接构建 SQL参数 id 未做任何转义恶意用户可构造特殊 id 执行任意 SQL。 - 建议: 改用占位符方式jdbc.query(select * from users where id ?, User.class, id) ### [严重] 参数缺失导致 SQL 执行异常 - 位置: 第 12 行 - 说明: update 方法声明了两个占位符 ?但只传入了一个参数 user.getName()缺少 id 参数。 - 建议: 补充 id 参数jdbc.update(sql, user.getName(), user.getId()) ### [一般] 注入依赖未使用接口 - 位置: 第 4 行 - 说明: 直接注入 JdbcTemplate 实现类建议面向接口编程。 - 建议: 通过构造器注入 JdbcTemplate。这个报告的质量已经超过很多初级开发者的审查水平。更关键的是它不挑食——100 行和 10000 行的 PR 对它来说只是时间问题。五、进阶多维度子代理分布式审查当项目规模变大单个 Agent 的全能模式开始吃力它既要懂安全又要懂性能调优还要背代码规范。Harness 的子代理机制让这件事变得优雅——主 Agent 做路由子 Agent 做专精。5.1 定义三个专用子代理importorg.noear.solon.ai.harness.agent.AgentDefinition;// 安全审查员AgentDefinitionsecurityDefAgentDefinition.builder().name(security-reviewer).description(应用安全专家负者审查代码中的安全风险).toolsAdd(read,ls).systemPrompt( 你是一名应用安全专家。审查代码中的安全风险 - SQL / NoSQL 注入 - XSS、CSRF、SSRF - 硬编码密钥、Token、密码 - 权限校验缺失 - 不安全的反序列化 输出 JSON 格式 {issues: [{severity:critical|major|minor, line:N, type:security, desc:..., fix:...}]} ).build();// 性能审查员AgentDefinitionperfDefAgentDefinition.builder().name(performance-reviewer).description(性能优化专家负责审查代码中的性能问题).toolsAdd(read,ls).systemPrompt( 你是一名性能优化专家。审查代码中的性能问题 - N1 查询、循环内调用远程服务 - 不必要的对象创建、自动装箱 - 线程阻塞、锁竞争 - 大事务、长连接、缓存使用不当 输出 JSON 格式同上type 为 performance。 ).build();// 代码风格审查员AgentDefinitionstyleDefAgentDefinition.builder().name(style-reviewer).description(代码规范专家负责审查代码风格问题).toolsAdd(read,ls).systemPrompt( 你是一名代码规范专家。审查代码风格问题 - 命名不规范不遵循驼峰/常量命名 - 方法过长超过 50 行应拆分 - 异常捕获过于宽泛catch Exception - 魔法数字未定义常量 输出 JSON 格式同上type 为 style。 ).build();// 全部注册到引擎engine.getAgentManager().addAgent(securityDef);engine.getAgentManager().addAgent(perfDef);engine.getAgentManager().addAgent(styleDef);5.2 主 Agent 编排子代理主 Agent 通过 system prompt 教会自己如何编排// 在 engine 构建时调整 systemPrompt.systemPrompt( 你是代码审查的主协调员 CodeReviewOrchestrator。 工作流程 1. 列出工作区文件识别变更文件列表 2. 对于每个变更文件依次分发给三个专家子代理 - security-reviewer安全审查 - performance-reviewer性能审查 - style-reviewer风格审查 3. 通过 getAgentManager().getAgent(name) 获取子代理定义 4. 用 createSubagent(definition).build() 创建子代理实例 5. 调用子代理审查文件 6. 收集所有子代理的结果合并为完整报告 7. 写入 review-report.md )5.3 多维度审查的执行流程一次完整的 PR 审查经历以下步骤主 Agent 启动 ├─ 列出文件清单 ├─ 读取 UserService.java ├─ 创建 security-reviewer 子代理 → 返回安全问题 ├─ 创建 performance-reviewer 子代理 → 返回性能问题 ├─ 创建 style-reviewer 子代理 → 返回风格问题 ├─ 读取 UserController.java ├─ 重复上述子代理分发... ├─ 合并所有 JSON 结果 └─ 写入 review-report.md最终报告带维度标签## 文件: UserService.java ### [严重][security] SQL 注入漏洞 - 第 6 行 ... ### [严重][correctness] 参数缺失 - 第 12 行 ... ### [minor][style] 常量命名不规范 - 第 3 行 ... ### [minor][performance] 循环内调用数据库 - 第 20 行 ...每个问题前面带[维度]标签一目了然。团队可以配置 CI 规则只要存在critical级别的安全漏洞就阻止合并。六、总结用 Solon AI Harness 构建 Code Review Agent本质上是把人工审查的经验沉淀为系统提示词 工具权限 子代理编排的组合。回顾核心要点主引擎配置通过链式 API 在一处完成所有设置包括模型、工具、会话、安全策略子代理拆分用AgentDefinition定义专精角色主 Agent 按需调度每个子代理只关注一个维度沙盒 StopLoop两个安全机制确保 Agent 在可控范围内工作不会越狱也不会空转完整的会话管理sessionProvider、sessionWindowSize、compressionThreshold共同确保长对话不丢上下文这套方案可以每天自动帮我们审查大量 PR拦截大量低级缺陷和安全漏洞。下一步可以计划接入私有知识库团队编码规范、历史事故文档让 Agent 的审查标准与团队沉淀对齐——那是 Harness 的 memory 能力的用武之地。