资讯中心

25个技能+9条命令:将代码评审直觉转化为可安装的Agent技能

📅 2026/9/24 23:43:27
25个技能+9条命令:将代码评审直觉转化为可安装的Agent技能
1. 从“评审直觉”到可安装技能这件事到底在解决什么代码评审这件事做过几年的人都有体会真正值钱的不是“能看出 bug”而是那种说不清道不明的直觉。比如看到一段异常处理老工程师会本能地皱眉——不是语法错而是“这个 catch 把上下文吞了线上出问题根本查不到”。再比如看到某个函数里塞了七八个参数直觉会告诉你“这里迟早要炸”但你要让一个刚入行的人解释为什么他可能只能说“感觉不太优雅”。问题就在这。评审直觉高度依赖个人经验无法复制、无法传递、无法规模化。团队里有一个资深工程师代码质量就靠他一个人扛他一休假评审质量立刻掉一个档次。更麻烦的是AI 编码工具现在越来越普及agent 能帮你写代码、改代码、跑测试但它默认不懂你团队的评审标准——它写出来的东西语法没问题逻辑也跑得通可就是“不像我们团队会合入的代码”。这个项目要干的事就是把这层直觉从人脑里“抠”出来做成可安装、可分发、可组合的 skill。标题里说的“25 个技能9 条命令”本质是一套把评审经验结构化的方法每个 skill 对应一类具体的评审判断比如“异常处理是否丢失上下文”“命名是否暴露了实现细节”“并发访问是否有明确的同步边界”而 9 条命令则是把这些 skill 挂载到 agent 或 CLI 工作流里的操作入口。关键词里反复出现 skill、agent、CLI、命令、AI 编码说明这套东西的定位很明确它不是给人看的文档而是给 agent 用的能力包。你把它装进 codex cli、claude cli 或者自研的 agent 框架里agent 在生成或修改代码时就会自动带上这些评审约束。换句话说你不再需要每次都在 prompt 里写“注意异常处理”“注意命名规范”这些已经被固化成 skillagent 自己会去调用。适合谁来参考三类人最直接受益。第一类是带团队的技术负责人手里有评审标准但落不了地每次 review 都在重复讲同样的东西第二类是在做 agent 开发的人需要给 agent 注入领域判断力而不是只靠通用 prompt第三类是自己用 AI 编码工具的单兵开发者想让 agent 输出的代码更接近“能直接合入”的水平而不是每次都要自己再改一遍。我先把结论放前面这套方法的核心不是写 25 个 prompt而是把评审判断拆成“触发条件 检查动作 输出格式”三段式结构。后面会详细讲这个结构怎么设计以及为什么直接写 prompt 会失败。2. 为什么“写一堆 prompt”注定失败skill 和 agent 的本质区别很多人第一次听到“把评审直觉做成 skill”第一反应是那我写 25 个 prompt 不就行了每个 prompt 对应一条评审规则agent 需要的时候去查。这个思路听起来合理实际跑起来会崩原因在于 prompt 和 skill 在 agent 工作流里的角色完全不同。2.1 prompt 是“一次性指令”skill 是“可调用能力”prompt 的本质是你对模型说一段话模型基于这段话生成回复。它的生命周期很短一次对话结束就没了。你写“请检查异常处理是否丢失上下文”模型这次会检查下次你不写它就不检查。而且 prompt 之间会互相干扰——你同时塞 25 条规则进去模型注意力被稀释最后每条都只做到一半。skill 不一样。skill 是一个有明确输入输出契约的能力单元。agent 在运行过程中根据当前上下文判断“我现在需要做异常处理评审”然后主动调用这个 skillskill 返回结构化的评审结果agent 再决定怎么处理。这个过程中skill 不需要一直占用模型的注意力它只在被调用时生效。打个比方prompt 像是你每次做饭都口头告诉厨师“盐少放点、火别太大、菜要洗干净”skill 像是厨房里贴好的操作卡厨师做到某一步时自己去看对应的卡。前者依赖你每次都在场后者是厨房基础设施。2.2 agent 调用 skill 的触发机制agent 怎么知道该调用哪个 skill这取决于你的 agent 框架。常见的有两种触发方式。一种是基于工具描述匹配。每个 skill 注册成一个工具带一段描述比如“检查代码中的异常处理是否丢失了原始错误上下文”。agent 在处理代码时如果判断当前任务涉及异常处理就会匹配到这个工具并调用。这种方式对 skill 的描述质量要求很高描述写得太泛agent 匹配不准写得太窄又覆盖不到。另一种是基于显式规则触发。你在 agent 的工作流里定义当检测到代码变更涉及 try-catch 块时强制调用异常处理评审 skill。这种方式更可控适合评审这种“必须执行”的场景不依赖 agent 的自主判断。我实测下来评审类 skill 更适合第二种。因为评审是质量门禁不能靠 agent“想起来才做”。你可以在 agent 的 pre-commit 钩子或者代码生成后的后处理阶段固定挂载这几个 skill确保每次代码产出都过一遍。2.3 25 个技能怎么划分才不重叠25 这个数字不是随便定的。评审直觉如果拆得太粗比如只分“代码质量”“安全性”“性能”三类每个 skill 内部逻辑会极其复杂agent 调用后返回的结果也没法用。拆得太细比如“检查变量名是否超过 20 个字符”又太机械失去了“直觉”的价值。合理的划分维度是按判断类型分而不是按代码位置分。我梳理下来25 个 skill 大致落在这么几个簇里技能簇覆盖的判断类型典型 skill 举例错误处理异常是否被吞、错误是否可追溯、失败路径是否明确异常上下文保留检查、错误传播路径检查命名与抽象命名是否暴露实现、抽象层级是否一致、概念是否混淆实现细节泄漏检查、抽象层级一致性检查并发与状态共享状态是否有同步、锁粒度是否合理、状态变更是否可预测共享状态访问检查、锁范围合理性检查接口与契约参数是否过多、返回值是否明确、边界条件是否处理参数数量与内聚性检查、边界条件覆盖检查可测试性依赖是否可注入、副作用是否隔离、断言点是否明确依赖注入可行性检查、副作用隔离检查每个 skill 只负责一个判断类型内部逻辑保持单一。这样 agent 调用时目标明确返回结果也容易解析。25 个 skill 覆盖了日常评审中最高频的判断场景再多的场景可以通过组合已有 skill 来覆盖不需要无限扩张。注意skill 数量不是越多越好。每增加一个 skillagent 的匹配负担就增加一分。25 个是我实测下来在“覆盖度”和“匹配准确率”之间的平衡点。如果你团队有特殊评审标准优先考虑改造现有 skill 的判断逻辑而不是新增 skill。3. 9 条命令的设计逻辑让 skill 真正“可安装”skill 设计得再好如果安装和使用成本高团队里没人会用。9 条命令的存在意义就是把“安装 skill”这件事变成一条命令能搞定的事而不是让每个人去读文档、配环境、改配置文件。3.1 命令分组安装、挂载、执行、调试9 条命令我按功能分成四组每组解决一个阶段的问题。安装组2 条一条用于从技能仓库拉取 skill 包到本地一条用于把 skill 注册到目标 agent 框架。分开的原因是拉取和注册可能发生在不同环境——比如你在本地拉取但注册到远程的 agent 服务。挂载组3 条一条用于列出当前可用的 skill一条用于把指定 skill 挂载到某个工作流阶段比如代码生成后、提交前一条用于卸载。挂载是核心操作决定了 skill 在什么时机生效。执行组2 条一条用于手动触发单个 skill 对指定代码做评审一条用于批量触发一组 skill。手动触发主要用于调试和验证批量触发用于 CI 流程。调试组2 条一条用于查看 skill 的详细定义和触发条件一条用于模拟 agent 调用 skill 的过程输出中间结果。调试命令是给 skill 开发者用的普通用户用不到但必须有否则 skill 出问题时没法排查。3.2 为什么是 9 条而不是更少有人会问能不能合并成 3 条命令一条安装、一条挂载、一条执行技术上可以但实际用起来会很难受。合并后每条命令要带大量参数比如安装命令要区分“拉取”和“注册”就得加--modefetch或--moderegister用户记不住也容易输错。9 条命令的设计原则是一条命令只做一件事命令名直接体现动作。比如skill-fetch就是拉取skill-register就是注册skill-mount就是挂载。用户不需要记参数看命令名就知道干什么。这种设计在 CLI 工具里被反复验证过认知负担最低。3.3 命令与 agent 框架的对接方式9 条命令本身是 CLI 入口背后要对接不同的 agent 框架。对接方式有两种一种是命令直接操作 agent 框架的配置文件比如把 skill 注册信息写进 codex cli 的配置目录另一种是命令通过 agent 框架暴露的 API 做注册。我建议优先走配置文件方式。原因是 API 方式依赖 agent 框架的运行时如果 agent 没启动或者版本不匹配命令就失败。配置文件方式更稳定命令执行完就落盘agent 下次启动时读取配置生效。代价是可能需要重启 agent 才能加载新 skill但对于评审这种非实时场景重启成本可以接受。具体配置文件的格式取决于 agent 框架。以常见的 CLI agent 为例通常是一个 JSON 或 YAML 文件里面有一个 skills 数组每个元素包含 skill 名称、路径、触发条件。9 条命令里的注册命令本质就是往这个数组里追加或修改元素。{ skills: [ { name: exception-context-check, path: ./skills/exception-context-check, trigger: post-codegen, enabled: true } ] }这段配置的意思是把exception-context-check这个 skill 挂载到代码生成后的阶段启用状态。agent 在生成代码后会自动调用它。挂载命令做的就是修改trigger字段启用/禁用命令做的就是改enabled字段。4. 单个 skill 的内部结构触发条件、检查动作、输出格式前面讲了 skill 怎么划分、怎么安装现在拆开一个 skill 看内部。一个合格的评审 skill 必须包含三段触发条件、检查动作、输出格式。缺任何一段skill 都没法在 agent 工作流里稳定运行。4.1 触发条件什么时候该调用这个 skill触发条件回答的是“agent 在什么情况下应该调用我”。写得太宽agent 频繁调用浪费算力还干扰主流程写得太窄该调用的时候不调用skill 形同虚设。触发条件通常由两部分组成代码特征匹配和工作流阶段。代码特征匹配是指当前处理的代码里出现了什么模式比如“存在 try-catch 块”“存在共享变量访问”“函数参数超过 5 个”。工作流阶段是指当前处于 agent 流程的哪一步比如“代码生成完成后”“提交前检查”“代码评审请求时”。以异常上下文保留检查为例触发条件可以写成代码特征存在catch块且块内没有对捕获的异常对象做任何引用没有日志、没有重新抛出、没有包装工作流阶段代码生成后、提交前这两个条件同时满足时agent 才调用这个 skill。这样既不会漏掉真正有问题的代码也不会对正常的异常处理做无谓检查。4.2 检查动作具体查什么、怎么查检查动作是 skill 的核心逻辑。它要回答“调用我之后我具体做什么”。对于评审类 skill检查动作通常分三步定位、分析、判定。定位是找到需要检查的代码片段。比如异常上下文检查定位动作是“找到所有 catch 块提取块内语句”。分析是对定位到的片段做判断比如“检查块内是否有对异常对象的引用”。判定是给出结论比如“该 catch 块丢失了异常上下文建议至少记录日志或重新抛出”。这里有个关键点检查动作要尽量用确定性逻辑而不是让模型自由发挥。能用正则或 AST 匹配的就不要让模型去“理解”。模型的理解能力不稳定同样的代码两次调用可能给出不同结论。确定性逻辑保证每次结果一致评审才能作为质量门禁。当然有些判断确实需要语义理解比如“命名是否暴露实现细节”。这种场景可以让模型参与但要限定输出格式比如只允许输出“是/否 一句话理由”减少自由发挥空间。4.3 输出格式agent 怎么消费评审结果输出格式决定了 skill 的评审结果能不能被 agent 自动处理。如果输出是一段自然语言agent 还得再理解一遍效率低且容易出错。评审 skill 的输出应该是结构化的至少包含问题位置、问题类型、严重程度、建议动作。{ skill: exception-context-check, findings: [ { location: src/service/user.js:42, type: exception-context-lost, severity: high, message: catch 块未记录异常对象线上问题无法追溯, suggestion: 至少添加 logger.error(err) 或重新抛出 } ] }agent 拿到这个结构后可以直接决定是自动修复比如自动插入日志语句还是标记为待人工确认还是直接阻断提交。严重程度字段让 agent 能做分级处理high 级别阻断medium 级别警告low 级别仅记录。提示输出格式里的location字段要精确到行号。agent 后续如果要自动修复需要知道改哪里。行号信息在定位阶段就要采集不要等到输出时再去找。5. 把评审直觉“翻译”成 skill 的实操过程前面讲的是设计逻辑这一节讲具体怎么把一个资深工程师脑子里的评审直觉翻译成一个可运行的 skill。我拿“异常上下文保留检查”这个 skill 做完整示例其他 skill 可以照这个流程复刻。5.1 第一步找资深工程师做“判断复述”不要一上来就写代码。先找一个评审经验丰富的工程师给他看几段有问题的代码让他说出判断过程。关键是让他复述判断链路而不是只给结论。比如给他看这段try { await saveUser(user); } catch (err) { return null; }他可能会说“这个 catch 把 err 吞了线上出问题查不到原因。”你要追问你是看到什么才这么判断的他会说“catch 块里没有对 err 的任何引用直接 return null 了。”继续追问那什么情况下你觉得可以接受他会说“如果这个操作本身不重要失败也无所谓那可以不记录。但 saveUser 是写操作失败必须知道。”这个追问过程就是在提取判断链路。最终你得到的是触发特征catch 块内无 err 引用 上下文判断写操作失败需可追溯 结论丢失上下文需修复。5.2 第二步把判断链路拆成可执行步骤拿到判断链路后拆成 skill 能执行的步骤。以上面的例子用 AST 解析代码找到所有catch块对每个 catch 块检查块内语句是否引用了 catch 参数err如果无引用检查 try 块内的操作类型读操作还是写操作如果是写操作且无引用判定为“异常上下文丢失”严重程度 high如果是读操作且无引用判定为“异常被静默忽略”严重程度 medium第 3 步的“操作类型判断”需要一些规则比如函数名包含 save、create、update、delete 的视为写操作。这个规则不完美但比让模型自由判断稳定。后续可以逐步完善规则库。5.3 第三步写 skill 定义文件skill 定义文件通常包含元信息和执行逻辑。元信息包括名称、描述、触发条件执行逻辑可以用脚本实现也可以用配置化的规则引擎。name: exception-context-check description: 检查 catch 块是否丢失了异常上下文 trigger: code_pattern: catch block without exception reference workflow_stage: [post-codegen, pre-commit] check: steps: - action: find_catch_blocks - action: check_exception_reference - action: classify_operation_type - action: judge_severity output: format: json fields: [location, type, severity, message, suggestion]这个定义文件就是 skill 的“说明书”agent 读取它来了解 skill 的能力和调用方式。执行逻辑可以内联在定义里也可以指向外部脚本。我建议复杂逻辑用外部脚本简单逻辑内联这样定义文件保持可读复杂逻辑也方便单独测试。5.4 第四步用真实代码验证并调参skill 写完后拿团队历史代码跑一遍。重点看两个指标召回率真正有问题的代码有没有被检出和误报率没问题的代码有没有被误判。我实测下来第一版 skill 的误报率通常偏高因为规则太死。比如“catch 块内无 err 引用”这个规则会把一些故意忽略异常的代码也标出来。这时候要加例外规则比如 catch 块内有注释说明“ignored intentionally”的跳过检查。调参是个迭代过程不要指望一次到位。建议先在小范围代码库跑收集误报案例逐步加例外规则。等误报率降到可接受范围再推广到全量代码。6. 实测中踩过的坑和应对方式这套东西我从零搭到能用中间踩了不少坑。挑几个最有代表性的讲都是文档里不会写、但实际一定会遇到的。6.1 skill 之间互相干扰一个 skill 的修复建议触发另一个 skill 的告警最开始我把 25 个 skill 全部挂载到代码生成后阶段结果出现连锁反应。异常上下文检查 skill 建议“添加 logger.error(err)”agent 自动修复后日志规范检查 skill 又告警“日志缺少 traceId”。然后 agent 又去加 traceId加完后命名检查 skill 又告警“logger 变量名不符合规范”。这个问题本质是skill 执行顺序和依赖关系没定义。修复建议会改变代码改变后的代码可能触发其他 skill。如果顺序不对agent 会陷入无限修复循环。我的应对方式是给 skill 定义优先级和依赖。异常上下文检查属于“结构性问题”优先级高先执行日志规范属于“规范性问题”优先级低后执行。同时规定同一轮评审中一个 skill 的修复建议不立即执行而是收集所有 skill 的发现后统一处理。这样避免连锁触发agent 拿到完整问题列表后一次性修复。6.2 agent 匹配不到 skill描述写得太“专业”反而失效skill 描述我一开始写得很专业比如“检测异常处理路径中的上下文传播完整性”。结果 agent 匹配率很低很多该调用的时候没调用。后来发现agent 匹配 skill 时用的是语义相似度太专业的描述反而和实际代码场景的语义距离远。改成大白话后匹配率明显上升“检查 catch 块里有没有把错误吞掉”。这句话和代码场景的语义更接近agent 更容易匹配到。skill 描述是写给 agent 看的不是写给评审专家看的用词要贴近代码本身的表述。6.3 输出格式被 agent 忽略JSON 里混入了自然语言有段时间我发现 agent 拿到 skill 输出后不按预期处理排查后发现是输出 JSON 里混了自然语言。比如message字段我写了一句“这个 catch 块看起来有问题建议检查一下”agent 解析时把整句当成了问题类型导致后续逻辑错乱。修复方式是严格约束输出字段的取值。type字段只能是预定义的枚举值severity只能是 high/medium/lowmessage虽然可以自然语言但要在 skill 定义里明确“message 仅用于展示不参与逻辑判断”。agent 处理时只读结构化字段忽略展示字段。6.4 命令执行环境不一致本地能跑CI 里报错9 条命令在本地跑没问题挂到 CI 后报错。排查发现是 CI 环境里没有 skill 仓库的访问权限拉取命令失败。另外 CI 里的 agent 框架版本和本地不一致注册命令写的配置格式对不上。应对方式是给命令加环境检测和版本校验。拉取命令执行前先检查仓库可达性不可达时给出明确错误提示而不是静默失败。注册命令执行前检查 agent 框架版本版本不匹配时提示用户升级或降级 skill 包。这些检查增加了命令的健壮性避免在 CI 里出现难以排查的失败。7. 怎么把这套方法迁移到你自己的团队25 个 skill、9 条命令是我针对自己团队场景做的你直接拿去用可能不完全适配。但方法是可以迁移的核心就三步提取判断、结构化 skill、挂载到工作流。7.1 从团队评审记录里提取高频判断别凭空想 skill 清单。去翻团队最近三个月的代码评审记录把评审意见分类。你会发现高频意见集中在少数几类问题上比如“这里没处理空值”“这个命名容易误解”“这个并发访问没加锁”。这些高频意见就是你的 skill 候选。我统计过自己团队的评审记录前 5 类问题占了总评审意见的 70% 以上。把这 5 类做成 skill就能覆盖大部分评审场景。剩下的长尾问题等前 5 类跑顺了再逐步补充。7.2 先做 3 个 skill 跑通闭环再扩展不要一上来就做 25 个。先挑 3 个最容易结构化的判断做成 skill挂载到工作流跑通“代码生成 → skill 评审 → agent 处理 → 提交”这个闭环。闭环跑通后你会对 skill 的定义方式、触发时机、输出格式有实际体感再扩展就顺了。我第一版只做了 3 个 skill异常上下文检查、参数数量检查、命名规范检查。这三个逻辑简单、误报率低适合验证流程。跑了两周后才逐步加到 25 个。7.3 把 skill 仓库当成团队资产维护skill 不是做完就完了。团队评审标准会变代码风格会演进skill 也要跟着更新。建议把 skill 仓库当成团队资产来维护每个 skill 有负责人定期 review 触发条件和检查逻辑收集误报案例并修复。另外skill 仓库要版本化。不同项目可能用不同版本的 skill 集版本化后可以按项目挂载对应版本避免新 skill 影响老项目。9 条命令里的拉取命令支持指定版本就是为这个场景设计的。注意skill 更新后要重新跑验证。我遇到过更新了一个 skill 的触发条件结果误报率飙升的情况。原因是新条件匹配到了大量正常代码。每次更新 skill 后拿历史代码回归测试一遍确认召回率和误报率没有明显退化。8. 关于 skill 和 agent 配合的一点个人体会这套东西跑了大半年最大的体会是skill 的价值不在于“让 agent 更聪明”而在于“让 agent 更稳定”。agent 本身的能力已经够强了它缺的不是智力而是约束。评审 skill 就是给 agent 加约束让它在生成代码时知道哪些线不能踩。另一个体会是skill 的粒度比数量重要。我见过有人把 skill 拆得极细一个 skill 只检查一个变量命名规则结果 agent 匹配负担极重评审一轮要调用几十个 skill效率反而下降。25 个是我找到的平衡点每个 skill 覆盖一类判断既不过粗也不过细。最后说一个实际使用中的小技巧把 skill 的评审结果和人工评审结果做对比。定期抽一批代码同时跑 skill 评审和人工评审看两者的发现重合度。重合度高说明 skill 有效重合度低说明 skill 的判断逻辑和团队实际标准有偏差需要调整。这个对比机制让 skill 不会偏离团队真实需求也能持续发现新的评审模式。

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案