Jason Liu(OpenAI Codex 团队工程师,Instructor 库作者)分享了他从"把 Codex 当代码工具"到"把 Codex 当工作操作系统"的转变过程。
关键认知:Codex 依然擅长写代码,但更有趣的转变是它让工作有了"栖身之所"(somewhere to live)。
持久线程(Durable Threads)
Compaction(压缩)是改变行为的第一件事——把长期运行的线程压缩,让它不必携带每条旧消息的全文就能继续前进。
Jason 现在为每个重要工作流维护一个 pinned thread:
- Chief of Staff thread
- Agents SDK thread
- OpenAI CLI thread
- Codex for open source thread
- 一个专门监控 Twitter 的 thread
这些不是短对话,是已经压缩了数月的 mega-threads。它们积累历史、偏好、旧决策,不用每次回来都重建上下文。
Pinned thread 可以用 Command-1 到 Command-9 快捷键直接跳转。
代价:长期线程不是免费的。如果稍后 revisit,对话可能已不在缓存中,成本会比新开短线程更高。但对在乎的工作流,连续性值得这个代价。
语音输入(Voice Input)
语音输入的价值不是速度,而是让 Agent 获得未经编辑的思考版本。
Jason 用 Wispr Flow 做系统级语音输入。规划工作时可以说:"我想 Slack 里有个叫 Ben 的人提过这事,我不记得具体是什么,去查查。"这种话太模糊、懒得打字,但说出来很自然。
同样适用于转录:打电话、面对面交谈时用 Granola 录音,然后把转录作为起始材料。很多计划在模型能接触到** messy version** 而非 polished version 时变得更好。
Steering(实时引导)
Steering = 在 Codex 已经工作时继续添加方向,而非等当前步骤完成。
可以在 tool call 后注入下一条消息。比如审网站时可以边看图边说:
- "把这个做小一点"
- "这段文案错了"
- "这两个东西的间距感觉不对"
- "做完后开个 PR"
- "等预览部署"
- "把预览链接发给 Slack 里需要审的人"
不需要等每步完成再决定下一步。可以在 Agent 工作时持续添加意图,然后走开,队列已经 shaping 好了。
之后 Heartbeats 可以在离开后监控 PR 或 Slack thread。工作单元不再是"一个 prompt 一个答案",而是一个小型 operating loop。
记忆系统(Memory)
线程变长后,需要线程外的共享记忆。
关键动作不是保留消息历史。长线程能记住很多,但记忆被困在线程里,除非有用的部分被序列化到某个持久的地方。记忆系统的目的是把线程学到的东西变成可检查、可编辑、可 diff、可复用的 artifact。
Jason 的大部分长期线程从一个 Obsidian vault 开始:
vault/
├── TODO.md
├── people/
├── projects/
├── agent/
└── notes/
顶层放 AGENTS.md 指令,比如:当你学到更多关于人的信息、在项目上有进展、或关闭一个 open loop 时,更新 vault 里相应的页面。
Vault 是 Agent 居住的地方,独立于任何项目。Repo 放代码,vault 放工作的滚动上下文:人、决策、open loops、每日笔记、项目状态、那些否则会在线程之间丢失的理解碎片。
Vault 同时是一个 GitHub repo,带来两个好处:
- 可以在云端工作
- Diff 变成记忆的 review surface
当 Agent 更新 vault 时,可以看 diff 了解它认为什么值得记住。Review 步骤很重要——不希望 evergreen threads 在对话历史中悄悄积累 vibes,而希望它们写下什么变了:这个人偏好这个,这个项目等那个,这个决策已做,这个 loop 已关。
这也是 Jason 喜欢文件形式记忆的原因。文件迫使 Agent 把经验压缩成能 survive 线程的形式。如果线程死了、压缩坏了、或太贵了无法继续依赖,有用的知识还在那里。
到这个阶段,pinned threads 开始感觉不像聊天,更像不同工人读同一本笔记本。
Codex 也有第一方记忆功能(Settings > Personalization > Memories)。Jason 把它们看作本地召回层:对稳定偏好、重复工作流、项目惯例、已知陷阱有用,但不能替代 checked-in 指令或显式 vault。
Chronicle 尤其有趣,因为它能用近期屏幕上下文帮助构建记忆。但文档明确说明这是 opt-in research preview,有权限、速率限制、prompt injection、未加密本地记忆文件等真实 tradeoffs。
方向性上它指向同一件事:工作应该留下结构化记忆,而非只是更长的聊天记录。
计算机与浏览器使用
线程有了记忆后,下一个问题是它能触碰什么。
Jason 的区分方式:
$browser:本地 web surface,想检查和标注@chrome:已登录的浏览器状态和多标签@computer:只能通过 GUI 完成的工作
迭代本地 app 时用 $browser,需要在已登录会话里工作时用 @chrome,只能点击桌面应用时用 @computer。
Connectors 把触手延伸到实际工作的其余部分。最常用的是 $slack、$gmail、$calendar,因为 Slack threads、收件箱、日历是很多工作在变成代码之前出现的地方。
Skills 让重复工作流可复用。Skill Creator 和 Skill Installer 是起点。Skill Installer 可以直接从 composer 添加 OpenAI 推荐的 skills。做过一次有用的事后,通常可以打包让 Codex 下次无需重新教就能做。
远程控制(Remote Control)
远程控制让这些更长的 loops 变得便携。
Codex 可以在文件、权限、本地设置已存在的机器上持续工作,同时你从移动端 check in、review 发现、回答问题、批准下一步、或改变方向——无需回到桌前。OpenAI 把它描述为"从任何地方使用 Codex"。
这在你开始了一个长时间运行的任务、想保持 momentum 时最有价值。可以启动任务,走开,然后在到达决策点时从手机上 steering。
这很重要,原因和 pinned threads、语音、Heartbeats 重要一样:工作不再因为换了位置就必须暂停。 线程可以继续,你可以保持刚好足够的注意力来 unblock 下一步。
Heartbeats
Pinned threads 有用,但它们仍然等你说话。Heartbeats 让它们自动重复。
Heartbeat = 线程可以为自己安排的周期性检查,比如监控 Slack 或 PR 的新活动。
一个线程可以有多个 schedule,运行到某个条件满足,并随时间调整频率。
Chief of Staff 示例
Jason 的 Chief of Staff thread 每 30 分钟运行一次:
每 30 分钟检查 Slack 和 Gmail 中需要我注意的未回复消息。
帮我优先处理最重要的。
如果有人问我问题,尽可能深入研究答案并起草回复,但不要发送。
回到 Slack 时,回复往往已经在草稿里。仍然决定发什么,但收集上下文的昂贵部分已经完成。
监控反馈
同样模式适用于 review loops。Heartbeat 可以监控 Google Docs 评论、PR 评论、或 Slack 回复,在反馈到达时保持工作推进。
一个动画项目的例子:在 Slack 发视频,让 Codex 每 15 分钟检查 thread 的反馈,有新评论时重新渲染版本,回复到 thread 里 tag reviewer。Slack MCP server 不能上传文件,Agent 用 @computer 按 Add file 按钮并 post 修订后的渲染。
有趣的部分不只是每 15 分钟检查 Slack。Loop 跨越了工具边界:Slack 收集反馈,Remotion 渲染,@computer 上传。当 Heartbeats、connectors、computer use 不再像独立功能,而是一起变成持续运行的反馈 loop——这才是真正的代理式工作流。
退款示例
最近一个包裹被偷。Amazon 说大概需要 25 分钟才能和真人对话。于是创建一个 @computer 线程:
每 5 分钟检查客服是否已加入对话。
如果加入了,尽力帮我退款。
一旦回复,切换到每分钟检查,以便更快响应。
洗完澡回来,退款已完成。
很多 Heartbeats 也会更新 Obsidian vault 作为显式记忆。
Goals(目标)
Jason 还在学习如何用好的是 Goals。
Goal = 有真正终点、Codex 可以持续推动的长期任务。
应该对它们有野心。弱目标是"实现这个 Markdown 文件里的计划"。强目标有 Agent 可以持续 push against 的真实成功标准。
上周尝试把 Python Rich 库迁移到 Rust。因为原项目已有大量单元测试,可以设定目标:迁移 Rich 到 Rust,但必须通过原库的所有单元测试。
测试套件给了运行一个真正的 oracle:Rust 端口直到通过和 Python 库相同的测试才算完成。
这和与 AI 进行长对话、积累 Markdown 计划、最后说"实现这个"不同。执行的质量取决于目标和验证。 没有验证的野心只是愿望。
侧边栏(The Side Panel)
Codex 中 Jason 最兴奋的部分是侧边栏。
容易把它看作 preview 发生的地方。这低估了它。侧边栏是 Codex 从聊天应用变成工作发生之地的地方。
对 Jason 来说它做三件事:检查 artifact、操作 web surface、review 变更。在所有三件事中,他都可以查看和评论 Agent 正在操作的同一个对象。
检查 Artifacts
Markdown、spreadsheet、CSV、PDF、slides 都可以住在那里。
Markdown 可评论。Spreadsheet 渲染公式并支持单元格编辑。CSV 变成表格而非原始文本。PDF 直接渲染,和 LaTeX 尤其有用。Slides 可以在不离开应用的情况下创建和 review。
重要的不是 Codex 能生成 artifact,而是可以在不打破 loop 的情况下检查和标注它们。
操作 Web Surfaces
应用内浏览器更有趣。Agent 可以看到它,通过 $browser 用 JavaScript 控制它,Jason 可以直接在正在看的东西上留 annotation。
几个常用的 web surface:
index.html:轻量级静态 artifact- Storybook:review UI 组件
- Remotion Studio:程序化动画
- Slidev:演示文稿
- Streamlit:数据应用
最小的版本往往最好。可以让模型做一个带 JavaScript 和 CSS 的单个 index.html,在侧边栏打开,立即开始交互。不需要服务器。
Jason 在实验用 Heartbeats 随时间更新静态 index.html,这样每次回到线程时,已经有一个新鲜的 artifact 在等着。
Thariq 有一篇很好的 post 关于偏好 HTML 而非 Markdown 作为输出格式。这个直觉是对的。一旦输出变成小型应用而非只是文档,关系就变了。
如果需要更重的,可以用 Vite app,但需要保持服务器运行。纯 index.html 更 durable。
动画工作时,经常并排打开 Storybook 和 Remotion Studio。可以留评论如"让这个弹跳"或"这个应该更大",Agent 可以 inspect 和 Jason 看的一样的浏览器状态,包括动画的当前帧。
演示文稿常用 Slidev。Codex 可以 inspect slides、发现内容被截断、切换 slides、在 review 时响应 annotations。
也期待这对 Streamlit、Jupyter 等工具变得更有用。不同的人已经住在不同应用里,Codex increasingly 能在那里和他们见面。
核心洞察: Codex 获得越多能记忆、 revisit、inspect、行动的地方,工作就越不会在 prompts 之间死掉。
重要的不是 Agent 能为 Jason 写代码,而是更多工作可以在他离开后持续推进。