2026 年 9 月 10 日,OpenAI 把驱动 Codex 的那套「harness」(智能体调度框架)挂上了 API:Agents API 进入公开测试。值得关注的地方不是模型,而是那层过去每个团队都要自己写一遍的东西——上下文管理、工具调度、子智能体协调,以及能让 Agent 连续跑上几天的运行基础设施。这篇教程带你从零跑通一个托管云 Agent,并把容易踩的坑一次讲清。
先理解:Agents API 托管了什么
官方公告里有一段话值得抄下来:有用的 Agent 需要一个强大的 harness 来管理上下文、高效使用工具并协调子智能体;还需要能让它连续可靠运行数天的基础设施,以及可以处理文件、运行代码、保存中间结果的环境。过去这三件事全由调用方自己承担,Agents API 把它们收归平台侧。
整个 API 被拆成四个概念,先把名词对上号:
| 概念 | 含义 | 你要关心什么 |
|---|---|---|
| Agent | 模型、指令、工具、MCP 服务器的组合 | 写清楚 instructions,它决定 Agent 的行为边界 |
| Environment | 代码在哪里跑(托管沙箱 / 自托管 / 合作方沙箱) | 决定网络策略、可用依赖与产物留存 |
| Session | 跨任务的持久会话 | 保存 session_id,才能做多轮跟进 |
| Events / items | 会话中的输入输出事件流 | 判断「这一轮到底成没成」的核心依据 |
核心接口只有一个:向 POST /v1/agents/sessions 发请求,带上 Beta 请求头,剩下的由平台接管。它和已经淡出的 Assistants API 不是一回事,是另起的新服务,并会跟随模型发布节奏一起版本化。
Step 1:准备一个「够权限、但不进沙箱」的密钥
Agents API 用的不是普通用户密钥,而是 OpenAI 平台项目里的 application API key。官方文档列出的权限有三项,缺一项就会在创建会话时报权限错误:
# 需要的权限范围
api.agents.read # 读取 agent / 会话
api.agents.write # 创建与操作会话(session operations)
api.responses.write # 模型推理(model inference)
# 导出到环境变量
export OPENAI_API_KEY="your-api-key"
密钥必须保存在 Agent 沙箱之外。这是官方文档明确写出的安全要求。原因很直接:沙箱里跑的是模型生成的代码,一旦密钥被读走,等于把账号交给了不可信代码。正确做法是密钥只存在于你的服务端进程环境变量里,由平台侧在出站请求时注入,而不是写进沙箱的文件系统。
Step 2:跑通一个最小会话
先装新版 SDK。Python 端只要一条命令,注意要用 --upgrade,因为 beta.agents 命名空间是新增的:
pip install --upgrade openai
# 验证版本里有 beta.agents
python -c "from openai import OpenAI; c=OpenAI(); print(hasattr(c.beta, 'agents'))"
新建 quickstart.py。这段代码会创建一个会话,让 Agent 在沙箱里写出 tree.py、执行它,并把真实输出回报:
from openai import OpenAI
with OpenAI() as client:
with client.beta.agents.sessions.create(
agent={
"model": "gpt-6-astra",
"instructions": "Write clean code, run it, and report the actual output.",
},
environment={"type": "openai_hosted"},
input="Create tree.py, a Python script that prints a readable tree of the "
"files in the current directory. Run it and show me the output.",
stream=True,
) as events:
for event in events:
# 原样打印事件,先看清协议长什么样
print(event.to_json(indent=None), flush=True)
运行 python quickstart.py。如果不想装 SDK,也可以用 cURL 直接打接口,此时 必须手动带上 Beta 请求头,SDK 会自动加:
curl --no-buffer --fail-with-body https://api.openai.com/v1/agents/sessions \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"agent": {
"model": "gpt-6-astra",
"instructions": "Write clean code, run it, and report the actual output."
},
"environment": { "type": "openai_hosted" },
"input": "Create tree.py, a Python script that prints a readable tree of the files in the current directory. Run it and show me the output.",
"stream": true
}'
instructions 写成「写出干净代码、运行它、回报真实输出」这类可验证的表述,比写「你是一个专业助手」有效得多——它直接约束了 Agent 不许编造执行结果。Step 3:读懂事件流,判断「到底成没成」
这是本篇最容易被忽略、却最容易在生产里翻车的一节。官方文档专门提醒:「回合完成」不等于「所有工具都成功」。需要区分的事件类型如下:
| 事件 | 含义 | 能不能当作成功 |
|---|---|---|
agent.session.turn.completed | 一个回合结束 | 不能单独当成功,必须再看 Agent 回报的执行结果 |
agent.session.idle | 会话空闲 | 单独出现不代表成功 |
agent.session.turn.failed | 回合失败 | 失败 |
agent.session.turn.cancelled | 回合被取消 | 失败 |
agent.session.failed | 会话失败 | 失败 |
把判断逻辑写成代码,而不是靠肉眼看日志:
OK = "agent.session.turn.completed"
BAD = ("agent.session.turn.failed",
"agent.session.turn.cancelled",
"agent.session.failed")
def consume(events):
turn_done = False
for event in events:
name = event.type
if name in BAD:
raise RuntimeError("会话异常结束: %s" % name)
if name == OK:
turn_done = True
# 关键:completed 之后仍要校验业务结果
return turn_done
三个高频误判:① 看到 idle 就以为跑完了;② 看到 turn.completed 就跳过结果校验;③ 流提前断开时直接重试。第三种尤其危险——官方要求先检索会话及其保存的条目,再决定是否重试,否则可能重复执行已经生效的写操作。
Step 4:多轮跟进与会话恢复
会话是有状态的。把事件里的 session_id 存下来,就能在同一上下文里继续下一条指令,例如「给 tree.py 加一个最大深度参数,运行并展示输出」。
# 1) 从事件中保存 session_id
session_id = None
for event in events:
sid = getattr(event, "session_id", None)
if sid:
session_id = sid
# 2) 继续会话:先打开事件流,再发送跟进输入
with client.beta.agents.sessions.continue_( # 具体方法名以官方文档为准
session_id,
input="Add a maximum-depth option to tree.py, run it, and show me the output.",
stream=True,
) as events:
for event in events:
print(event.to_json(indent=None), flush=True)
Step 5:换执行环境——托管、自托管与第三方沙箱
environment 决定代码在哪跑。托管沙箱开箱即用,自托管适合已有基础设施的团队,第三方沙箱则在 GPU、冷启动、长会话等维度各有取舍。官方列出的沙箱合作方包括 Blaxel、Cloudflare、Daytona、DigitalOcean、E2B、Modal、Oracle、Runloop、Vercel。
| 环境类型 | 适用场景 | 要额外确认的事 |
|---|---|---|
openai_hosted | 快速验证、不想管基础设施 | 依赖包与网络访问策略、产物如何下载 |
| 自托管沙箱 | 数据不出自有网络、已有 K8s 或云主机 | 网络出口、鉴权、会话保活 |
| 合作方沙箱 | 需要 GPU、需要更短的冷启动、需要超长会话 | 计费模型、快照与持久化能力 |
换环境不等于换一个参数就完事。沙箱的网络策略、可用依赖、文件留存方式都会变。上线前建议用同一个任务在三类环境各跑一遍,对比成功率与耗时,而不是只看报价。
Step 6:子智能体与多智能体并行
Agents API 内置了子智能体能力:打开多智能体模式后,复杂任务会被拆成若干独立片段并行处理,每个子智能体维护自己的上下文以保持专注,主智能体负责协调与汇总。并发子智能体数量可以设上限,避免一次开太多把预算烧穿。
agent={
"model": "gpt-6-astra",
"instructions": "Coordinate subagents and merge their findings into one report.",
# 多智能体开关与并发上限(字段名以官方 multi-agent 指南为准)
"multi_agent": {"enabled": True, "max_concurrent_subagents": 3},
}
harness 里另外两个和成本直接相关的机制也值得知道:上下文压缩——会话接近上限时自动压缩早先的上下文,保留继续干活必需的信息,开发者不用自己写摘要逻辑;工具搜索——按需加载工具定义,而不是一次性全塞进提示词,既省 token 又保住模型缓存。
Step 7:收尾与清理
会话可以保留继续用,也可以删掉。删除接口很简单:
result = client.beta.agents.sessions.delete("sess_123")
print(result.to_json())
# 或直接用 cURL
curl -X DELETE "https://api.openai.com/v1/agents/sessions/sess_123" \
-H "OpenAI-Beta: agents=v1" \
-H "Authorization: Bearer $OPENAI_API_KEY"
删除前务必先把需要的文件保存出来。官方文档特别提示了这一点。Agent 在沙箱里生成的代码、报告、中间产物都属于会话的一部分,会话删掉就一起没了。生产环境建议把产物下载动作写进流程,而不是依赖人工记得。
常见问题 FAQ
Q1:Agents API 怎么计费?
使用 Agents API 本身不收取额外费用,你只为智能体实际消耗的 token 和工具付费。这一点对做成本预估很关键:省下的是自建 harness 的工程成本,而不是模型调用成本。
Q2:它和 Assistants API 是什么关系?
不是同一个服务的升级版。Agents API 是另起的新服务,底层基于开源的 Codex harness,并跟随模型发布节奏一起版本化。老的 Assistants API 已经淡出,新项目建议直接用 Agents API。
Q3:能不能用自己写的工具和 MCP 服务器?
可以。Agent 定义里除了模型与指令,还能挂工具与 MCP 服务器;官方示例里也有把工具类型指向 MCP 端点的写法。具体字段结构请以官方配置指南为准。
Q4:Agent 跑出来的结果能审计吗?
会话以事件流形式输出,每一步的输入输出都能落盘。建议把事件流按 session 归档到对象存储或日志系统,出问题时可以沿着链路回看是哪一步偏了,而不是只看最终答案。
Q5:本地开发能省钱吗?
可以先在本地把 prompt、指令和工具描述打磨好,再上托管环境跑完整任务。真正花时间的往往是指令措辞与工具边界,而不是跑一次会话。目前官方及行业暂未披露更多细节,后续将持续跟进迭代动态。