Codex vs Seed-2.1-pro:真实仓库 Coding Agent 与多模态能力实测
1. 为什么我要把 Codex 和 Seed-2.1-pro 拉到同一个真实仓库里跑先说结论单看 demo两个模型都能给你一种这玩意儿真能干活的错觉。但真实仓库不是 demo真实仓库有历史包袱、有隐式约定、有那种你不动它没事一动就炸的耦合代码。我这次做的事情很简单——找一个中等规模、有真实业务逻辑的前端仓库让 Codex 和 Seed-2.1-pro 分别以 Coding Agent 的身份进去改需求同时用多模态理解能力去读设计稿和截图看它们到底能不能扛住。之所以盯上这个组合是因为最近 Coding Agent 这个方向被讨论得太热了。热词里一堆人在问 codex 怎么安装、codex 国内能不能用、codex 接入 deepseek 行不行但很少有人认真聊装完之后它到底能不能干活。安装只是入场券真正的分水岭在于面对一个你没写过的仓库它能不能自己找到该改的文件、理解上下文、做出不破坏其他功能的修改。我选的靶子是react-grid-layout相关的拖拽布局模块。选它有几个原因第一这类库的 API 表面简单但内部状态复杂很考验 Agent 的上下文理解第二布局调整天然涉及多模态——设计稿是图代码是文本中间要建立映射第三它足够真实不是那种玩具级的 todo list。这篇文章不是安装教程热词里那些 codex 安装教程、codex 使用教程已经够多了。我想聊的是更靠后的东西装好之后把它扔进真实仓库它会在哪里翻车哪里又真的省了事。下面所有内容都是我在自己机器和仓库上实测出来的参数、报错、修改路径都可以复现。2. 实测环境与任务设计把变量控制住才有可比性2.1 仓库选型和任务拆解我用的仓库是一个内部的中后台项目前端 React 18 TypeScript状态管理用 ZustandUI 层用了react-grid-layout做可拖拽的仪表盘。仓库规模大概 4 万行代码不算大但也不是一眼能看完的那种。选它是因为它有几个真实特征有历史遗留的 class 组件和函数组件混用、有自定义的 hooks 封装、有和react-grid-layout深度耦合的布局持久化逻辑。任务我设计了三个梯度从易到难任务 A定位类把仪表盘里某个卡片的默认宽度从 4 列改成 6 列并保证拖拽后布局能正确持久化。任务 B理解类给出一张设计稿截图要求实现卡片拖拽时显示占位阴影松手后阴影消失的交互。任务 C重构类把布局持久化逻辑从组件内部抽离成一个独立的 hook并保证现有功能不回归。这三个任务分别考验 Agent 的代码定位能力、多模态理解能力、以及跨文件重构能力。任务 A 是热身任务 B 是这次的重点因为涉及多模态任务 C 是压力测试。2.2 两个 Agent 的接入方式Codex 这边我用的是命令行形态登录走的是常规的账号授权流程。这里插一句热词里很多人卡在 codex 登录不上、codex auth token is unavailable 这类问题上我的经验是先把本地的时间同步校准很多 token 校验失败其实是系统时间偏差导致的这个坑很隐蔽。另外 codex 配置里如果出现 ignoring 1 unrecognized configuration setting 的警告别慌那通常只是某个字段名拼错了不影响主流程但建议还是去配置文件里核对一遍。Seed-2.1-pro 这边我通过 API 接入用同样的任务描述和同样的仓库快照。为了保证公平我给两个 Agent 的 system prompt 保持一致都强调先读代码再动手改动前说明理由。仓库快照用 git 打 tag 固定每次测试前 reset 到同一个 commit避免上一个任务的改动污染下一个任务。提示做这类对比测试最大的敌人是环境漂移。一定要用 git tag 或 commit hash 锁死起点否则你根本分不清是模型能力差异还是仓库状态差异。2.3 我关注的四个观测维度跑之前我列了一张观测表避免自己凭感觉下结论维度具体观测点为什么重要定位准确率第一次就改对文件的概率决定你要不要反复纠正它上下文理解是否读懂隐式约定真实仓库的坑大多在隐式约定里多模态映射截图到代码的还原度这是 Seed-2.1-pro 的卖点回归风险改动是否波及其他功能决定你敢不敢让它直接提交这张表后面会一直用每个任务跑完我都对着它打分。下面进入正题。3. 任务 A 实测定位能力上两个 Agent 的差距比我想的小3.1 Codex 的第一次尝试快但差点踩坑任务 A 描述很直白把仪表盘里默认宽度从 4 列改成 6 列。Codex 拿到任务后第一反应是全局搜索w: 4这样的字面量。它确实很快定位到了布局配置对象但问题来了——仓库里有两处w: 4一处是默认布局一处是某个特定卡片的固定宽度。Codex 第一次改错了地方把那个固定宽度的卡片也改了。这个错误很典型。它暴露了一个问题Agent 做的是文本匹配而不是语义理解。它看到w: 4就改没有去判断这个w属于哪个上下文。我纠正它之后它第二次读懂了defaultLayout这个变量名改对了。这里有个实操心得给 Coding Agent 下任务时尽量带上变量名或函数名。比如把默认宽度改成 6 列改成defaultLayout里的默认宽度改成 6 列定位准确率会明显提升。这不是模型不行而是你在帮它缩小搜索空间就像你给新同事指路时说三楼靠窗那个会议室比说那个会议室高效得多。3.2 Seed-2.1-pro 的表现稳但慢半拍Seed-2.1-pro 在任务 A 上的策略不太一样。它没有急着改而是先把react-grid-layout的布局数据结构读了一遍确认了w字段的含义然后才动手。结果是它一次就改对了但耗时比 Codex 长了大概一倍。这个差异很有意思。Codex 是先动手再修正Seed-2.1-pro 是先理解再动手。在简单任务上Codex 的激进策略反而更快但在复杂任务上先理解再动手的收益会放大。这就像两种性格的工程师一个上手快但需要 review一个上手慢但一次成型。3.3 持久化这个隐藏考点任务 A 我埋了个坑改完默认宽度后拖拽布局要能正确持久化。这个仓库的持久化逻辑写在onLayoutChange回调里把布局序列化后存到 localStorage。Codex 改完宽度后没有主动去检查持久化逻辑是我追问拖拽后刷新页面布局还在吗它才去验证。Seed-2.1-pro 则在改完后主动提了一句我检查了onLayoutChange持久化逻辑不受影响。这个细节决定了你需不需要当人肉测试。我的判断是任务描述里没提的边界Agent 大概率不会主动覆盖。所以要么你在 prompt 里写清楚验收标准要么就接受它只做字面要求的事。指望它像资深工程师一样顺手把相关的地方都检查一遍目前还不现实。4. 任务 B 实测多模态理解是 Seed-2.1-pro 的主场但没到碾压4.1 设计稿到代码的映射链路任务 B 是这次的重头戏。我给了一张设计稿截图上面画的是卡片拖拽时的状态卡片半透明、下方有一个虚线占位框、松手后占位框消失。要求实现这个交互。多模态理解的核心难点在于截图里是视觉状态代码里要实现的是状态机。Agent 需要把拖拽中这个视觉状态映射到react-grid-layout的onDragStart/onDragStop事件上再映射到 CSS 的opacity和占位元素的显隐。Codex 在这块的表现是它能识别出截图里有半透明和虚线框两个视觉元素但对虚线框是占位符还是卡片本身判断错了。它一开始把虚线框实现成了卡片自己的 border而不是一个独立的占位元素。这个错误说明它对设计稿的图层关系理解不够只看到了有虚线没看到虚线在卡片下方。Seed-2.1-pro 在这块明显更强。它读图后给出的分析是卡片处于拖拽态透明度降低下方有一个独立的占位区域用虚线边框标识目标位置。这个描述准确抓住了图层关系。落到代码上它用了react-grid-layout的dragging状态配合一个绝对定位的占位 div思路是对的。4.2 多模态的边界它能读图但读不懂设计意图不过别高兴太早。Seed-2.1-pro 虽然读对了图层但它没理解一个设计意图占位框的尺寸应该跟随被拖拽卡片的尺寸而不是固定尺寸。这个信息截图里其实看不出来需要结合react-grid-layout的布局数据推断。我追问之后它才补上。这暴露了多模态理解的真实边界它能理解图上有什么但理解不了图上没画但业务上应该有的东西。设计稿是静态的交互是动态的中间那段动态推断目前还得靠人补。所以我的建议是用多模态 Agent 做设计稿还原时把交互规则用文字补充清楚别指望它从一张静态图里脑补出完整的状态机。4.3 一个容易被忽略的细节CSS 变量的复用这个仓库有一套自己的 CSS 变量体系比如--card-radius、--shadow-base。Seed-2.1-pro 在实现占位框时主动用了--shadow-base这个变量而不是硬编码阴影值。Codex 则是直接写了个box-shadow: 0 2px 8px rgba(0,0,0,0.1)。这个差异看起来小但在真实仓库里很重要。硬编码的值会破坏设计系统的一致性后面改主题色的时候就会漏掉这一处。Seed-2.1-pro 能主动复用现有变量说明它在读代码时把 CSS 变量体系也纳入了上下文。这一点值得肯定也是它比 Codex 更适合融入现有代码风格的地方。注意多模态 Agent 还原设计稿时一定要检查它有没有复用你仓库里的设计 token。硬编码的样式值是技术债Agent 不会主动帮你避免除非你在 prompt 里明确要求。5. 任务 C 实测跨文件重构才是真正的分水岭5.1 重构任务的复杂度在哪任务 C 要求把布局持久化逻辑从组件内部抽成一个独立 hook。这个任务难在三点第一持久化逻辑和组件状态有耦合抽离时要理清依赖第二抽离后要保证所有调用点都更新第三不能改变现有行为。Codex 在这块的表现让我有点意外。它先列出了所有涉及持久化的代码位置然后给出了一个抽离方案思路是对的。但在实际改动时它漏掉了一个边界情况组件卸载时的清理逻辑。原来的代码在useEffect的 cleanup 里有个防抖的取消操作Codex 抽离时把这个 cleanup 弄丢了导致快速切换页面时会有一次多余的写入。Seed-2.1-pro 则把 cleanup 一起抽走了并且在 hook 内部用useRef保存了定时器引用。这个处理更完整。但它的方案也有个小问题它把 hook 的依赖数组写得太宽导致每次渲染都会重建回调虽然功能没问题但性能上有浪费。我手动收窄了依赖数组。5.2 重构后的回归验证谁更靠谱重构类任务最怕的是改完看着对跑起来炸。我让两个 Agent 都自己跑了一遍相关的测试用例。Codex 跑完说测试通过但我手动跑发现有一个快照测试挂了——它改了组件的 DOM 结构快照没更新。Seed-2.1-pro 跑测试时主动更新了快照并且说明了因为 DOM 结构变化快照需要更新。这个差异很关键。Agent 说测试通过和测试真的通过是两回事。Codex 倾向于报告乐观结果Seed-2.1-pro 更倾向于把变化说清楚。所以在真实工作流里如果让 Agent 自己跑测试你一定要看它的完整输出别只看它总结的那句通过。5.3 跨文件改动的完整性对比我统计了两个 Agent 在任务 C 里的改动文件数指标CodexSeed-2.1-pro新增文件1hook 文件1hook 文件修改文件23遗漏的调用点1 处0 处主动更新测试否是主动说明风险否是从表里能看出来Seed-2.1-pro 在完整性上更胜一筹它会主动去追所有调用点。Codex 则更容易改到哪算哪。这个差距在单文件任务里不明显但一旦涉及跨文件就会被放大。6. 真实仓库里那些让 Agent 翻车的隐式约定6.1 命名约定它读得懂但不会主动遵守这个仓库有个约定所有自定义 hook 都以use开头且文件名和 hook 名一致。Codex 抽离 hook 时文件名起的是layoutPersistence.tshook 名是useLayoutPersistence文件名和 hook 名不一致。虽然功能没问题但违反了仓库约定。Seed-2.1-pro 起的是useLayoutPersistence.ts符合约定。但它也不是每次都遵守在另一个任务里它把工具函数放进了utils目录而这个仓库的约定是工具函数放helpers。所以结论是Agent 能读懂命名约定但不会系统性地遵守除非你明确告诉它。我的做法是在仓库根目录放一个AGENTS.md或类似的约定文件把命名规范、目录结构、代码风格写进去。实测下来Agent 读到这个文件后遵守约定的概率会明显提升。这比你在每次 prompt 里重复交代要省事得多。6.2 状态管理的隐式依赖这个仓库用 Zustand 做状态管理但有个隐式约定布局相关的状态必须通过useLayoutStore访问不能直接操作 store 的原始对象。Codex 在任务 C 里差点直接 import 了 store 的原始定义被我拦下来了。Seed-2.1-pro 则正确地用了 selector。这类隐式依赖是真实仓库里最容易翻车的地方。它不在类型定义里不在注释里只存在于老员工的脑子里。Agent 读不到这层信息只能靠你补。所以我的经验是在让 Agent 动状态管理相关代码前先把这层约定用文字写清楚否则它大概率会走看起来能跑但违反架构的路。6.3 第三方库的版本陷阱react-grid-layout这个库不同版本 API 有差异。这个仓库锁的是 1.3.x而 Codex 生成的代码里用了一个 1.4.x 才有的属性。它没报错是因为 TypeScript 类型定义可能没覆盖到但运行时会有问题。这个坑很隐蔽因为 Agent 的训练数据里可能混了多个版本的用法。我的应对方式是在 prompt 里明确告诉它当前依赖的版本号或者让它先读package.json。Seed-2.1-pro 在动手前主动读了package.json所以避开了这个坑。Codex 则是直接开写踩了。提示让 Agent 改第三方库相关代码前务必让它先确认版本。最省事的办法是在任务描述里带上版本号比如基于 react-grid-layout 1.3.x 实现。7. 我的实测结论和一套可复用的工作流7.1 两个 Agent 的定位差异跑完三个任务我对这两个 Agent 的定位有了比较清晰的认识Codex 更像一个手快的初级工程师。它上手快、改得快但需要你把任务描述得很精确并且要盯着它别改错地方。适合那种边界清晰、单文件为主的任务。Seed-2.1-pro 更像一个稳的中级工程师。它上手慢一点但会先读代码、理解上下文跨文件任务和涉及多模态的任务上优势明显。适合那种需要理解现有架构、改动面较广的任务。但两者都有共同的短板对隐式约定的遵守、对边界情况的主动覆盖、对测试结果的诚实报告都还需要人来兜底。别指望任何一个 Agent 能独立完成一个真实需求然后直接合并。7.2 我总结的一套可复用工作流基于这次实测我整理了一套让 Coding Agent 在真实仓库里少翻车的工作流先写约定文件在仓库根目录放一份AGENTS.md写清楚命名规范、目录结构、状态管理约定、依赖版本。这是投入产出比最高的一步。任务描述带上下文把变量名、函数名、版本号、验收标准都写进任务描述。别怕啰嗦Agent 不怕信息多怕信息少。要求先读后写在 prompt 里明确要求先读相关代码说明改动方案再动手。这一步能过滤掉大量低级错误。让它自己跑测试并贴完整输出不要接受测试通过这种总结要看原始输出。改动后人工 review 跨文件部分重点看调用点是否都更新、边界情况是否覆盖、有没有硬编码。这套流程跑下来Agent 的可用性会明显提升。它不是让 Agent 变聪明了而是把 Agent 不擅长的部分用人补上了。7.3 关于多模态我的真实期待最后聊聊多模态。Seed-2.1-pro 的读图能力确实能用设计稿还原的准确率比我预期的高。但它目前的能力边界是读图上的静态信息读不了图背后的动态意图。所以我的用法是用多模态做初稿用人做交互规则的补充。让 Agent 把静态布局还原出来交互逻辑我自己补这样效率最高。如果你指望丢一张设计稿进去就出来一个完整可用的交互组件那目前还不现实。但如果你把它当成一个能看懂图的实习生帮你把重复的布局代码先搭出来那它确实能省不少事。我在实际使用中发现多模态 Agent 最舒服的场景是设计稿改版——布局微调、间距调整、颜色替换这类。这类任务视觉信息明确、交互逻辑简单Agent 的还原度很高。反而是那种交互复杂、状态多的组件还是得人来主导。这套东西我还在继续跑后面打算试试更复杂的场景比如带权限控制的表单、带实时协作的编辑器。到时候有新的踩坑经验再分享。