<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Agent Loop on Codexer</title><link>https://codexer.com/tags/agent-loop/</link><description>Recent content in Agent Loop on Codexer</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sat, 31 Oct 2026 06:52:15 +0800</lastBuildDate><atom:link href="https://codexer.com/tags/agent-loop/index.xml" rel="self" type="application/rss+xml"/><item><title>Codex 每问一句，都要把整段对话重发一遍</title><link>https://codexer.com/posts/2026-10-31-codex-agent-loop-prefix-cache/</link><pubDate>Sat, 31 Oct 2026 06:52:15 +0800</pubDate><guid>https://codexer.com/posts/2026-10-31-codex-agent-loop-prefix-cache/</guid><description>&lt;p&gt;前段时间翻 OpenAI 的工程博客，读到 Michael Bolin 写的《Unrolling the Codex agent loop》，今年一月发的，是一个系列的开篇。这篇讲的是 Codex 最里面那个循环怎么转，信息密度比大多数产品说明高出好几档。&lt;/p&gt;
&lt;p&gt;大部分人看这种文章，注意力会停在模型怎么思考上。我读完记住的却是另一件事：Codex 每问一句，都要把整段对话原封不动重新发一遍，而且它到今天也不打算改。&lt;/p&gt;
&lt;h2 id="一次对话几百次请求"&gt;一次对话，几百次请求&lt;/h2&gt;
&lt;p&gt;先把循环说清楚。你写一句话描述需求，Codex 组一个 prompt 发给模型。模型要么直接回你一段话，要么要求调工具，比如跑一条 shell 命令、读一个文件。要调工具的话，Codex 执行完把输出拼回 input，再发一次请求。&lt;/p&gt;
&lt;p&gt;这个「再发一次」会一直重复，直到模型不要再工具、直接给你回复为止。这段过程在 Codex 里叫一个 turn。&lt;/p&gt;
&lt;p&gt;一个 turn 里跑几百次工具调用是常事，每一次都要重新请求一次模型。而每一次请求，Codex 都会把之前所有内容带上：你的原始消息、模型前面想过的东西、它调过哪些工具、工具返回了什么。全带上。&lt;/p&gt;
&lt;p&gt;所以随着对话变长，发给 API 的 JSON 总量是按平方涨的。官方自己也认这一点，原文写的是「你说得对」。&lt;/p&gt;
&lt;p&gt;Responses API 其实给了办法，一个叫 &lt;code&gt;previous_response_id&lt;/code&gt; 的参数，只要给个 id，服务端自己去取之前的状态，你只发新增那一小段。Codex 没用。&lt;/p&gt;
&lt;p&gt;两个理由。一是让每个请求完全无状态，服务端不用记东西，实现起来简单。二是要支持零数据保留（ZDR）的客户，而这个能力的前提是服务端不存会话状态等人来取。&lt;/p&gt;
&lt;p&gt;这里有个细节挺耐人寻味。ZDR 客户按理说会失去「模型记得上一轮想过什么」这件事，因为推理内容留不下来。但 Codex 往 reasoning item 里塞了一个 &lt;code&gt;encrypted_content&lt;/code&gt;，加密后的推理内容，服务端能解开。OpenAI 存的是 ZDR 客户的解密密钥，不是他们的数据。这个损失就被绕过去了。&lt;/p&gt;
&lt;h2 id="缓存命中时平方变线性"&gt;缓存命中时，平方变线性&lt;/h2&gt;
&lt;p&gt;传输量按平方涨，听着吓人。但网络不是主要成本，采样模型才是。所以真正的解法不在传输层，在计算层，也就是提示词缓存。&lt;/p&gt;
&lt;p&gt;缓存命中时，模型采样从平方变成线性。这是整篇里最值钱的一句话。&lt;/p&gt;
&lt;p&gt;条件是精确前缀匹配。缓存只认「这次请求的开头跟上次一个字节都不差」的情况。由此推出一条通用规则：静态内容放前面，变量放后面，图片和工具定义在两次请求之间必须完全一致。&lt;/p&gt;
&lt;p&gt;Codex 的 prompt 结构就是按这条规则排的。&lt;/p&gt;
&lt;h2 id="一个-prompt-里装了哪几样东西"&gt;一个 prompt 里装了哪几样东西&lt;/h2&gt;
&lt;p&gt;这部分值得细看，它解释了 Codex 一堆看着奇怪的设计。&lt;/p&gt;
&lt;p&gt;instructions 字段来自配置文件，或者模型自带的 base instructions。tools 是工具定义，包括 Codex 自己的 shell 工具、plan 工具、联网搜索，加上你通过 MCP 挂上去的。然后 input 里依次放四样东西，最后才是你说的话。&lt;/p&gt;</description></item></channel></rss>