刚开源的 Codex 到底是怎么“干活“的?把它的 Harness 拆开一看,全是循环
先说一个反直觉的事大模型自己根本不会干活。你让它帮我修这个 bug它不会真的去翻代码、跑测试、改文件。它只会做一件事——吐字。一个字一个字往外蹦。那 GitHub 的 Codex 是怎么做到真的去干活的秘密就在一个叫Harness的东西里。今天我就把它拆开给你看。文章目录先泼盆冷水模型只是个嘴一个问题进来先走五层一个问题怎么钻进 Core从 TUI 出发路由开新局还是插话App Server 做翻译官Core 的队列先排队不阻塞Harness 到底在循环什么外层循环RegularTask就管三件事第一次采样前它偷偷干了七件事模型到底看到了什么内层循环ReAct采样→工具→再采样流怎么被处理工具到底怎么执行一圈采样之后看三个标志输出是怎么飞回你屏幕的一个完整例子它到底经历了什么一句话总结附录关键文件速查先泼盆冷水模型只是个嘴很多人以为 AI 编程助手是一个很聪明的大脑自己会动手。真相是模型就是个只会说话的嘴。它连磁盘都碰不到更别说执行命令、改文件了。那干活的到底是谁是一个包在模型外面的循环。这个循环负责把该让模型知道的东西组装好喂给它把模型能用的工具摆到它面前让模型说它想干什么替它真的去执行把执行结果再喂回去循环直到模型说完这个循环在 Codex 的代码里就叫Harness马具、挽具。名字起得挺贴切——马不会自己拉车得套上挽具由人牵着缰绳走。模型不会自己干活得套上 Harness由循环推着它一步步走。一句话Harness 包在模型外面的 agent 循环。它不是单独的组件而是RegularTask→run_turn→run_sampling_request这么一串循环逻辑主要实现在codex-rs/core里。一个问题进来先走五层你敲下一句话它不会直接砸到模型脸上。中间隔了五层像餐厅点菜一样一层层往下传输入层TUI / CLI / App Server 客户端——你在这里打字路由层App Server 的 JSON-RPC决定是开新一轮turn/start还是插话turn/steer调度层Core 的submission_loop按指令分发HarnessRegularTaskrun_turn组上下文、暴露工具、采样、跑工具——核心在这事件层Core 事件 → App Server 通知 → UI 渲染每一层各管一摊解耦得挺干净。这也是为什么你能在 TUI、CLI、App Server 三种界面里用同一个 Codex 内核——换的只是第一层的点菜窗口。一个问题怎么钻进 Core从 TUI 出发你在聊天框里回车这一下会变成一个AppCommand通常是UserTurn然后ChatWidget.submit_op发出一个AppEvent::CodexOp(...)。路由开新局还是插话这里有个很贴心的设计thread_routing.rs如果现在正有一轮回答在跑你新输入的话会被并进去turn_steer——就像你打断别人说话对方接着你的话茬继续。如果空闲就开新一轮turn_start。App Server 做翻译官turn_processor.rs干了几件事校验输入长度、把 v2 的输入项翻译成 Core 认识的UserInput、组装环境/权限/模型覆盖项最后调用CodexThread.start_or_steer_turn(...)。Core 的队列先排队不阻塞CodexThread把请求包成Op::TurnInput丢进 session 的提交通道。submission_loop按Op分发调turn_input::handle。注意这个函数只做路由判断绝不傻等采样。它给你三个答案之一结果含义Started线程空闲创建TurnContextspawn_task(RegularTask)开跑Steered已有活跃 turn把输入追加进去NotSubmitted被拒了turn id 不对、这轮不能插话等Harness 到底在循环什么说白了就是下面这几步反复转组装上下文——模型能看到的instructions、world state、AGENTS.md、skills、历史对话暴露工具——这一步给模型摆出它能调用的工具发起一次流式请求Responses API执行工具调用可能要过审批、进沙箱把工具结果写回 history再采样直到模型结束然后发TurnComplete几个关键函数先混个脸熟函数文件干嘛的RegularTask.runtasks/regular.rs外层 turn 任务run_turnsession/turn.rs内层 agent 循环主角capture_step_context_...session/mod.rs冻结工具/环境/AGENTS.mdbuild_promptsession/turn.rs组装模型请求run_sampling_requestsession/turn.rs一次采样带重试handle_output_item_donestream_events_utils.rs区分文本和工具调用ToolCallRuntime.handle_tool_calltools/parallel.rs真正执行工具build_tool_routertools/spec_plan.rs组装工具表外层循环RegularTask就管三件事RegularTask.run是个很懒的壳只干三件事立刻发TurnStarted让 UI 先渲染起来别让用户干等尽量复用启动时预热好的ModelClientSessionWebSocket / sticky routing省得每次重新握手run_turn返回后如果队列里还排着用户输入就再跑一轮伪代码长这样发 TurnStarted 复用预热好的 ModelClientSession loop: last_agent_message run_turn(...) if input_queue 没有排队输入: return last_agent_message # 否则把排队的用户消息再喂一轮 run_turn第一次采样前它偷偷干了七件事很多人以为采样就是直接把问题丢给模型。其实在第一次真正采样前run_turn先做了一堆铺垫都在session/turn.rs步骤函数目的排空迟到的 hookdrain_async_hook_results把上一轮结束后才完成的 hook 结果入账预压缩run_pre_sampling_compact下次请求可能超窗时先压缩上下文解析 MCP/插件required_mcp_servers_for_input看plugin这类提及决定拉哪些 MCP冻结本步视图capture_step_context...工具、环境、AGENTS.md、能力用同一份快照写 world staterecord_context_updates...让 cwd、权限、模型、环境对模型可见Skills/pluginsbuild_skills_and_plugins注入技能说明和显式启用的 connectorHooks 记录输入run_hooks_and_record_inputshook 能拦截输入通过了才把用户文本写进 history这里有个细节值得注意capture_step_context冻结的是本步的快照。也就是说这一轮里组上下文、暴露工具、派发工具用的都是同一份视图不会出现前面说有一套工具、后面真调用时又变了的错位。工具怎么来的build_tool_router从几个来源拼核心工具shell、apply_patch、多 agent 等、MCP 工具、扩展工具、动态工具。还有个细节Guardian review 这一轮不会暴露 MCP 工具——审核的时候不给它太多武器挺合理。模型到底看到了什么模型拿到的不是原始聊天文本而是一个组装好的PromptPrompt { input // history.for_prompt(...) tools // tool_router.model_visible_specs() parallel_tool_calls // true base_instructions // session 系统提示 output_schema // 可选的结构化输出 }那个input是history.for_prompt(...)合并出来的大杂烩developer / user instructionsworld state工作区、权限、模型、环境AGENTS.md、skills、plugin 说明历史对话本轮用户问题之前的 tool call / tool resultbase_instructions来自Session.get_base_instructions()跟 history 里的 contextual fragments 是分开的。一句话模型看到的是一份被精心拼好的上下文全家桶而不是你打的那句话本身。内层循环ReAct采样→工具→再采样run_turn里有个loop每一圈就是一次采样请求。这是整个 Harness 的心脏这其实就是经典的ReActReason Act循环模型思考——它先说出想法流式吐字调用工具——它提出要调用某个工具结果回灌——Harness 执行完把结果写回 history回到第 1 步——带着结果再让模型想一次流怎么被处理try_run_sampling_request读 SSE 流按事件分门别类模型事件Harness 动作文本/推理增量立刻发AgentMessageContentDelta/ReasoningContentDelta边想边给你看消息/推理完成ItemStarted/ItemCompleted写入 history工具调用完成设needs_follow_up排队一个 tool future流结束但工具没跑完等工具跑完写回结果再采样工具到底怎么执行stream_events_utils.rs里三步走先把 tool call item 写进 history →ToolCallRuntime.handle_tool_call执行 handler → 设needs_follow_up true。tools/parallel.rs里有个挺讲究的并发控制可并行工具比如多个只读查询拿读锁能同时跑互斥工具比如改文件的 shell拿写锁串行执行执行过程中还可能卡在用户审批上exec / patch / permissions。结果变成FunctionCallOutput写回 history下一圈采样就能看到。关键点模型自己永远不碰磁盘。所有副作用都走ToolRouter。这层隔离就是安全感的来源。一圈采样之后看三个标志run_turn会检查三个东西model_needs_follow_up——还有工具没跑完或子 agent 往 mailbox 投了消息has_pending_input——模型跑着时你又打了一句steertoken_limit_reached/ 新 context window——要不要在 turn 中间压缩然后分情况要跟进且快超窗 →run_auto_compact再continue只要跟进 → 带着 history 里的工具结果continue模型说完了 → 跑run_turn_stop_hooks。hook 可以should_block并塞一个 continuation prompt强制再采样否则内层循环 break。之后RegularTask再看一遍 input queue决定要不要再跑一轮。输出是怎么飞回你屏幕的有个体验细节流式文字在采样过程中就发出去了UI 根本不用等TurnComplete。所以你能看到模型边想边打而不是憋半天一次性吐出来。任务收尾时spawn_tasktasks/mod.rs会发TurnComplete带last_agent_message或TurnAborted。事件路径Session.send_event/send_event_raw_with_persistence按策略持久化 rolloutApp Serverconversation.next_event()apply_bespoke_event_handlingServerNotificationTurnStarted、item 增量、TurnCompleted等TUI 渲染一个完整例子它到底经历了什么你问「这个函数为什么 panic」TUI / App Server 把它映射成TurnInput::UserInputCore 返回StartedRegularTask发TurnStarted刷新 AGENTS.md、MCP、工具表冻结进StepContext把 world state、skills、用户问题写进 history把history base_instructions tools发给模型模型先流式输出「我先看代码」再调用shell/ 搜索 / 读文件等工具Harness 执行工具可能先审批把结果写回 history再采样模型写出解释以 delta 流式发出Stop hooks 放行 →TurnCompleteUI 早就把流式文字展示出来了TurnComplete正式收尾一句话总结Codex 的 Harness RegularTask包一层 turnrun_turn反复做「组 Prompt → 流式采样 → 执行工具 / compact / hook → 再采样」直到模型不再需要跟进。模型负责想Harness 负责做。一个只会吐字一个真正动手。两者加起来才是你看到的那个会干活的 AI。附录关键文件速查路径职责tui/src/chatwidget.rs接收用户提交tui/src/app/thread_routing.rsturn/start与turn/steerapp-server/src/request_processors/turn_processor.rsApp Server turn APIcore/src/codex_thread.rs线程侧 submit / start-or-steercore/src/session/handlers.rssubmission_loopcore/src/session/turn_input.rsStart / steer / 拒绝core/src/tasks/regular.rs外层 harness 任务core/src/tasks/mod.rsspawn_task、TurnCompletecore/src/session/turn.rsrun_turn、采样、promptcore/src/session/mod.rsStep context、world state、事件core/src/session/turn_context.rsTurnContextcore/src/stream_events_utils.rs流 item → 文本或工具core/src/tools/spec_plan.rs工具表core/src/tools/parallel.rs并行 / 串行工具运行时app-server/src/bespoke_event_handling.rsCore 事件 → 客户端通知参考代码https://github.com/openai/codex如果你觉得这篇对你有用点个赞、转给身边写代码的朋友。下一篇可以聊聊 Codex 的上下文压缩compact到底是怎么瘦身的——想看的人多就安排。

