我以前很自然地把 ChatGPT 和 Codex 分成上下游。
有一个想法,先在 Chat 里聊。问题差不多想清楚以后,再让 Chat 整理成一份 Prompt,交给 Codex 读文件、改代码或者完成其他具体工作。Chat 负责方案,Codex 负责执行,这套分工一眼看上去很合理,我也这样用了很长一段时间。
后来,凡是和现有项目关系比较深的事情,我开始更多地直接在 Codex 里讨论,也在 Codex 里继续做。Chat 仍然会用,不过主要用来处理临时问题、搜索和学习,或者在我与 Codex 已经讨论很久以后,从外面重新看一遍当前方案。
我调整这套用法,和谁更聪明没有太大关系。用久以后,反复交接本身开始让我觉得麻烦。
每次从 Chat 转到 Codex,我都得重新解释项目。任务本身通常说得清,前面为什么会得出这个任务,却很容易在交接里少掉一部分。
一份很完整的 Prompt,仍然是一次压缩
Chat 里聊了十几轮,最后交给 Codex 的往往是一份已经整理好的任务:要做什么、改哪些文件、哪些地方不能动,做到什么程度可以停。任务本身很清楚,前面的讨论却不一定还在。
前面为什么选 A、为什么放弃 B,某条限制究竟来自技术、产品判断还是个人偏好,还有已经试过但后来否掉的方案,都很容易只剩下结果。Codex 只看最后的 Prompt,不一定知道有些地方为什么宁可麻烦一点,也不能顺手改掉。
这些内容很难全部搬过去。Prompt 写得再长,写进去的也主要是我当时认为值得保留的结论。讨论中那些迟疑、反例和被否掉的路线,还是会被压缩。
这有点像把我们来回讨论的过程改写成需求单。需求单可以写得很完整,接手的人也知道下一步做什么,但他没有参与前面的取舍,看到新的情况时就只能根据结果反推理由。任务简单时没有关系,项目越复杂,后面越可能在一个看似很小的地方重新走回已经否掉的路线。
以前碰到这种情况,我会继续补 Prompt,尽量把前面的讨论写进去。后来发现,Prompt 更完整只能少丢一点;只要方案和执行分在两个地方,交接时还是得由人决定哪些内容留下。
让执行者参加问题的形成
现在遇到和现有项目关系很深的事情,我会先让 Codex 读项目。
讨论开始以前,它可以先读当前代码、需求文档、项目规则和历史记录。遇到具体问题,再去看日志、构建结果和 diff。这样我不需要先凭记忆把项目描述一遍,也不用假设我说的现状就是项目真实的现状。有些我以为只是局部修改的问题,读完现有实现以后才会发现,它还会影响另一条流程;有些看起来需要重做的东西,项目里其实已经有了一半。
接下来我和 Codex 一起比较方案。它提出的做法如果和项目规则冲突,可以马上回到文件里核对;我不认同某个方向,也可以在它开始大改以前把理由说清楚。等决定形成以后,还是这条任务接着修改、验证和复查。
Codex 能做的不只是写代码。它从“为什么要做这件事”开始就在场,后面看到一个边界条件时,不需要只根据最终 Prompt 猜我当时为什么这样决定。
这套用法也不只在开发里有效。比如写这篇文章,Codex 同时读了原始讨论、个人写作 Skill 和以前的文章。改需求文档时,它可以把新方案放回已有产品规则里检查;研究资料、草稿、引用和后续修订,也可以一直放在项目里。只要这份工作还要围着项目里的文件反复转,我更愿意直接在 Codex 里开始。
这不等于把方案判断也交给 Codex。想解决什么问题、哪些条件不能破坏、结果做到哪里可以停,仍然要由我决定。变的只是:参加讨论的 Codex 后面还会继续读文件、修改和验证,不必重新接收一份缺少前情的任务。
Codex 进入得更早,Chat 站到了外面
Codex 成为我的主要工作环境以后,Chat 的位置反而比以前更清楚了。
一个突然想到的问题,还不知道值不值得做,我会先在 Chat 里聊。需要快速搜索公开信息、学习一个陌生概念、看一张截图,或者只是想把脑子里的半句话展开,Chat 都更轻便。这些事情还没有进入某个正在进行的项目,也不需要先读取一组本地文件。
这篇文章就是个例子。最初的话题是在 Chat 里出现的,我当时讨论的是怎样使用 ChatGPT Pro 里的不同能力。聊着聊着,问题才从工具分工变成了我自己的工作方式。到了要写文章时,我把前面的讨论整理成一份交接材料,带进文章项目,再让 Codex 读取写作规则和历史文章。
交接当然还会发生。这篇文章从 Chat 进入文章项目,写成一份可以保存的材料,我觉得很合理。但一个已经持续很久的项目,如果每做一步都要先去另一个地方讨论,再压成 Prompt 搬回来,前面丢过的东西就得再丢一遍。
很小、边界很清楚的一次性任务,也完全可以先在 Chat 里想好,再交给 Codex 执行。如果目标、输入和验收条件都已经确定,执行者并不需要知道太多历史。让我开始调整工作流的,主要是那些方案会随着实现继续变化、过程里还要反复判断的事情。
上下文并不是越多越好
Codex 提前进入以后,交接少了,我和它却可能在同一套方案里待得太久。前面已经投入了不少时间,某些决定又反复改过,我们会慢慢把一些前提当成已经成立。Codex 记得每次变化的理由,我也记得为什么否掉其他方案,这些内容对继续执行有帮助,也会让我们更少回头检查最早的方向。
这时我会把当前方案和必要事实交给 Chat,请它别沿着原来的思路继续设计,只从外面看哪里可能有问题。它没有参与前面两小时的讨论,不会因为一条路已经走了很远,就继续帮我们把它走顺。那些被我们当成前提的东西,到了这个新对话里,要重新解释一次。
当然,Chat 也不能完全不了解项目。我仍然会给它当前方案、目标、现实限制和可核对的证据,只是不把前面的讨论过程全部带过去。事实不够,它给出的只会是脱离项目的意见;形成过程少一些,才有机会重新检查我们已经默认的前提。
Chat 提出问题以后,我还会把它带回 Codex,对照项目文件、现有实现和历史约束再看一次。它指出的可能是我们忽略的地方,也可能只是因为没看到项目里的限制。最后怎么改,还是要回到项目里判断。
我现在更愿意把这两种上下文分开看。执行要靠连续性,参与者最好知道决定是怎么形成的、哪些路已经走过。复核则要拉开一点距离,不必让复核者继承全部讨论,只从当前方案本身重新判断。过去我总想让每个 AI 拿到尽可能多的信息,现在反而会问:它这一次承担的角色,究竟需要哪一部分上下文?
长期记忆应该回到项目里
主要工作放进 Codex,不代表所有内容都要留在一条不断变长的对话里。
任务会结束,对话会切换,模型能保留的内容也有限。项目规则、架构约束和决策理由以后还会反复用,如果只留在聊天里,过一段时间往往很难找。下一次开新任务,Codex 还是得重新猜。
我会把以后还要用的内容写回项目。稳定的协作规则放进 AGENTS.md,反复执行的工作方式写进 LOOPS.md,具体决策为什么这样做,可以留在项目文档或单独的决策记录里。日志、测试结果和 diff 则说明这一次执行到底发生了什么。
当然也不用保存每段对话。临时讨论和随手想到的备选方案,留在聊天里就够了。我只会写回那些以后还会影响判断、忘了可能再犯同样错误的内容。
新任务不必接着同一条长对话。它先读项目当前状态,再从规则、历史记录和验证结果继续。只要这些内容还在项目里,换一个任务也能重新找到;如果它们只存在聊天窗口里,对话再长也不保险。
我说 Codex 是工作台,指的就是这一点:它手边就是项目的真实状态,讨论后的决定也能写回项目。下一次再打开任务,它读到的是已经修改过的文件,不需要我凭记忆复述上一次发生了什么。
我只是重新安排了它们的位置
我还在用 ChatGPT,这套分工也只适合我现在的任务。对于清楚、独立的工作,先在 Chat 里想好再交给 Codex,依然简单有效。
对我来说,判断标准主要看这件事离真实项目有多近。它需要频繁读取本地文件,方案会在实现过程中变化,后面还要持续修改和验证,我就会让 Codex 尽早参与。如果它只是一个开放问题,或者我只是需要一个不受当前项目影响的第二意见,我会回到 Chat。
这不是把 ChatGPT 换成 Codex。以前我让 Chat 站在上游,把想好的方案交给 Codex;现在我更常让 Codex 留在项目内部,参与从问题形成到执行验证的过程,再让 Chat 在需要时站到外面,重新看一遍我们已经走出的路线。
执行时,我希望 Codex 记得我们为什么走到这里。需要重新判断时,我会把当前方案交给没参与前面讨论的 Chat。