Agent 能接进 IDE,为什么还不能随意互换?
假设你正在给团队的开发工作台加一个审查入口:开发者选中一批改动,点“审查”,结果统一显示在侧栏。第一版接 Codex,第二版想再接一个审查 Agent。界面没有变化,看上去只要换掉调用目标。
但同一个 codex-plugin-cc 插件里,两种都叫“审查”的功能,就已经不是同一种请求和返回值:普通审查调用 Codex 内置 reviewer;反方审查自行收集上下文、构造提示词,再要求一份结构化结果。
这个差异比“未来 IDE 会有多少 Agent”更值得先弄清。一个 Agent 能被工作台调用,只证明入口接通;要让它能被另一执行者替换,还需要保持输入含义、运行状态和结果解释一致。下面沿这两条现成路径看一次替换需要改什么。工作台接入场景是设计例子,源码分析没有执行真实跨 Agent 替换。
一个审查入口,已经有两种任务定义
截至 2026-09-22,本次核对的官方插件 main 指向提交 db52e28。在这个固定版本的 executeReviewRun 中,普通 Review 分支先转换并校验审查目标,再调用 runAppServerReview;其余这里讨论的反方审查分支则调用 collectReviewContext,把上下文和关注点交给提示词构造函数。1
区别最容易从自定义关注点看出来。validateNativeReviewRequest 遇到非空 focusText 就报错,提示改用 /codex:adversarial-review。这不是让模型试着理解后再拒绝,而是在进入普通审查前就明确限制输入。
因此,“审一下这批改动”和“专门挑战这批改动的重试设计”不能在客户端里无条件当成同一种请求。前者有内置审查目标的表示方式,后者需要把自定义问题组织进输入上下文。即使执行者都叫 Codex,这个差异也没有被模型名称消除。
对工作台来说,用户选择了一个 Agent 之后,仍要回答一个更具体的问题:它接受哪一种任务?如果新执行者没有相同的目标选择能力,适配层——把工作台请求转换成执行者请求的那段代码——就得补齐等价输入,或者明确显示“不支持”。静默丢掉关注点,会让界面看起来成功,实际审查的却是另一个问题。
协议负责把任务送进去,调用方仍要选对方法
沿着普通审查往下走,runAppServerReview 先创建线程,再发送 review/start,请求中带着线程、交付方式和审查目标。反方审查则经 runAppServerTurn 发送 turn/start,其中包含文本输入和 outputSchema。2
把这两个调用并排,差异很直观:
| 插件路径 | 发送给 App Server 的任务 | 插件准备的输入 | 返回后主要处理什么 |
|---|---|---|---|
| 普通审查 | review/start | 转换后的原生审查目标 | reviewText,交给原生审查渲染函数 |
| 反方审查 | turn/start | 自行收集的上下文、提示词、输出 schema | 最终消息,解析后交给结构化审查渲染函数 |
这是固定源码的调用关系,不能把表里的第二行当成所有 Agent 都支持的统一标准。
当前官方 App Server 文档也分别列出了这两个方法,并区分 Thread、Turn 与 Item:线程承载会话,轮次承载一次请求及随后的工作,条目承载过程中产生的内容。客户端要处理开始、增量与完成等事件。3
协议提供的是可管理的调用方式,不会替工作台定义“这个审查按钮究竟承诺检查什么”。同样是 JSON 消息,也不会自动具有相同的目标选择、事件顺序或返回含义。换执行者时,需要重新检查的是这段翻译关系;如果现有执行者完全满足需求,就没有必要为了“多 Agent”先造一个通用调度平台。
相同的成功状态,装不下两种结果
插件对普通审查保留 reviewText,renderNativeReviewResult 将其作为文本展示。这个分支没有把审查文本统一转换成反方审查使用的 verdict、findings 等字段。这里描述的是该插件的消费方式,不是声称 Codex 内置审查器不存在任何内部结构。14
反方审查的输出约定则写在 review-output.schema.json 中:顶层需要 verdict、summary、findings、next_steps;其中 verdict 的允许值是 approve 和 needs-attention。5
返回后还有连续的处理步骤。parseStructuredOutput 先尝试 JSON 解析;renderReviewResult 再检查顶层形状,缺少必要的字符串或数组时展示结构错误和原始内容,而不是直接按正常审查结果排版。这个形状检查有自己的有限范围,不能等同于运行时完整执行了整份 JSON Schema,更不能证明发现的问题真实存在。24
另一个容易被界面抹平的差异是执行状态。buildResultStatus 把最终 Turn 的 completed 映射为 0,其他情况映射为 1。它回答的是本轮执行是否完成,不是在读取 verdict 后判断代码能否合并。2
假如一个接入方只看退出状态为 0,就给侧栏画绿色勾选,它会把“执行完成”误当成“审查认可”。反过来,只要没有可解析 findings 就填空数组,也会混淆“没有得到结构化结果”和“审查后没有发现问题”。这些是从源码差异推导的接入风险,不是本次观测到的线上故障。
把第二个审查 Agent 接进一次真实形状的任务
把“换一个执行者”展开到足够具体,才能看出适配工作在哪里发生。下面仍是构造案例,用来推演接入设计,没有调用第二个模型,也没有获得可比较的运行结果。
设想团队正在修改订单服务:同一笔支付通知可能重复到达,实现者为数据库写入增加了幂等判断。开发者在工作台选择这次提交,要求审查重复通知是否仍可能产生第二条订单。第一版工作台调用 Codex,准备再接一个只接收文本上下文、返回自然语言报告的执行者 B。
这里刻意不假定 B 兼容 Codex 的接口。它的能力只是案例条件,不对应某个真实产品。接入目标也很窄:让开发者在同一侧栏阅读两种执行者的审查结果,不自动修改文件或批准合并。
第一处要适配的是输入。工作台不能把“当前改动”四个字原样转给 B 就算完成交接。用户选择的是哪次提交、比较基线是什么、相关文件内容来自哪个版本,都要随任务留下记录。对于能读取工作区的执行者,可以传入它支持的审查目标,并记录实际解析到的版本;对于只能接收文本的 B,就需要提供对应差异和必要上下文。
这不是要求把整个仓库塞进提示词。假设风险取决于数据库唯一约束,只给订单函数的几行 diff,B 可能根本看不到决定结论的条件。适配器要么补充相关表结构和调用入口,要么在报告上保留“未提供数据库约束”的缺口。前者增加输入和准备成本,后者限制结果可用范围;两者都比悄悄把缺失上下文当成已检查更诚实。
同时,自定义关注点必须被保留。案例问的是重复通知,而源码中的普通 /codex:review 路径不接受自定义 focusText。如果工作台承诺一定审查这个问题,就不能只因为普通命令容易调用而丢掉它;需要选择能承载关注点的路径,或者告知用户该入口只提供一般审查。这个约束来自固定插件实现,不能泛化为 App Server 本身禁止自定义目标。
第二处是运行中的归属。工作台创建的审查任务可以有自己的任务编号,再关联 Codex 或 B 返回的执行标识。用户稍后切到另一批代码时,迟到的报告仍应回到原来的任务,而不是覆盖当前侧栏。若任务只有同步文本返回,也可以先支持这一种简单模式;没有必要为了统一外观虚构进度百分比或取消能力。
假设用户等待期间又改了一次订单函数。B 最终返回“幂等判断之后仍有一次写入窗口”。工作台首先要显示这条结论对应的是送审时的旧版本。接下来是让开发者核对该问题是否还存在,或者对新版本重审,而不是偷偷把旧结果改挂到最新代码行。任务身份在这里服务的是结果归属,并不要求恢复两个产品内部相同的会话历史。
第三处才是结果转换。B 的原始报告没有文件位置,工作台就保留原文并标注“尚未定位”;不能从“订单函数”猜出一个文件路径,再制造一条看似精确的行内评论。如果后续让另一个模型提取文件和行号,提取结果仍需对照送审版本检查,且应保留它来自转换步骤这一事实。否则接入层会把不确定性洗成结构化字段,下游反而更难发现问题。
最后,开发者核对后发现数据库确有唯一约束,但重复通知仍会触发一次多余的外部调用。这时,可以记录哪些原始意见被采纳、哪些被证据排除,以及实际需要修复什么。不能因为报告中的一处推断有误,就把整次执行标成失败;也不能因为执行完成,就默认接受它的每条判断。
沿这条过程走完,第二个 Agent 已经可以成为工作台里的一个可用执行者,但还没有变成 Codex 的无差别替身。它可能缺少工作区读取、结构化输出、进度事件或取消能力。工作台需要让这些差异可见,再决定当前任务是否还能等价地交给它。
用一份映射记录验收接入
下面这份映射记录可以直接用于讨论接入方案。它是作者建议的工作台设计,不是官方插件已有字段,也不是完成过的兼容性验收:
| 工作台要保留的含义 | 从插件现有路径看到的约束 | 替换时要作出的决定 |
|---|---|---|
| 审查对象与自定义关注点 | 普通路径校验原生目标且拒绝自定义关注点;反方路径自行组织上下文 | 记录新执行者实际收到的对象;不支持的关注点明确拒绝或交回调用方 |
| 本轮执行结果 | Turn 完成状态被转换成执行状态 | 把执行失败、中断与审查意见分开显示;保留执行者自己的任务标识 |
| 可供后续使用的审查内容 | 一条路径消费文本,另一条解析并检查结构 | 保留原始输出;只有可验证的字段才进入统一显示或后续动作 |
| 能否推动下一步 | 执行状态与结构化 verdict 来自不同处理位置 | 单独定义采纳条件;“需关注”进入核对,结构缺失不自动变成“无发现” |
这张记录要围绕一个真实任务填写,而不是先为所有 Agent 发明通用字段。第一步可以只支持“人工读报告”这一种用途;后续确实需要自动定位或修复分派时,再补相应适配。接入层的价值,是让调用方清楚哪些含义已被保留、哪些仍需要判断。
哪些职责留在工作台,哪些交给执行者
这个例子也解释了工作台为什么不能只是模型选择器。具体推理过程可以由执行者承担,但用户选了什么任务、结果归到哪里、什么条件下可以推动下一步,需要有稳定的管理位置。以下是基于案例的设计建议,不是对官方插件已有能力的完整描述。
工作台首先保存的是用户意图和任务身份。订单审查的输入版本、关注点、允许的操作、结果用途,不能只存在于某个 Agent 的长对话里。换一个执行者后,这些信息仍然需要成立。执行者内部如何命名会话、如何拆解工作可以不同,工作台只保留完成追踪所需的映射,不必接管所有内部状态。
适配器则处理产品差异:怎样把审查目标转换成请求,怎样接收事件,怎样保存原始输出,怎样解释错误。它不应为了迎合统一界面而宣称执行者具备不存在的能力。例如,B 没有可靠的中断接口,适配器就不能把“用户不再等待”显示成“远端已停止”。最低限度应区分界面等待结束与执行是否确认终止;涉及重试时,也不能假定前一次工作没有继续发生。
执行者负责在给定条件下完成分析,但它生成的自述不应成为工作台唯一的事实来源。它说“检查了数据库约束”,调用方仍应能追溯送入了什么材料,或取得了哪些可核对的工具证据。本文没有实现这样的追踪机制;这里提出的是接入验收需要验证的能力,而不是承诺所有产品都能返回同样完整的轨迹。
团队规则决定结果怎样被消费。人工阅读一份报告,和根据报告自动建立修复任务,是不同强度的承诺;进一步让它影响合并,又需要仓库检查、证据核对和明确的责任人。执行者输出 approve 可以是一条审查意见,但工作台是否允许下一步,仍取决于它原来向团队承诺了什么。不能让一个供应方的返回字段悄悄改写团队规则。
这类分工有一个实际收益:以后更新模型或换供应方时,变化主要集中在任务能力和适配器,已有任务记录及采纳规则不必跟着重建。但隔离程度也有成本。一次性的个人审查脚本,保留原始输出、输入版本和人工判断可能就够了;只有多个入口或执行者反复使用同一流程,才值得把这些职责逐步抽成稳定模块。
“可组合”因此不等于每个组件都必须独立成服务。它首先是一种可解释的责任划分:哪些信息由谁保存,哪里发生转换,转换失败由谁处理。代码可以先放在一个进程里;是否需要队列、数据库或独立调度服务,应由并发、持久化和故障恢复需求决定。
什么时候值得增加第二个执行者
接入第二个 Agent 的理由,不应该只是它在另一份排行榜上分数更高。对订单审查这个具体任务,更有用的问题是:它能否发现原流程遗漏且值得处理的问题,或者在满足现有要求的前提下降低总成本?这两种收益需要分别观测,不能用一份听起来更强硬的报告替代证据。
可以先拿一组团队已经理解的历史改动做离线比较:其中既有已确认的问题,也有容易被误报的正常代码。两种执行者使用对应版本和尽量一致的任务范围,记录哪些发现被人工确认、哪些缺少依据、哪些只是重复了已有发现。历史样本不完整,也可能与未来任务分布不同,因此结果只能帮助决定是否继续试用,不能证明上线后一定更好。
比较时还要把接入层算进去。如果为了给 B 补齐上下文,需要开发者手工导出文件、解释代码位置、重新整理报告,那么单次模型调用便宜并不代表整条流程便宜。这里可以采用一个简单的记账口径:总投入包括调用费用、输入准备时间、结果核对时间,以及失败后的恢复工作。它是评估口径,不是本文测得的数据,也不必把所有项目强行折算成同一货币单位。
并行运行会带来另一种取舍。两份报告同时返回,可能缩短等待某个补充判断的时间,也可能把更多冲突意见交给同一个人处理。若两者都围绕同样的提示和材料提出同一类猜测,执行者数量增加并不自动提供独立证据。真正有价值的差异,可能来自明确不同的审查任务、补充材料或已验证的能力,而不是给两个窗口起不同角色名。
因此,初次接入可以先采用按需调用:普通变更沿原流程走,遇到具体争议或现有执行者不擅长的任务,再请求第二份意见。团队能明确说出补充调用解决了什么问题之后,再考虑哪些场景值得默认触发。这比一开始给每个改动都配置多角色流水线,更容易看清收益与负担。
如果当前问题主要是输入不全、送审版本错了、报告没人核对,那么先修这些环节通常更直接。第二个执行者收到同一份错误输入,也不能替工作台补回任务事实。相反,当输入和验收已经稳定,仍反复出现某类能力缺口,并且试用记录显示另一执行者能提供可采纳的补充,接入才有了可讨论的依据。
上线范围也可以小于技术能力范围。即使适配器已经能返回结构化发现,也可以先只供人工阅读,不立即接到修复或合并动作。这样得到的运行记录会回答后续真正的问题:哪些字段可信、哪些错误经常发生、维护者能否解释一次异常。当这些问题尚未解决时,增加自动化程度只会扩大接入层判断失误的影响。
可组合的工作台,保留差异才有替换空间
这两条审查路径没有证明未来 IDE 必然成为某种 Agent Router,也没有证明多 Agent 一定比单 Agent 更快、更准。它们只给出一个扎实的观察:即使同属一个插件、使用同一个执行产品,不同任务仍有不同的输入能力与结果表示。
由此能作出的设计推论是:工作台若要接入更多执行者,应把任务含义和结果消费方式放在明确的位置,让每个适配器声明自己能满足什么。开发者才能判断一次切换是等价替换,还是把任务改成了另一种工作。
实际落地时,可以先拿一个现有审查任务,把上面的映射记录填完,再接第二个执行者。如果连它审的是哪批改动、返回的是原始报告还是可用结论都说不清,增加一个下拉选项不会带来真正的可替换性。
Footnotes
-
OpenAI,
codex-companion.mjs,固定提交db52e28f4d9ded852ab3942cea316258ae4ef346,validateNativeReviewRequest与executeReviewRun,github.com/openai/code… ↩ ↩2 -
OpenAI,
lib/codex.mjs,同一固定提交,runAppServerReview、runAppServerTurn、buildResultStatus、parseStructuredOutput,github.com/openai/code… ↩ ↩2 ↩3 -
OpenAI,Codex App Server,2026-09-22访问,learn.chatgpt.com/docs/app-se… ↩
-
OpenAI,
lib/render.mjs,同一固定提交,renderNativeReviewResult、renderReviewResult与形状检查,github.com/openai/code… ↩ ↩2 -
OpenAI,反方审查输出 schema,同一固定提交,github.com/openai/code… ↩