相关新闻

实测Grok 4.6:从炫酷演示到工程实践,AI编码助手的能力边界与集成指南

实测Grok 4.6:从炫酷演示到工程实践,AI编码助手的能力边界与集成指南

上周,我花了一下午时间,把网上能找到的关于 Grok 4.6 的零散信息、开发者讨论和早期测试反馈都翻了一遍。说实话,第一感觉是有点“割裂”。一边是社区里流传的、让人眼前一亮的“中文配音”演示视频,展示着它如何流畅地生成一个浏…

2026/8/23 19:40:18 阅读更多 →
fzf:终端里的万能模糊查找器,找文件找命令都快人一步

fzf:终端里的万能模糊查找器,找文件找命令都快人一步

fzf:终端里的万能模糊查找器,找文件找命令都快人一步通用命令行模糊查找工具,替代 find、CtrlR,配合 Vim、Shell 使用,输入几个字母就能瞬间定位目标。📖 背景说明 fzf(Fuzzy Finder&#xff09…

2026/8/23 19:40:18 阅读更多 →
大厂Java面试全解析:流程、重点与应对策略

大厂Java面试全解析:流程、重点与应对策略

1. 面试实录背后的行业现状最近在技术社区看到一份名为"互联网大厂Java求职面试实录:严肃面试官VS搞笑谢飞机"的面试记录,这份材料生动展现了大厂技术面试的真实场景。作为经历过数十场大厂面试的面试官,我发现这份实录准确地反映了…

2026/8/23 19:39:17 阅读更多 →

最新新闻

FileMover:开源文件自动化管理工具,告别手动整理与备份

FileMover:开源文件自动化管理工具,告别手动整理与备份

你的电脑硬盘是不是也经常被各种文件塞得满满当当?照片、文档、视频、压缩包混在一起,想整理却无从下手?手动筛选、复制、移动,不仅耗时费力,还容易出错,一个不小心就可能覆盖重要文件。今天要介绍的&#…

2026/8/23 20:37:47 阅读更多 →
从数学建模赛题看数据驱动决策:自行车功率优化实战解析

从数学建模赛题看数据驱动决策:自行车功率优化实战解析

1. 项目概述:从一道赛题看数据驱动决策的实战演练 2022年美国大学生数学建模竞赛(MCM/ICM)的A题,题目是“ Cycling Power Profile ”(自行车功率曲线)。当年这道题一出来,就在我们这些老建模人…

2026/8/23 20:37:47 阅读更多 →
基于ThinkPHP与Laravel的高校招聘系统开发实践

基于ThinkPHP与Laravel的高校招聘系统开发实践

1. 项目背景与核心需求高校招聘会求职系统是连接企业与应届毕业生的重要桥梁。传统线下招聘会存在时间短、信息不对称、效率低下等问题,而基于ThinkPHP和Laravel框架开发的移动端解决方案能有效解决这些痛点。这个系统需要实现的核心功能包括:企业端&…

2026/8/23 20:37:47 阅读更多 →
PyTorch模型调参实战:学习率与批量大小优化指南

PyTorch模型调参实战:学习率与批量大小优化指南

在机器学习项目中,我们常常遇到这样的困境:模型训练了很久,但准确率就是卡在一个瓶颈上不去;或者损失函数震荡剧烈,始终无法收敛。这背后,往往不是算法本身的问题,而是超参数(Hyperp…

2026/8/23 20:36:46 阅读更多 →
vite配置

vite配置

#vite配置-------##这是项目初始化创建的时候配置(vite.config.js): import { defineConfig } from ‘vite’ import vue from ‘vitejs/plugin-vue’ // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], }) 接…

2026/8/23 20:36:46 阅读更多 →
数学建模实战:皮尔逊、斯皮尔曼与肯德尔相关系数的选型、计算与解读全指南

数学建模实战:皮尔逊、斯皮尔曼与肯德尔相关系数的选型、计算与解读全指南

1. 从“相关性”到“相关系数”:为什么它不只是个数字 在数学建模的实战里,尤其是处理那些涉及社会经济、生物统计、金融分析等领域的题目时,我们常常会面对一堆看起来杂乱无章的数据。比如,给你一个城市过去十年的GDP数据和它的空…

2026/8/23 20:36:46 阅读更多 →

日新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

周新闻

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/23 0:00:50 阅读更多 →
SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/23 0:00:50 阅读更多 →
Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/23 0:00:50 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/23 18:47:06 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/23 12:10:44 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/22 3:22:48 阅读更多 →