目 录CONTENT

文章目录

深入解析 Codex 代理循环

Administrator
2026-01-24 / 0 评论 / 0 点赞 / 1 阅读 / 0 字

📢 转载信息

原文链接:https://openai.com/index/unrolling-the-codex-agent-loop

原文作者:Michael Bolin, Member of the Technical Staff


2026年1月23日

Codex CLI(opens in a new window) 是我们跨平台的本地软件代理,旨在安全高效地在您的机器上生成高质量、可靠的软件更改。自我们去年四月首次推出 CLI 以来,我们在构建世界一流的软件代理方面学到了很多东西。为了深入探讨这些见解,这是我们将要探索 Codex 工作原理的各个方面以及吸取的宝贵经验的持续系列文章的第一篇。(如需了解 Codex CLI 构建方式的更细粒度视图,请查看我们的开源仓库:https://github.com/openai/codex(opens in a new window)。如果您想了解更多信息,我们设计决策的许多细节都记录在 GitHub issue 和 pull request 中。)

首先,我们将重点关注代理循环agent loop),这是 Codex CLI 中的核心逻辑,负责编排用户、模型以及模型为执行有意义的软件工作而调用的工具之间的交互。我们希望这篇文章能让您对我们的代理(或“框架”,harness)在利用大型语言模型(LLM)方面所扮演的角色有一个清晰的认识。

在深入研究之前,我们快速说明一下术语:在 OpenAI,“Codex”涵盖了一套软件代理产品,包括 Codex CLI、Codex Cloud 和 Codex VS Code 扩展。本文重点介绍 Codex 框架harness),它提供了所有 Codex 体验的基础核心代理循环和执行逻辑,并通过 Codex CLI 呈现出来。为方便起见,我们将交替使用“Codex”和“Codex CLI”这两个术语。

模型推理(Model inference)

每个 AI 代理的核心就是所谓的“代理循环”。代理循环的简化图示如下:

Diagram titled “Agent loop” illustrating how an AI system processes a user request, calls tools, observes results, updates its plan, and returns outputs. Arrows connect steps such as user input, model reasoning, tool actions, and final response.

首先,代理从用户那里获取输入,并将其纳入为提示词prompt)准备给模型的文本指令集中。

下一步是通过向模型发送指令并要求其生成响应来查询模型,这个过程称为推理inference)。在推理过程中,文本提示首先被翻译成一串输入令牌(opens in a new window)——索引到模型词汇表的整数。然后使用这些令牌对模型进行采样,生成一串新的输出令牌。

输出令牌被翻译回文本,成为模型的响应。由于令牌是增量产生的,这种翻译可以在模型运行时发生,这就是为什么许多基于 LLM 的应用程序会显示流式输出。在实践中,推理通常被封装在一个操作文本的 API 后面,从而抽象化了令牌化的细节。

作为推理步骤的结果,模型要么(1)对用户的原始输入产生最终响应,要么(2)请求代理应执行的工具调用(例如,“运行 ls 并报告输出”)。在情况(2)下,代理执行工具调用,并将其输出附加到原始提示词中。此输出用于生成新的输入,用于重新查询模型;然后代理可以考虑这些新信息并再次尝试。

这个过程会重复,直到模型停止发出工具调用,而是为用户生成一条消息(在 OpenAI 模型中称为助手消息assistant message)。在许多情况下,此消息直接回答了用户的原始请求,但也可能是向用户提出的后续问题。

由于代理可以执行修改本地环境的工具调用,“输出”不仅仅局限于助手消息。在许多情况下,软件代理的主要输出是它在您的机器上编写或编辑的代码。尽管如此,每一轮对话总是以一条助手消息结束——例如“我已添加您要求的 architecture.md”——这标志着代理循环中的一个终止状态。从代理的角度来看,它的工作已经完成,控制权返回给用户。

图中所示的从用户输入代理响应的旅程被称为对话的一(在 Codex 中称为线程thread)。尽管这个对话轮次可能包含 模型推理工具调用 之间的多次迭代)。每次您向现有对话发送新消息时,对话历史记录都会作为新一轮提示词的一部分包含在内,其中包含先前轮次的消息和工具调用:

