Agent Loop¶
Codex 的 agent loop 位于 codex-rs/core/src/session/turn.rs 的 run_turn。源码注释里把模型输出分成两类:函数调用或 assistant message。实现上,loop 会持续采样,直到模型不再需要工具 follow-up,也没有 pending user input。
采样前¶
一次 turn 开始后,run_turn 先做几件事:
run_pre_sampling_compact:如果上下文接近阈值,先压缩。record_context_updates_and_set_reference_context_item:记录 turn context 的差量或 baseline。build_skills_and_plugins:根据用户输入里的显式 mention、可用插件、MCP 工具和 connectors 构建注入项。run_pending_session_start_hooks、run_hooks_and_record_inputs:让 hook 有机会阻止或改写输入。
这说明 Codex 的 prompt 不是静态模板,而是每个 turn 动态组装的运行时视图。
采样中¶
每次进入 loop,核心步骤是:
- 从
InputQueue取 pending input。 - 运行 pending input hook 并写入历史。
- 记录时间提醒、rollout budget 提醒等上下文。
clone_history().for_prompt(...)生成模型输入。- 通过
run_sampling_request请求模型流。 - 解析 response item,遇到 tool call 就通过
ToolCallRuntime执行。
ModelClientSession 是 turn-scoped 的,它会跨 retry 复用,用于保持 websocket、sticky routing 等 turn 内状态。
采样后¶
模型返回后,loop 会判断:
model_needs_follow_up:模型调用工具后,需要把工具结果再发给模型。has_pending_input:用户在运行期间又输入了内容。token_limit_reached:上下文超过自动压缩阈值。
如果需要继续,就再次采样;如果 token limit 触发,则调用 run_auto_compact,再继续。
结束条件¶
当既没有 follow-up,也没有 pending input 时,Codex 会:
- 运行
run_turn_stop_hooks。 - 如果 stop hook 要求继续,会把 hook prompt 写入历史并继续 loop。
- 运行 legacy after-agent hook。
- 返回最后一条 assistant message。
这意味着“一个用户 turn”内部可能包含多次模型请求、多个工具调用、一次上下文压缩,甚至 stop hook 触发的额外模型继续。
Loop Engineering 的价值¶
Codex 的 loop 有几个值得借鉴的点:
- 把 pending user input 作为 loop 的一等输入,而不是简单拒绝。
- 把压缩放进 loop,而不是只在 turn 之间做后台任务。
- 把 hook 作为明确的阻断点和续跑点。
- 把 token usage、window id、trace、telemetry 和 history version 都绑定到 turn。
- 工具调用结果回到模型前会先经过统一生命周期和 hook。