
本文深入解析了OpenAI Codex的Harness框架从模型层到产品层详细阐述了如何将GPT模型与工具链结合实现稳定、可观察、可暂停、可恢复的Agent运行系统。文章从Codex Core的Thread运行时、App Server的双向协议设计到Thread、Turn、Item的状态管理逐层剖析了Harness的核心机制。特别强调了Harness在上下文管理、执行控制、状态持久化和产品交互方面的关键作用并通过源码解析展示了如何构建一个强大的Coding Agent。对于想要深入理解和应用大模型的小白和程序员来说本文提供了宝贵的实践指导和参考。同一个 GPT 模型接进一个几十行的 Tool Call 脚本可能跑两步就迷路放进 Codex却能读仓库、改代码、跑测试、等待审批中断后再接着干。差别不只在 Prompt。Tool Call 循环决定模型下一步调用什么Harness 则要回答另一组更麻烦的问题上下文从哪里来命令在哪执行什么动作必须停下来问人中间进度怎么显示客户端断线后怎么恢复同一个 Agent 又如何同时进入 CLI、IDE 和桌面端Codex 最难复制的并不是中间那段“模型—工具—模型”循环而是把一次不稳定的模型运行收敛成可观察、可暂停、可恢复、可嵌入产品的工作系统。这篇不列功能清单。我们沿着源码把 Codex Core、App Server、Thread / Turn / Item以及双向审批链逐层拆开。Harness 不是多写一个 while 循环最小 Agent Loop 并不神秘。用户给出任务程序把指令、工具定义和输入送给模型。模型要么返回答案要么要求调用工具。程序执行工具把结果追加到上下文再次请求模型。如此反复直到模型不再发 Tool Call而是给出最终消息。这段 Loop 解决的是“下一步做什么”。生产级 Coding Agent 还要处理四类工作第一类是上下文。 除了用户消息还要装入系统指令、项目里的AGENTS.md、当前目录、可用 Skills、工具定义、历史消息和刚刚产生的文件差异。上下文接近窗口上限时还要压缩同时尽量不丢任务状态。第二类是执行。 Shell 命令、文件修改、MCP 工具不只是 JSON。它们会改变真实环境需要工作目录、超时、输出截断、权限、网络策略和失败处理。第三类是状态。 一个任务可能持续几分钟甚至几小时。用户会中途追问、改方向、暂停、恢复或从旧节点分叉。Agent 不能只记住最后一条聊天消息。第四类是产品交互。 CLI 想看流式日志IDE 想看 diff桌面端想同时管理多个任务业务系统还想把审批放进自己的界面。这些客户端不该各写一遍 Agent Loop。所以更准确的分层是模型层推理、生成消息或 Tool Call Agent Loop执行工具把结果送回模型 Harness上下文、状态、权限、持久化、扩展、事件与恢复 产品层CLI、IDE、桌面端、业务工作台Loop 是 Harness 的心跳但不是整副身体。Codex Core一个 Thread 的运行时OpenAI 把 Codex 的 Agent 逻辑放在 Rust 代码库的codex-core。官方把它描述成一套库也是一套可运行的 Thread Runtime。这里的 Thread 不等于“聊天记录”。它是一段仍然可以继续工作的会话有历史、有当前配置、有工具、有审批策略也有落盘位置。在我核对的固定提交343074d4里CodexThread包着一个Session、双向SessionIo、会话来源和 rollout path。源码给它的注释很直接这是组成一个 Codex Thread 的双向消息流通道。再往上一层是ThreadManager。它负责创建 Thread并把活跃的ThreadId映射到对应的CodexThread。但它管的远不止一张内存表共享状态里还有认证、模型目录、执行环境、Skills、Plugins、MCP、扩展注册和 Thread Store。这套结构透露出一个重要边界Thread 是 Agent 的运行单位ThreadManager 是运行时的资源总管。你点击“新任务”时不只是创建一个对话 ID。Harness 需要解析配置和工作目录装入项目指令确定模型与权限连接工具准备持久化然后才让模型看到第一条输入。恢复也不只是把聊天文本重新塞回去。Harness 还得重建这段历史对应的运行语义上次在哪个目录、哪些 Item 已经完成、Turn 是否被中断、后续输入应该接在哪里。这也是为什么“我把历史消息存进数据库了”还不等于支持 Agent 恢复。消息是证据的一部分运行状态才决定接下来能不能安全继续。Core 先组装运行环境再让模型思考很多人把 Codex 的输入理解成“用户 Prompt 加仓库代码”。实际送进第一次推理的内容更像一份现场交接包。官方对 Agent Loop 的拆解把 Responses API 请求归成三块instructions、tools和input。instructions决定模型要遵守的基础行为。tools描述这一轮可以调用的 Shell、计划工具、托管工具和 MCP 工具。input则不只有用户消息还会放入权限说明、用户自定义指令、项目AGENTS.md、Skills 元数据、当前目录和 Shell 等环境信息。顺序很重要。权限说明要让模型提前知道哪些目录可写、什么时候必须申请升级项目指令要让它知道这个仓库怎么测试、哪些文件不能碰环境信息要让它别在错误目录里运行命令。少一块模型可能依然会写代码却会在收尾时用错测试命令、漏掉仓库规则或者提出当前环境根本执行不了的动作。工具也不是一股脑塞进同一个执行器。Codex 内置的 Shell、Responses API 提供的托管工具、用户配置的 MCP 工具来源和安全边界不同。Harness 负责把它们整理成模型能理解的工具表再把 Tool Call 路由到对应执行路径。一轮里如果连续调用几十次工具上下文会持续增长。旧消息、命令输出和文件内容不能无限累积Core 还要在接近上下文窗口时做压缩。压缩不是简单删掉前半段聊天任务目标、已经完成的动作、关键文件、失败证据和待办状态都要尽量保留否则“上下文变短”会直接变成“Agent 忘了自己在干什么”。这里可以看出模型与 Harness 的分工模型负责在当前上下文里判断下一步Harness 负责决定它这一刻能看到什么、能调用什么以及历史以什么形态继续存在。App Server把同一套 Agent 从 TUI 里拆出来Codex 最初是终端里的 TUI。界面和 Agent Loop 在同一个进程里TUI 可以直接调用 Rust 类型开发速度很快。问题出现在 VS Code 插件。IDE 需要的不是一问一答。它要一边显示模型输出一边展示命令进度、文件差异和审批按钮用户还可能在工具执行期间补充输入。如果为 VS Code 重写一套 HarnessCLI 与 IDE 很快就会出现两种行为。App Server 就是在这个压力下长出来的。它是一项协议也是一段长期运行的进程。客户端启动 App Server通过默认的 stdio 通道发送一行一条的 JSON 消息App Server 托管 Codex Core Thread把内部事件翻译成稳定、适合 UI 消费的 JSON-RPC 消息。最初的官方架构图把它画成四部分1. 输入层读取客户端消息2. Message Processor分发请求转换内部事件3. Thread Manager创建和管理 Thread4. Core Threads分别运行各自的 Agent 会话。当前源码已经比这张图复杂得多。MessageProcessor下面拆出了 Thread、Turn、配置、文件系统、Git、MCP、插件、账号等多个 Request Processor。高层边界却没有变客户端说产品语言Core 说运行时语言App Server 负责翻译。Core 可以继续重构内部事件CLI、IDE、桌面端只要依赖稳定的协议原语不必追着每个 Rust 枚举一起改。反过来客户端可以把同一个 Item 渲染成终端日志、IDE diff 或桌面端时间线而不必干涉 Agent 怎么推理。App Server 为什么没有直接沿用 MCPOpenAI 最初确实试过把 Codex 暴露成 MCP Server后来放弃了这条路。原因不是 MCP 不好而是两套协议在解决不同方向的问题。MCP 更适合让 Agent 发现和调用外部能力工具、资源、Prompt 或交互组件。它回答“这个 Agent 能接哪些系统”。App Server 则要让一个产品完整承载 Agent创建 Thread、开始 Turn、流式展示 Item、发送 diff、处理中断、响应审批再把历史恢复出来。它回答“产品怎样控制这个 Agent 的一生”。两者的关系更像纵向与横向产品客户端 ↔ App Server ↔ Codex Core ↕ MCP 工具与数据IDE 通过 App Server 控制 CodexCodex 再通过 MCP 连接外部工具。把 App Server 和 MCP 当成二选一会把“嵌入 Agent”与“扩展 Agent”混成同一件事。这种差异在审批上尤其明显。MCP Tool Call 发生在 Agent 内部但批准按钮、风险解释和用户选择属于宿主产品。App Server 必须允许服务端反过来询问客户端并把当前 Turn 停在正确位置。普通的“调用一个 MCP Tool等它返回”表达不了完整的产品控制面。协议稳定不代表所有字段永远不变App Server 的公开协议仍在快速扩展。固定提交里既有稳定方法也有大量 experimental 字段。接入方如果直接对着源码抄 JSON很容易在升级二进制后踩到变化。官方提供了两条更稳的路。第一使用运行中的 App Server 生成 TypeScript 类型或 JSON Schema。生成物和当前二进制版本一致避免文档版本、客户端类型和服务端实现各走各的。第二本地客户端固定经过验证的 Codex 二进制版本。OpenAI 的 IDE 与桌面端不是每次启动都随便拉一个最新 Core而是让客户端与经过测试的 App Server 一起发布。协议能向前演进版本仍然要经过配套验证。连接初始化也承担一部分兼容工作。客户端会声明名称、版本和能力服务端根据是否启用实验 API、是否支持扩展、是否退订某类通知来调整输出。未知能力可以被忽略实验字段也可以被过滤。所以“有 JSON-RPC”并不自动等于稳定。协议的稳定来自四件事少量清楚的原语、显式能力协商、与二进制匹配的类型以及客户端愿意处理未知与失败。Thread、Turn、Item三种不同寿命的状态App Server 没有把整个过程压成一条巨大的“响应”。它选了三个不同寿命的原语。Thread 是容器。它包含多次用户输入可以创建、恢复、分叉和归档。一个 Thread 可以跨越多个 Turn持久化后客户端重连仍能重建时间线。Turn 是一次工作。用户说“跑测试并总结失败”就启动一个 Turn。这个 Turn 里可能发生十几次模型推理、Shell 命令和文件读取。它最终处于completed、interrupted、failed或inProgress之一。Item 是可展示的原子事件。用户消息、Agent 消息、命令执行、文件修改、MCP 调用、计划和推理都可以成为 Item。Item 有自己的 ID 和生命周期适合被增量更新、单独渲染和持久化。为什么要拆三层看一个具体场景就明白了。你让 Codex 修一个测试。任务还没结束IDE 已经需要显示Agent 开始分析、准备执行pytest、命令正在跑、出现两个失败、修改了三个文件、生成一段 diff、等待你批准下一条命令。如果后端只在最后返回一大段字符串客户端既不知道现在发生到哪一步也无法把审批按钮准确挂到那条命令上。Item 让中间动作有身份Turn 让一次工作有边界Thread 让多次工作能续上。这不是命名洁癖而是把 Agent 从“文本生成器”变成“可操作产品”的最小状态模型。一次用户输入为什么会变成事件流连接建立后客户端不能立刻发任务。它要先发送initialize带上客户端名称、版本和能力然后再发initialized通知。这个握手不只是打招呼。当前协议允许客户端声明自己理解哪些扩展、是否启用实验 API、想屏蔽哪些通知。App Server 因此知道该发什么也知道哪些字段必须过滤。接下来客户端用thread/start创建 Thread或者用thread/resume恢复旧 Thread。用户输入则通过turn/start进入指定 Thread。从这里开始一次请求会展开成一串通知turn/started item/started item/agentMessage/delta item/completed item/started # 命令执行 item/completed ... turn/completedstarted让界面先占住位置delta让文本或进度持续更新completed给出终态数据。客户端不需要等整个 Turn 结束才能知道 Agent 正在做什么。这里还有一个常被忽略的工程问题事件流也会堵车。固定提交的 App Server 在输入、请求处理和输出之间使用有界队列。入口过载时服务端会返回可重试错误慢客户端把输出队列塞满后连接可能被断开。这类代码不会出现在“十分钟搭 Agent”教程里却直接决定产品能否扛住多个长任务。流式不只是打字机动画它是一条需要背压、重试和断线策略的数据通道。为什么协议必须双向Agent 会停下来等你很多流式 API 只有一个方向客户端发请求服务端不断推 token。Coding Agent 不够用。模型准备运行一条高风险命令时Harness 可能需要向客户端发起审批。文件修改、命令执行、MCP 工具补充输入都可能由服务端主动提出请求。协议里对应的名字很直白item/commandExecution/requestApproval item/fileChange/requestApproval item/tool/requestUserInput客户端收到请求后可以弹出对话框、展示命令和原因再把允许或拒绝返回给 App Server。回复到达之前相关动作会停住。而且审批不只是“允许 / 拒绝”两个按钮。固定提交里的命令审批还区分仅允许这一次、在当前 Session 内允许同类动作、接受一条执行策略修订、拒绝但让 Turn 继续以及拒绝并立刻中断 Turn。这些选项对应的产品后果不同。一次性允许最保守但重复命令会不断打断用户Session 级允许降低摩擦却不能悄悄扩大到以后所有任务策略修订适合把明确规则沉淀下来“拒绝后继续”和“拒绝并取消”则决定 Agent 是换一条路还是立即交还控制权。如果客户端把它们全部压成一个布尔值Harness 虽然支持细粒度决策用户最后看到的仍是粗糙的安全体验。这条链路把三个角色分开了模型提出“我想做什么”Harness 判断“是否触发策略”客户端决定“怎样向用户呈现并收回选择”。我的判断是双向协议是 App Server 与普通 SDK 封装最重要的分水岭。它不是把 Codex API 换成 JSON-RPC而是把“Agent 需要人类参与”的时刻做成了一等公民。同时要守住安全边界。Codex 的 sandbox policy 和 approval policy 可以随 Thread 或 Turn 配置Harness 也能把审批稳定地送到客户端。但这不等于所有工具自动进入同一个操作系统沙箱。OpenAI 的 Agent Loop 文章明确说明Codex 提供的 Shell 受它自己的沙箱约束MCP 工具并不会因此自动被套住必须执行各自的 guardrail。一个能调用生产数据库的 MCP Server不能因为前面挂了 App Server 就被当成安全。Harness 统一的是控制流和策略接口。实际隔离仍要落到每种工具、凭证和运行环境上。再往前一步Thread 与 Turn 的权限也不是完全固定。当前协议允许在创建 Thread 时设置工作目录、模型、sandbox 和 approval policy也允许turn/start对后续工作覆盖一部分设置。这带来灵活性也带来审计要求同一 Thread 前后两次 Turn 可能处于不同权限配置。客户端不能只在任务开头显示一次“已启用沙箱”然后默认后面永远不变。权限变化本身应该进入可观察状态审批还要绑定当时真实生效的策略。App Server 不是所有场景的答案App Server 给了产品团队最大的生命周期控制也要求接入方承担更多工作启动和管理长期进程、维护连接、重建事件、处理审批、应对版本和背压。官方现在给出的选择很清楚。脚本、CI、一次性后台任务用codex exec。任务有明确入口和终点拿结构化输出就够了不必维护长期会话。应用代码需要启动、恢复或流式读取任务优先看 Codex SDK。SDK 把常见的程序化工作流包得更直接。Agent 本身就是产品体验的一部分再用 App Server。比如 IDE、SRE 控制台、安全调查台需要持久 Thread、中间事件、用户中断和审批 UI这些才是 App Server 的主场。宿主应用也不能把责任全部交给 Harness。OpenAI 的示例把边界画得很实在应用拥有业务界面、业务上下文、MCP 数据与动作、关键操作的同意流程Codex 提供 Agent Loop、会话状态、流式活动和工具交互。复用 Harness不等于把产品判断外包。自建 Coding Agent先过这八道检查如果你正在搭自己的 Harness不要只看“模型能不能调用 Shell”。先拿这份清单过一遍。Thread 能恢复、分叉和归档吗只有一份 messages 数组不足以恢复目录、配置、中断点和工具状态。Turn 有明确终态吗完成、中断、失败和仍在运行必须分开。否则客户端无法判断该重试、续跑还是交还用户。Item 有生命周期吗命令、diff、审批和 Agent 消息需要独立 ID以及 started、delta、completed 之类的边界。工具动作能被观察吗至少要知道调用了什么、输入来自哪里、结果是什么、失败发生在哪一步。高风险动作能暂停吗“运行前打印一句日志”不算审批。系统必须真的停住等待外部决定并把决定绑定到正确的动作。权限是不是分层治理Shell 沙箱、网络访问、MCP 凭证、文件修改和业务写操作不是同一件事。协议能演进吗初始化、能力协商、版本、实验字段、背压和重试至少要有明确策略。断线和重启后怎么办客户端慢消费、进程退出、机器重启都不该让系统凭空猜测任务是否完成。八项里缺一两项Demo 依然能跑。缺得多了长任务越成功积累的不可控状态反而越多。最后的判断模型能力还会继续涨Agent Loop 也会越来越短。但 Thread、工具、权限、审批、事件和恢复不会自动消失。Codex Harness 值得研究不是因为它给出了一套必须照抄的唯一架构而是它把 Coding Agent 最容易被低估的工程层公开了出来Codex Core 负责让一个 Thread 活着App Server 负责让不同客户端看懂、控制并继续这段工作。下次评估一个 Coding Agent别只问它接了什么模型、榜单多少分。把上面的八项检查表拿出来逐项写下现有证据和缺口再看它在任务跑到第 30 分钟、等待审批、客户端断线之后还剩多少工程确定性。如果你正在自建 Agent Runtime建议把这篇先收藏。后面我会继续拆 App Server 的协议接入从initialize开始跑通一个最小客户端再实测 Thread 恢复、事件流和审批回路。如何学习大模型 AI 由于新岗位的生产效率要优于被取代岗位的生产效率所以实际上整个社会的生产效率是提升的。但是具体到个人只能说是“最先掌握AI的人将会比较晚掌握AI的人有竞争优势”。这句话放在计算机、互联网、移动互联网的开局时期都是一样的道理。我在一线科技企业深耕十二载见证过太多因技术卡位而跃迁的案例。那些率先拥抱 AI 的同事早已在效率与薪资上形成代际优势我意识到有很多经验和知识值得分享给大家也可以通过我们的能力和经验解答大家在大模型的学习中的很多困惑。我们整理出这套AI 大模型突围资料包✅ 从零到一的 AI 学习路径图✅ 大模型调优实战手册附医疗/金融等大厂真实案例✅ 百度/阿里专家闭门录播课✅ 大模型当下最新行业报告✅ 真实大厂面试真题✅ 2026 最新岗位需求图谱所有资料 ⚡️ 朋友们如果有需要《AI大模型入门进阶学习资源包》下方扫码获取~① 全套AI大模型应用开发视频教程包含提示工程、RAG、LangChain、Agent、模型微调与部署、DeepSeek等技术点② 大模型系统化学习路线作为学习AI大模型技术的新手方向至关重要。 正确的学习路线可以为你节省时间少走弯路方向不对努力白费。这里我给大家准备了一份最科学最系统的学习成长路线图和学习规划带你从零基础入门到精通③ 大模型学习书籍文档学习AI大模型离不开书籍文档我精选了一系列大模型技术的书籍和学习文档电子版它们由领域内的顶尖专家撰写内容全面、深入、详尽为你学习大模型提供坚实的理论基础。④ AI大模型最新行业报告2025最新行业报告针对不同行业的现状、趋势、问题、机会等进行系统地调研和评估以了解哪些行业更适合引入大模型的技术和应用以及在哪些方面可以发挥大模型的优势。⑤ 大模型项目实战配套源码学以致用在项目实战中检验和巩固你所学到的知识同时为你找工作就业和职业发展打下坚实的基础。⑥ 大模型大厂面试真题面试不仅是技术的较量更需要充分的准备。在你已经掌握了大模型技术之后就需要开始准备面试我精心整理了一份大模型面试题库涵盖当前面试中可能遇到的各种技术问题让你在面试中游刃有余。以上资料如何领取为什么大家都在学大模型最近科技巨头英特尔宣布裁员2万人传统岗位不断缩减但AI相关技术岗疯狂扩招有3-5年经验大厂薪资就能给到50K*20薪不出1年“有AI项目经验”将成为投递简历的门槛。风口之下与其像“温水煮青蛙”一样坐等被行业淘汰不如先人一步掌握AI大模型原理应用技术项目实操经验“顺风”翻盘这些资料真的有用吗这份资料由我和鲁为民博士(北京清华大学学士和美国加州理工学院博士)共同整理现任上海殷泊信息科技CEO其创立的MoPaaS云平台获Forrester全球’强劲表现者’认证服务航天科工、国家电网等1000企业以第一作者在IEEE Transactions发表论文50篇获NASA JPL火星探测系统强化学习专利等35项中美专利。本套AI大模型课程由清华大学-加州理工双料博士、吴文俊人工智能奖得主鲁为民教授领衔研发。资料内容涵盖了从入门到进阶的各类视频教程和实战项目无论你是小白还是有些技术基础的技术人员这份资料都绝对能帮助你提升薪资待遇转行大模型岗位。以上全套大模型资料如何领取