Headless Agent CLI:无头模式下的独立代码评审实践
1. Headless Agent CLI 与独立评审的场景匹配先把话说在最前面我第一次正儿八经把 codex cli 这类 agent CLI 跑成纯 headless、跑完整个仓库评审而不是顺便改几行代码的时候心里其实很没底。无头模式听起来很酷但真正把一个“有手有脚”的 AI agent 丢到命令行里自动干活不是把交互界面去掉那么简单。你得先想清楚什么任务适合让它独立跑什么任务一跑就容易跑偏。我跑了几十轮之后得到一个很明确的结论Headless 的 Agent CLI 最合适的用法是独立评审不是独立开发也不是独立修 bug。1.1 无头模式不是“无人驾驶”而是“不带交互地执行完整任务”很多人对 headless 的理解是“没人盯着AI 自己搞定一切”这其实是个误区。Headless 准确的翻译应该是“无头模式”可以把它理解成脱离交互界面、按预设指令执行完整任务的运行方式。Agent CLI 在这里的角色不是聊天机器人而是一个可以被脚本调用、被 CI 触发、被命令行参数驱动的自动化组件。打个比方。你在终端里敲codex进入交互模式那是你坐在驾驶座上AI 是副驾你们一起看路。而 headless 模式是 AI 自己坐在驾驶座上你只给了它一个目的地和一个“注意安全”的指令它踩油门、打方向盘、看红绿灯全靠自己。这个模式下最怕什么怕它自由发挥过了头。你会让一个没有交互界面的自动司机去干什么当然是让它做那些不需要临时决策、不需要创意摇摆、结果可以事后校验的事情。独立评审就是这样一个场景任务边界清晰评价标准相对明确产出物是报告而非直接修改。这也是我为什么坚持说“评审”是 headless agent CLI 的首选用法。因为评审天然适合被拆成“输入一个代码变更 → 输出结构化意见”的批处理流程而批处理正是无头模式最擅长的活。1.2 为什么评审比修复更适合 headless我见过不少人一上来就让 agent CLI 去“帮我修这个 bug”“把这个功能补完”。这类任务的共同特点是目标发散、需要反复确认、改完还得验证。headless 模式下 agent 一旦理解偏了就会沿着错误的路线越跑越远。它效率再高跑错方向也是白搭。而评审不一样。评审的输入输出非常清晰输入是 diff 或者一段代码输出是问题列表、风险等级、修改建议。即使 agent 判断错了最坏的结果也是报告里多了一条不准确的评论代码本身不受影响。这给了无头模式一个非常重要的安全垫任务的不可逆性低试错成本小。再说直接一点独立开发是“从 0 到 1”容错率低独立修复是“把错的对回来”需要理解上下文而独立评审是“挑出问题并说明理由”恰恰是当前大模型最稳定的能力区间。我实测下来模型在“寻找潜在缺陷、对照团队规范、判断代码风格一致性”这类任务上的稳定性明显高于“直接写一段完整可运行代码”和“精确修复一个复杂 bug”。这也是把 agent CLI 用在评审上最朴素的理由让 AI 做它擅长的事别拿它的短板去碰运气。2. 独立评审的整体架构与工作流设计确定方向之后就要考虑怎么搭一套真正能用的“独立评审”链路。这一步很容易犯的错误是以为只要把 PR 链接或者 diff 丢给 agent它就会像人一样自动去看相关文件、理解背景、给出高质量意见。实际上如果不做工作流设计headless agent 的表现会非常“飘”。我梳理了一套比较成熟的方案从输入到输出分成几个层次来讲。2.1 从 PR diff 到评审意见先搭一条最小可行链路一套最基础的独立评审链路至少包含四个环节变更提取 → 上下文组装 → 评审执行 → 结果落盘。每个环节都有可以直接照搬的做法。变更提取从版本管理平台拉取待评审的 PR 或 commit得到文件变更列表和 diff 内容。需要特别注意diff 可能很大不能一股脑全塞给 agent。上下文组装根据变更文件列表把相关文件的关键内容函数定义、依赖关系、调用方、测试用例读取出来和 diff 一起拼成一段结构化的“评审任务书”。评审执行以 headless 方式运行 agent CLI传入任务书和明确的评审规则让它独立输出评审意见。结果落盘将评审结果保存为结构化文件比如 JSON 或 Markdown并推送回版本控制平台或通知相关人员。我早期犯的一个低级错误就是把 diff 直接当 prompt 传给 agent然后问它“看看有什么问题”。结果它只能基于片段猜测意见大多是泛泛而谈的“建议增加错误处理”之类。后来我把“相关文件上下文”补上意见质量立刻上了一个台阶。2.2 让 agent “独立”的三个层次很多人理解的“独立”就是不给交互但实际操作里独立有三个层次缺一不可任务独立指的是 agent 能自主规划评审步骤不需要人一步步告诉它先看哪个文件再看哪个文件。环境独立指的是它在一个干净的、资源可控的沙箱里运行不会污染你的本地开发环境也不会因为缺少依赖而中途崩溃。判断独立指的是它依据你提供的规则和历史数据做评价而不是“想象”一个标准来打分。这里尤其要强调“判断独立”。我见过不少把代码评审跑成“夸夸群”的例子agent 输出的意见全是“代码结构清晰逻辑正确值得肯定”。这不是评审这是自动点赞。要避免这种情况必须在输入里注入明确的负面条件比如“如果发现资源泄漏风险请指出具体行和理由”而不只是“请检查代码质量”。规则写得越具体agent 的独立性才越有支撑。2.3 架构对比为什么说“评审”是转换成本最低的场景手工写一个评审脚本并不难难的是让它能复用、能接入现有流程。我把三种常见模式放在一起对比过这里直接贴出来供参考模式交互方式任务特点适合场景headless 适配度交互式调试多轮对话、实时确认目标发散、需要不断校正探索性开发、定位疑难 bug低批处理修改一次指令、静默执行有明确输入输出但改动有风险格式化、批量重构、简单修 bug中独立评审自动触发、报告产出只读为主、结果可校验代码评审、规范检查、风险预警高这个表格不是拍脑袋得出的是我在实际跑任务时观察到的规律。凡是需要“读代码 → 形成判断 → 输出报告”的headless 表现都很稳凡是需要“读代码 → 改代码 → 验证效果”的headless 就很容易失控。所以如果你刚开始尝试 agent CLI我建议从评审类任务入手体验会顺畅很多。3. 独立评审的核心参数与配置要点定好了工作流接下来是具体的配置。这部分是实操性最强的也是全网最零散的内容。我以 codex cli 为主要案例来讲其他同类 agent CLI 的参数名称可能不同但底层逻辑完全一致。3.1 model、token 与生成参数评审场景怎么选模型选择评审任务对推理能力要求不低我建议至少选择当前可用的最强推理模型。太小的模型容易出现“假阳性”——没问题的代码它非要挑点毛病或者反过来漏掉真问题。预算有限的话可以把评审分成两层第一层用轻量模型做规范检查比如 lint 风格、命名规则第二层用强推理模型做逻辑检查。分层的实测效果比单一大模型更稳成本还能降不少。token 预算这是最容易被忽略的坑。Agent CLI 的 token 消耗远比你想象得快它不光是生成报告要花钱逐行浏览代码、多次调用工具、内部“思考”都会消耗 token。我给一个常用的起步配置作参考评审单个文件时上下文窗口建议至少 16k评审整个 PR 时建议 32k 以上并且要设置输出 token 上限防止它生成一篇史诗级长文。temperature 设置评审是判断型任务不是创意型任务。我强烈建议将采样温度设为 0 或者接近 0 的极小值。温度高了输出会有随机性同一段代码跑两次可能给出不同的评审意见这在实际使用中会严重损害可信度。Git 提交的确定性还能靠 hash 保证评审结果的可复现性只能靠参数保证。还有一个参数是max_turns / 最大交互轮数。Headless 模式下最怕 agent 反复试探、绕圈子。我遇到过评审任务跑了 20 多轮才结束的情况原因就是它在不断重新读取同一个文件“确认细节”。限制最大轮数配合超时机制是保证链路稳定的关键。3.2 上下文窗口与仓库浏览策略评审一个 PR 时agent 不可能把整个仓库都读进上下文它必须决定先看什么、后看什么、省略什么。这个决策直接影响评审质量。我目前实践下来比较有效的做法是先给 agent 一个仓库地图再喂变更内容。所谓仓库地图就是项目的目录结构、每个模块的职责说明、核心文件的索引。有了这个基础agent 才知道改动涉及哪个模块、应该去哪些地方找关联代码。这一步可以用脚本自动生成也可以直接在系统提示词里写清楚。效果差异非常显著——没有地图时agent 经常会漏看跨模块的影响有了地图它至少知道要主动搜索引用关系。另外diff 的分块策略也值得多说一句。一次把所有变更文件都塞给 agent它会把注意力均匀分配导致重点不突出。我的经验是把变更文件按照“核心逻辑改动”和“外围改动”分类核心改动给更多 token 和更详细的关联上下文外围改动只需做基本检查。这相当于给 agent 划了优先级避免“眉毛胡子一把抓”。3.3 评审规则注入把团队规范写进 skill 与系统提示词评审规则是决定输出质量最关键的一环没有之一。你给 agent 的规则越具体输出就越能对齐团队要求。简单来说规则分三类硬性规范比如“禁止直接拼接 SQL必须使用参数化查询”“日志中不得输出敏感字段”。这类规则通常来自团队 code style 和安全规范。软性建议比如“优先使用现有工具类而不是重复造轮子”“公共函数必须有注释说明参数含义”。这类规则体现团队的技术取向。负面清单明确告诉 agent 不要输出哪些内容。比如“不需要评论缩进和空格等格式细节”“不要重复 diff 中肉眼可见的简单问题”。很多 agent CLI 支持把这类规则做成 skill 或者自定义指令文件放在项目根目录下每次评审自动加载。这个功能非常值得花时间打磨。说白了普通 prompt 是“告诉 AI 做什么”而 skill 是“告诉 AI 在什么时候、按照什么标准、如何做”。我自己的习惯是规则宁可写得啰嗦一点也不要写得模糊。一份 50 条规则、每条都带正反例的评审规范产出意见的可用率比我早期那份 5 条笼统规则高出至少一倍。4. Headless 模式下的安全边界与审计设计聊到这一节已经不是“能不能跑”的问题而是“跑起来会不会出事”的问题。很多人把 headless agent CLI 当作普通脚本看待这是个严重的认知偏差。普通脚本只会执行你写好的逻辑而 agent 会“自主决策”——它调用的工具、读取的文件、生成的命令都有一定的不可预测性。安全问题一定不能等到出事了再补。4.1 权限最小化与只读沙箱我在跑独立评审的时候第一原则就是让 agent 处于只读状态。评审不需要修改任何文件所以凡是它可能写入的目录一律设置为只读。我不推荐直接给 agent 打开全部文件系统权限哪怕它“看起来只是在读代码”。具体操作上我会用容器或者专用工作目录把它圈起来。比如在 Docker 容器里运行 codex cli挂载仓库目录时加:ro参数同时不开放网络出口或者只允许访问少数白名单域名。这样即使 agent 被诱导执行了一些奇怪操作破坏范围也被限制在沙箱内。这里补充一个血泪教训仓库内容本身可能是不可信的。有的项目里有 README其中可能写着“请帮我执行以下命令”之类的诱导性内容。一旦 agent 读取了这些内容又具备执行权限理论上可能执行恶意指令。这在业内叫 prompt injection并不是危言耸听。独立评审场景相对安全因为你通常不会给它写权限但仍然建议关闭终端执行能力或者至少限制可执行命令的白名单不要把所有 CLI 工具都交给它。4.2 结果防篡改与留痕审计评审报告如果只是生成一段文字很容易被误改或流失。我在对接 CI 流程时做了一套简单的审计设计核心是两个点哈希存证和日志留痕。哈希存证很简单评审报告生成后计算它的 SHA-256 摘要并记录到评审系统里。之后任何人都没法在不被发现的情况下改动报告。日志留痕则要把 agent 的执行过程都记录下来包括它看了哪些文件、执行了哪些命令、每次工具调用的输入输出。很多 agent CLI 自带详细日志模式建议在 headless 模式下强制开启。不要小看这些设计。当评审报告被用于发布决策时一旦出了问题你必须有办法追溯是 agent 判断有误还是数据在传输中被改动。此外完整的审计日志也是后续调优 prompt 的最宝贵素材——我每次评审效果不理想都是先翻日志找线索而不是凭感觉改 prompt。4.3 多 agent 与评审会模式的前景单独一个 agent 做评审多少有点“既当运动员又当裁判”的意味。不过我们已经在尝试把独立评审升级为“多 agent 评审会”模式一个 agent 负责代码走查一个 agent 负责测试覆盖度评估还有一个 agent 专门找安全漏洞。它们各自独立运行输出独立报告最后由人汇总。这个模式目前还比较重成本和延迟都会上升。但如果你负责的系统关键性很高比如金融交易或底层基础设施多 agent 交叉评审带来的收益值得多花这些成本。它本质上和人工评审要求“至少两人确认”是一个道理——独立判断带来的多样性比单个 agent 的长篇输出更有价值。5. 常见问题与排查技巧实录最后这部分都是干货是从多次实际运行里踩坑踩出来的经验不是什么“最佳实践”的纸上谈兵。5.1 高频问题速查表我把自己遇到的典型问题整理了一下方便你对照排查现象常见原因排查思路评审意见全是套话没有具体行号上下文里只有 diff缺关联文件补充仓库地图和相关源码片段同一 PR 两次评审结果不一致temperature 过高导致随机性调低或归零校验复现结果agent 一直在读同一个文件迟迟不结束上下文不完整它在反复找信息优化上下文组装增加 max_turns意见集中在格式细节忽略逻辑风险规则里负面清单缺失把“不要评论缩进/命名”加进规则报告引用不存在的行号模型“眼花”把近似行号当成了真实目标用脚本校验行号有效性再做二次过滤评审很慢一次 PR 要跑十几分钟任务拆得太粗一次喂太多文件分层评审、拆分任务控制单次输入量5.2 实例复盘评审漏掉严重问题的三种典型原因有一段时间我的评审 Agent 对“空指针潜在风险”这类问题几乎零命中后来复盘日志才发现了三类原因这里直接分享给你。第一上下文截断。PR diff 很长我在组装输入时手动截断了部分文件内容agent 看到的代码不完整自然发现不了问题。后来我改为“优先保留被调用的函数体截断日志打印和格式代码”问题明显改善。第二规则覆盖不全。我最初没告诉它项目里“从 Map 里 get 之后必须判空”这一约定它把这段代码当成常规写法就放过了。加了规则之后这类问题立竿见影被捡出来。第三注意力被稀释。一次性让它评审 20 个文件真问题被大量小问题淹没了。拆成按模块评审后命中率提升非常明显。这些原因说起来都平淡无奇但如果不做日志复盘你可能永远不知道问题出在哪个环节。5.3 提速降本的实测技巧最后分享几个我自己实测有效的提速降本技巧分层评审。先让便宜模型做第一遍粗筛只把可能有问题的片段丢给强推理模型细看。我实测过成本可以降到全量强模型方案的三分之一而漏报率没有明显上升。增量复用。如果仓库里有历史评审记录把过往的问题模式和修复方案缓存起来作为参考注入新一轮评审。这样 agent 不会发现相同问题重新报一遍评审速度和新问题发现率都有提升。限制输出长度。明确告诉它“每个问题最多三句话描述、一条建议”很多 agent 在自由输出时会写很长的解释文字浪费 token 不说读者也没耐心看。做出限制之后报告更精炼实际评审效率和阅读效率都高了不少。结尾最后想说的话个人在实际操作中最深的一点体会是跑去 headless 模式其实不是为了省掉交互而是为了倒逼你把任务定义清楚。一个任务如果你能用参数、规则、上下文把它描述到“一个 agent 在无人干预下能独立完成”的程度那它的边界、产出和验收标准大概率已经被你吃透了。这本身就是一种工程能力。如果你也在尝试用 agent CLI 做自动化我建议从一次只读的独立评审开始把这条链路跑稳了再考虑要不要让它承担更多“动手”的任务。另外一个小技巧每次跑完评审顺手把报告里那些“准确命中了真问题”的条目收集起来它们就是你调试规则和参数最宝贵的样本集。无头模式不会替你思考但它能放大你思考的成果——关键在于你愿不愿意先把规则打磨到位。