目 录CONTENT

文章目录

解密 Codex Agent 循环:深入探索软件智能体的核心逻辑

Administrator
2026-01-24 / 0 评论 / 0 点赞 / 0 阅读 / 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 issues 和 pull requests 中。)

首先,我们将重点介绍智能体循环(agent loop),这是 Codex CLI 中的核心逻辑,负责编排用户、模型以及模型为执行有意义的软件工作而调用的工具之间的交互。我们希望这篇文章能让您很好地了解我们的智能体(或“框架”/“harness”)在利用 LLM 方面所扮演的角色。

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

智能体循环

每个 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)。在许多情况下,此消息直接回答了用户的原始请求,但也可能是对用户的后续问题。

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

图中所示从用户输入智能体响应的整个过程被称为对话的一个回合(turn)(在 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发送 HTTP 请求以运行模型推理。我们将研究信息如何通过 Codex 传输,Codex 使用 Responses API 来驱动智能体循环。

Codex CLI 使用的 Responses API 端点是可配置的,因此它可以与实现 Responses API 的任何端点一起使用:

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

构建初始提示词

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

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

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

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

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

JavaScript

1
[
2
// Codex's default shell tool for spawning new processes locally.
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 built-in plan tool.
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
// Web search tool provided by the Responses API.
34
{
35
"type": "web_search",
36
"external_web_access": false
37
},
38

39
// MCP server for getting weather as configured in the
40
// user's ~/.codex/config.toml.
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 对象,其中包含 typerolecontent,如下所示:

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 的配置方式,发送带有 Authorization 标头的 HTTP POST 请求(如果指定,还会添加额外的 HTTP 标头和查询参数)。

当 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 对话中的第一个“回合”。服务器通过服务器发送事件(SSE(opens in a new window))流进行响应。每个事件的 data 是一个 JSON 载荷,其 "type""response" 开头,可能如下所示(事件的完整列表可以在我们的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

评论区