先给结论:Agents API 把循环托管了,没有把合同托管。2026 年 9 月 10 日,OpenAI 把驱动 Codex 的 Agent Harness 以 public beta 交给开发者。模型调度、上下文压缩、子 Agent、沙箱生命周期,都从你的进程挪到了 beta.agents.sessions。你还握在手里的,几乎全是 JSON:function 工具的 JSON Schema、arguments、tool_result 的字符串、MCP 的 inputSchema、session 事件流。Harness 替你跑 loop,不等于替你校验字段。合同松了,托管循环只会把坏参数跑得更勤。
这篇按 2026 年 9 月 18 日写。本站已有《Agent 为什么离不开 JSON》《Tool Calling 为什么依赖 JSON Schema》《JSON Schema 会成为标准 Contract 吗》《MCP / Skills / Tools / Subagents》《MCP 是什么》。本文只回答:Agents API 发布之后,JSON 为什么更重要,而不是更不重要。
9 月 10 日到底发布了什么
OpenAI 的原话是:用驱动 Codex 的同一套 harness 和基础设施,给开发者一个托管的云端 Agent。公开文档把它放在 beta.agents 命名空间,请求要带 OpenAI-Beta: agents=v1。Harness 本身不另收费,你付的是模型 token、工具和沙箱时间。
一次 session 创建里,你提交的是一份 JSON:模型、指令、工具列表、环境、输入。官方示例用 gpt-6-astra,工具可以是 MCP、自定义 function、内置检索。环境可以是 none、openai_hosted,或接到 Blaxel、Cloudflare、Daytona、E2B、Modal、Vercel 这类自建 / 合作沙箱。多 Agent 用 multi_agent.enabled 和 max_concurrent_subagents 打开。
它不是又一个「请输出 JSON」的聊天接口。Responses API 还在;Agents SDK 还在。Agents API 收走的是循环本身:谁决定下一跳、何时压缩上下文、何时派子 Agent。公测期字段名仍可能改,但分层已经清楚:OpenAI 跑 harness,你提供工具合同和业务结果。
三套入口:Responses、Agents SDK、Agents API
2026 年 9 月,OpenAI 并排放着三条做 Agent 的路。混用之前先分清「循环跑在哪」:
| 入口 | 循环跑在哪 | 状态存在哪 | 你还写什么 |
|---|---|---|---|
| Responses API | 你的应用 | 你自己拼 history / Conversations | 模型调用、工具回灌、整段 loop |
| Agents SDK | 你的进程 | SDK session + 你的存储 | 审批、部署、仍可改 loop |
| Agents API | OpenAI 托管的 Codex harness | 服务端 session / turn / item | 工具定义、function 结果、环境选择;改不了 loop |
单次补全继续用 Responses。要自己握审批和落盘,用 SDK。要把「跑几天的任务、压缩、子 Agent、沙箱」交给对方,用 Agents API。三条路的工具参数都还是 JSON Schema。差别是:前两条你还能在 loop 里加补丁;第三条补丁只能加在合同和回灌上。
Agent Harness 是什么,它不替你签什么
Harness 是夹在模型和副作用之间的运行时:读事件、选工具、喂结果、压缩上下文、在超长任务里保住进度。Codex 那一套现在开源可见,Agents API 则由 OpenAI 运维同一套逻辑,并随模型版本升级。公告里点名的能力包括自动 compaction、Tool search、Programmatic Tool Calling、并行 subagents。
它不签这几样东西:
- 某个
customer_id该不该存在、该不该是 UUID; - 你的函数该不该接受多余键;
- MCP Server 的
inputSchema松还是紧; - 回灌给模型的
output是对象、字符串,还是一段聊天。
这些仍然是 JSON Schema 和你自己的二次校验。托管 harness 提高的是「循环能跑多久、能并行多少」;它不提高「这一跳参数是否合法」。把两者当成一回事,是这篇要拆开的第一层误会。
为什么托管之后 JSON 跳数反而更多
自己写 loop 时,坏 JSON 往往死在你这一侧:parse 失败、字段对不上,你就停。循环托管之后,失败被推迟、被复制、被送进更多通道:
| 跳 | 载体 | 谁生成 | 谁必须校验 |
|---|---|---|---|
| 创建 session | agent / tools / environment JSON | 你的应用 | 你:提交前 |
| function 定义 | JSON Schema(parameters) | 你的应用 | 你:收紧 required / additionalProperties |
| 模型发起调用 | arguments 对象 | 托管 harness + 模型 | 你:执行前再验一遍 |
| 回灌结果 | tool_result.output 字符串 | 你的应用 | 你:先 stringify 合法值 |
| MCP | JSON-RPC + inputSchema | Server / harness | Server 与你的允许列表 |
| 事件流 | agent.session.* JSON 事件 | 托管服务 | 你:按 type 分支,不要当聊天正文 parse |
再加上 Tool search 按需加载定义、Programmatic Tool Calling 在代码里串并行调用、subagent 各自带一份上下文——一次用户任务里的 JSON 往返,比「单次 Function Calling」多一截。托管让这些跳对你不可见,不可见不等于可以不校验。数据流的逐跳拆解见《从 Tool Calling 到 MCP》。
Tool Calling:function 工具仍是 JSON Schema
Agents API 的 function 工具和 Responses API 用同一套定义。你交给 agent.tools 的不是一段自然语言,而是名字、说明、一份 JSON Schema:
{
"type": "function",
"name": "get_customer",
"description": "Look up a customer by ID.",
"parameters": {
"type": "object",
"properties": { "customer_id": { "type": "string" } },
"required": ["customer_id"],
"additionalProperties": false
}
}
官方示例把 required 写满,并把 additionalProperties 设为 false。这不是排版习惯。Agent 一旦被允许多写一个键,那个键就可能变成路径、SQL 片段或「顺便删除」。Schema 是模型在解码时看到的合同,也是你在执行前应再跑一遍的合同。严格模式、ajv、二次校验的流水线见《Tool Calling 为什么依赖 JSON Schema》。
描述字段仍然有用,它帮模型选工具;它不能代替类型、枚举和必填。Harness 越聪明,越会在一堆工具里挑一个「差不多」的——差不多的调用,只能靠 Schema 挡下来。
requires_action 与 tool_result:回灌也是 JSON
模型要跑你的函数时,session 停在 agent.session.requires_action。待处理项在 required_actions 里,而不是「历史里有一条 function_call」就算数。一条典型的 pending 调用是:
{
"type": "function_call",
"turn_id": "turn_123",
"call_id": "call_123",
"name": "get_customer",
"arguments": { "customer_id": "123" }
}
文档把 arguments 写成对象。不要把它再包进聊天回复里用 JSON.parse 抠——那是上一篇《JSON.parse 为什么失败》的通道错误。你要做的是:用同一份 Schema 校验这个对象,执行函数,然后往 session 事件接口回 agent.session.input.tool_result,带上原来的 turn_id / call_id。
成功时 success: true,output 是字符串或受支持的内容数组。对象要先 JSON.stringify。失败时 success: false,给模型一段能读的 error。不要把堆栈、密钥、整份数据库行回灌回去。进程若在执行后、回灌前崩溃,应按 session / turn / call 做幂等:重启后先读 pending,再决定是否重跑。
Function 始终在你的应用里跑,即使 session 带了沙箱。Harness 不会替你执行 get_customer。你不在线,这一跳就挂起。这是托管循环里,少数仍然完全属于你的同步点——也是你必须把 JSON 做对的那一跳。
Tool search 与 Programmatic Tool Calling
工具一多,把全部 Schema 塞进上下文会烧 token、打缓存。Agents API 默认急切加载 function;不常用的可以 defer_loading: true,并在 agent.tools 里放 {"type": "tool_search"}。模型先搜到相关定义,再调用。于是多出一跳「定义本身也是 JSON」:搜到的 Schema 必须和你真正实现的函数一致,不能搜到一份宽合同、执行一份窄实现。
Programmatic Tool Calling 让受支持的模型写一小段代码,并行或串联合格工具,再只把过滤后的结果带回上下文。这降低了「每一跳都占满窗口」的成本,提高了「中间 JSON 必须合法」的要求。中间结果若类型漂移,后面的过滤和合并会在你看不见的 harness 里静默错下去。SDK 一侧已经出现「把结构化错误编码成 JSON」的修补,说明这条路径吃的就是 Schema,不是散文。
MCP 与 Subagents:更多 Schema,更多 JSON
把 MCP Server 写进 agent.tools,harness 负责发现工具、发起调用、把结果喂回模型。和 function 不同:这些调用不经过你的应用。HTTP 默认由 OpenAI 连;也可以指定从环境连,或在沙箱里用 stdio 拉起进程。你在这一层能做的,是 allowed_tools、初始化失败是否让 turn 失败(required: true),以及 Server 自己的 inputSchema 有多紧。
MCP 的报文仍是 JSON-RPC。Schema 松,托管 harness 会替模型打出更多你看不到的请求。这不是「协议帮你安全了」,是「循环离你更远了」。协议分层见《MCP 是什么》;和 Skills、Subagents 的边界见《2026 Agent 栈》。
Subagents 各自一份上下文,主 Agent 汇总。并行能降延迟,也会并行打出多份 arguments。主 Agent 拿到的汇总若仍是无 Schema 的长文本,你只是把「解析聊天」推迟到了最后一跳。要进程序的结论,最终答复仍应走 Structured Output 或一份你定义的结果 Schema,而不是再从散文里抠。见《Structured Output 是什么》。
你还要在本地校验的四件事
Harness 托管之后,清单不是变短,是变窄:
- 工具 Schema。
required写满,additionalProperties: false,枚举收紧。不要靠描述词拦副作用。 - 执行前的 arguments。厂商说过 Schema,仍要在你的进程里用同一份再验。类型错、缺字段、多出来的键,这一层拦。
- 回灌的 output。先做成合法 JSON 再
stringify。错误走success: false,不要把内部异常原文丢给模型。 - 事件与聊天正文分通道。读
event.type,不要把整段 SSE 当 JSON 值。最终对用户的结构化答复,用 Structured Output,不要JSON.parse助手句子。
安全一侧还要记得:arguments 里的字符串可能是注入,不是「类型对了就执行」。见《恶意 JSON 与 Prompt Injection》。JSON Schema 会不会成为跨厂商合同,见《标准 Contract》——Agents API 没有削弱这个判断,它把它推到了你唯一还能改的那一层。
用本地 JSON 工具看合同
接到托管 session 之前,先在浏览器里看三份文本:工具 Schema、一条样本 arguments、你准备回灌的 output。
- JSON 校验 — 文法是否合法;有 Schema 就一起核字段、必填、多余键。
- JSON 格式化 — 把压成一行的
tool_result展开,看你是不是把整行数据库序列化回去了。 - JSON Diff — 对比「模型传来的 arguments」和「Schema 允许的最小对象」。
数据不离开浏览器。适合把一份失败的 required_actions、一份 parameters、一次 stringify 后的结果放在一起看。合同稳定了,再交给 hosted harness 去跑几天。
常见问题 FAQ
Agents API 是不是让我不用再写 JSON Schema 了?
正好相反。循环被托管之后,Schema 是你还握着的主合同。function 的 parameters、MCP 的 inputSchema、回灌的 output,都还是 JSON。
Agents API、Agents SDK、Responses API 该怎么选?
单次调用用 Responses。要自己握 loop、审批和存储,用 SDK。要把长任务、压缩、子 Agent、沙箱交给 OpenAI,用 Agents API。三条路的工具参数都是 JSON Schema。
arguments 已经是对象,还要不要 JSON.parse?
不要把整段聊天再 parse 一遍。按文档把它当对象,用同一份 JSON Schema 校验。从散文里抠 arguments,是通道用错了。
tool_result 为什么必须 stringify?
文档要求 output 是字符串或受支持的内容数组。对象先做成合法 JSON 再 stringify,避免二次编码和「看起来像对象、其实是字符串」混用。
MCP 工具会经过我的应用吗?
默认不会。harness 直连 Server。你要收紧的是 Server 自己的 inputSchema、allowed_tools,以及不可逆操作在 Server 内的审批。
公测期字段会不会改?
会。这篇按 2026 年 9 月 18 日的公开文档写。分层不会改:harness 跑循环,你提供 JSON 合同。字段名变了,校验责任还在你这边。
总结
Agents API 降低的是「如何跑完一个 Agent」的工程量,提高的是「每一跳 JSON 必须正确」的权重。9 月 10 日交出的是 Codex harness:session、压缩、工具搜索、程序化调用、子 Agent、沙箱。它不检查你的 customer_id 该长什么样,也不替你把 tool_result 编成合法字符串。
2026 年把 Agent 接到程序,顺序没有变:工具走 JSON Schema,结果走 Structured Output,聊天正文不要当 API。变的是,loop 一旦托管,你能打补丁的地方只剩合同。先在本地校验工具里看 Schema、arguments 和回灌结果,再交给 hosted session 去跑。模型会换,harness 会改版本;你的字段合同不应跟着一起松。