Diagram titled “Multi-turn agent loop” showing how an AI agent iteratively takes user input, generates actions, consults tools, updates state, and returns results. Includes labeled steps, arrows, and example tool outputs illustrating the agent’s reasoning cycle.

这意味着随着对话的增长,用于模型采样的提示词的长度也会增加。这个长度很重要,因为每个模型都有一个上下文窗口context window),即单次推理调用所能使用的最大令牌数。请注意,此窗口包括输入和输出令牌。正如您可能想象的那样,代理可能会决定在一个轮次中进行数百次工具调用,从而可能耗尽上下文窗口。因此,上下文窗口管理是代理的众多职责之一。现在,让我们深入了解 Codex 如何运行代理循环。

模型推理

Codex CLI 通过向Responses API(opens in a new window)发送 HTTP 请求来运行模型推理。我们将研究信息如何通过 Codex 流动,Codex 使用 Responses API 来驱动代理循环。

Codex CLI 使用的 Responses API 端点是可配置的(opens in a new window),因此它可以与任何实现 Responses API 的端点(opens in a new window)一起使用:

让我们探讨一下 Codex 如何为对话中的第一次推理调用构建提示词。

构建初始提示词

作为最终用户,当您查询 Responses API 时,您不会逐字指定用于模型采样的提示词。相反,您在查询中指定各种输入类型,Responses API 服务器决定如何将此信息构造为模型设计用于消费的提示词。您可以将提示词视为“项目列表”;本节将解释您的查询如何转换为该列表。

在初始提示词中,列表中的每个项目都与一个角色role)相关联。role 指示相关内容应具有多少权重,并且是以下值之一(按优先级递减):systemdeveloperuserassistant

Responses API 接受一个带有许多参数的 JSON 负载。我们将重点关注这三个参数:

在 Codex 中,instructions 字段从 ~/.codex/config.toml 中的model_instructions_file(opens in a new window)(如果指定)读取;否则,使用与模型关联的base_instructions(opens in a new window)。模型特定的指令存在于 Codex 仓库中,并捆绑到 CLI 中(例如,gpt-5.2-codex_prompt.md(opens in a new window))。

tools 字段是工具定义列表,符合 Responses API 定义的模式(schema)。对于 Codex 而言,这包括 Codex CLI 提供的工具、应提供给 Codex 的 Responses API 提供的工具,以及用户提供的工具,通常是通过 MCP 服务器:

JavaScript

1
[
2
// Codex's 默认 shell 工具,用于在本地生成新进程。
3
{
4
"type": "function",
5
"name": "shell",
6
"description": "Runs a shell command and returns its output...",
7
"strict": false,
8
"parameters": {
9
"type": "object",
10
"properties": {
11
"command": {"type": "array", "description": "The command to execute", ...},
12
"workdir": {"description": "The working directory...", ...},
13
"timeout_ms": {"description": "The timeout for the command...", ...},
14
...
15
},
16
"required": ["command"],
17
}
18
}
19

20
// Codex's 内置计划工具
21
{
22
"type": "function",
23
"name": "update_plan",
24
"description": "Updates the task plan...",
25
"strict": false,
26
"parameters": {
27
"type": "object",
28
"properties": {"plan":..., "explanation":...},
29
"required": ["plan"]
30
}
31
},
32

33
// Responses API 提供的Web 搜索工具
34
{
35
"type": "web_search",
36
"external_web_access": false
37
},
38

39
// MCP 服务器用于获取用户 ~/.codex/config.toml 中配置的天气信息。
40
// 的天气
41
{
42
"type": "function",
43
"name": "mcp__weather__get-forecast",
44
"description": "Get weather alerts for a US state",
45
"strict": false,
46
"parameters": {
47
"type": "object",
48
"properties": {"latitude": {...}, "longitude": {...}},
49
"required": ["latitude", "longitude"]
50
}
51
}
52
]

最后,JSON 负载的 input 字段是一个项目列表。在添加用户消息之前,Codex 将以下项目插入(opens in a new window)input 中:

1. 一条带有 role=developer 的消息,描述了仅适用于 Codex 提供的 shell工具(在 tools 部分定义)的沙箱环境。也就是说,其他工具(例如从 MCP 服务器提供的工具)不受 Codex 沙箱化保护,需要自行执行保护措施。

该消息是根据模板构建的,其中关键内容来自捆绑在 Codex CLI 中的 Markdown 片段,例如 workspace_write.md(opens in a new window)on_request.md(opens in a new window)

纯文本

1
<permissions instructions>
2
- description of the sandbox explaining file permissions and network access
3
- instructions for when to ask the user for permissions to run a shell command
4
- list of folders writable by Codex, if any
5
</permissions instructions>

2.(可选)一条带有 role=developer 的消息,其内容是用户 config.toml 文件中读取的 developer_instructions 值。

3.(可选)一条带有 role=user 的消息,其内容是“用户指令”,这些指令并非来自单个文件,而是从多个来源聚合(opens in a new window)而成。一般来说,更具体的指令会出现在后面:

4. 一条带有 role=user 的消息,描述了代理当前操作的本地环境。这指定了当前工作目录和用户的 shell(opens in a new window)

纯文本

1
<environment_context>
2
<cwd>/Users/mbolin/code/codex5</cwd>
3
<shell>zsh</shell>
4
</environment_context>

一旦 Codex 完成上述所有计算来初始化 input,它就会附加用户消息以开始对话。

前面的示例侧重于每条消息的内容,但请注意,input 的每个元素都是一个 JSON 对象,具有如下的 typerole(opens in a new window)content

JSON

1
{
2
"type": "message",
3
"role": "user",
4
"content": [
5
{
6
"type": "input_text",
7
"text": "Add an architecture diagram to the README.md"
8
}
9
]
10
}

一旦 Codex 构建了发送到 Responses API 的完整 JSON 负载,它就会根据 ~/.codex/config.toml 中 Responses API 端点的配置方式(如果指定,则添加额外的 HTTP 标头和查询参数)使用 Authorization 标头发出 HTTP POST 请求。

当 OpenAI Responses API 服务器接收到请求时,它会使用 JSON 按如下方式推导出模型的提示词(为确保准确性,自定义的 Responses API 实现可能会做出不同的选择):

Snapshot diagram showing a single step in an AI agent loop. A user request enters the model, which produces a thought, an action with a tool name, and a tool input. The diagram highlights this intermediate reasoning step before the tool is called.

正如您所见,提示词中前三个项目的顺序由服务器决定,而不是客户端。话虽如此,在这三项中,只有系统消息的内容也是由服务器控制的,因为 toolsinstructions 是由客户端确定的。紧随其后的是 JSON 负载中的 input,以完成提示词。

现在我们有了提示词,我们就可以对模型进行采样了。

第一轮对话

这个对 Responses API 的 HTTP 请求启动了 Codex 中对话的第一个“轮次”。服务器以服务器发送事件(Server-Sent Events,SSE(opens in a new window))流进行响应。每个事件的 data 是一个 JSON 负载,其中包含一个以 "response" 开头的 "type",可能如下所示(完整的事件列表可以在我们的API 文档(opens in a new window)中找到):

纯文本

1
data: {"type":"response.reasoning_summary_text.delta","delta":"ah ", ...}
2
data: {"type":"response.reasoning_summary_text.delta","delta":"ha!", ...}
3
data: {"type":"response.reasoning_summary_text.done", "item_id":...}
4
data: {"type":"response.output_item.added", "item":{...}}
5
data: {"type":"response.output_text.delta", "delta":"forty-", ...}
6
data: {"type":"response.output_text.delta", "delta":"two!", ...}
7
data: {"type":"response.completed","response":{...}}

Codex 消费事件流(opens in a new window)并将其重新发布为可供客户端使用的内部事件对象。诸如 respon... [内容被截断]




🚀 想要体验更好更全面的AI调用?

欢迎使用青云聚合API,约为官网价格的十分之一,支持300+全球最新模型,以及全球各种生图生视频模型,无需翻墙高速稳定,文档丰富,小白也可以简单操作。

0

评论区