ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

OpenAI Agents API:一次调用,云端跑起 Codex 同款智能体

OpenAI Agents API:一次调用,云端跑起 Codex 同款智能体 第一次看到“OpenAI 推出 Agents API一次调用在云端跑起 Codex 同款 Agent”这条消息时我的第一反应是OpenAI 终于把 Agent 的“脏活累活”接到自己服务器上去了。过去我们聊 AI Agent大多还在用 Chat Completions 自己维护上下文、自己写工具调用循环、自己处理重试和中断代码没少写效果还不一定稳。Agents API 给了一个更接近“任务提交”的抽象你把任务丢上去云端一个类似 Codex 的智能体自动规划、调用工具、迭代、出结果。这篇文章我就从一个实际开发者的角度拆解它是什么、怎么用、有哪些坑给想上手的人一条能直接抄的路径。如果你只是拿大模型做聊天、做文本翻译Chat Completions 已经完全够用了。但一旦任务变成“帮我把这个仓库的代码过一遍找到潜在的 bug并且改出补丁”事情就复杂了。你得先让模型理解任务再让模型决定先去读哪个文件、读完后如何修改、修改后如何验证。这个流程不会在一次请求里结束而是模型和外部环境反复交换信息直到达成目标。传统做法是你自己写一个 while 循环在每次迭代里调用模型、把工具结果拼回去、再让模型继续。Agents API 想省掉的正是这段手工循环。1. Agents API 到底是干嘛的把 Agent 的“脏活”接到云端1.1 从“聊天接口”到“任务接口”一次调用的意义OpenAI 之前给开发者提供的大多是“模型接口”你输入一句话它输出一句话。即便是带工具调用的 Chat Completions模型也只是在某一次回复里告诉你“我想调用某个函数”真正调用函数、把函数结果返回给模型、再决定下一步做什么全部要你手工控制。这意味着你要自己维护一个状态机自己管理上下文长度自己处理各种中途异常。项目小还好一旦任务链条拉长代码复杂度会直线上升。Agents API 的思路是把“任务”作为一等公民。你不再频繁请求模型而是创建一个 Agent告诉它系统指令、可用工具和最终目标然后提交一次 run云端会自己去跑完整个“思考—行动—观察—再思考”的循环。你可能在代码里只写了十几行但服务器上替你完成了几十次模型调用和工具调用。这种设计很像提交一个异步任务提交后你可以去干别的等结果通知过来再处理。有人问我这跟多轮聊天有什么区别区别在于控制权。多轮聊天每一轮都由用户触发Agent 任务则是智能体自己决定什么时候该继续什么时候该停下来。你要的是“把某件事办成”而不是“回答某个问题”。Agents API 这个“任务接口”的价值就在这它把目标与执行分开了。1.2 Codex 同款 Agent 意味着什么Codex 是 OpenAI 的编程智能体它的特点不是“能写代码”而是能像个初级工程师一样在一个工作环境里持续工作读文件、改文件、跑命令、看结果、根据报错继续调整。你想想这背后需要多少个步骤理解项目结构、定位相关代码、生成修改、执行测试、阅读测试输出、修复新问题。如果每一步都靠客户端脚本编排那这个脚本会非常庞大。Agents API 说“在云端跑起 Codex 同款 Agent”我理解有两层意思。第一层你不需要自己部署一套复杂的 Agent 运行环境OpenAI 在云端已经帮你准备好了。第二层Codex 身上那套“工具调用 长任务执行 循环迭代”的能力被抽象成了 API 能力你可以用代码创建自己的智能体并让它拥有接近 Codex 的干活方式。你甚至可以把你自己的私有工具接进去让这个云端智能体调用你的内部系统。这对开发者来说是个很重要的信号以前我们总把 Agent 当成实验室玩具因为要自己处理太多细节现在它变成了一个可以认真做产品的 API。任务循环、会话状态、工具执行这些东西如果是自己搭光稳定运行就得写几千行代码。而 Agents API 把它变成了一个调用省下的是真正的工程时间。2. 核心概念与架构云端 Agent 是怎么跑的2.1 四个核心对象Agent、Run、Thread、Tool我把 Agents API 涉及的核心概念归纳为四个Agent、Run、Thread、Tool。一个 Agent 是“一个具备身份和指令的智能体”它定义了模型类型、系统提示词、可用的工具、输出风格等信息。你可以把它理解成一个员工有岗位说明书有能用的工具清单有该遵守的行为规范。Run 是“一次任务执行”你给 Agent 提交一个任务就会产生一个 RunRun 从排队、执行到完成有完整的生命周期状态。Thread 是“一段会话上下文”。同一个 Agent 可以服务多个用户多个任务可能需要共享历史记忆这时候用 Thread 把消息串起来。Tool 是“Agent 可以调用的外部能力”。它可以是 OpenAI 内置的工具比如代码解释器、网页搜索也可以是你自己定义的函数。四个对象的关系我习惯这么记Agent 负责“你是谁”Thread 负责“你记得什么”Tool 负责“你能用什么”Run 负责“你现在要做什么”。对象作用类比Agent定义智能体的模型、指令、工具员工Thread保存会话历史和上下文聊天记录Run提交并执行一次具体任务一次工作指派Tool智能体可以调用的外部功能手中的工具这四样东西分开理解都容易难的是组合。实际项目中你会创建多个 Agent各自有不同的职能同一个 Agent 可能同时跑很多 Run一个 Run 中可能会调用多个工具工具结果又会被写回 Thread影响后续决策。把这些概念理顺了后面调试就会轻松很多。2.2 一次 run 背后的执行循环当你调用创建 Run 的接口时云端发生的事比我之前想象的要多得多。第一步系统把 Agent 的系统提示词、当前 Thread 里的历史消息和用户这次输入拼在一起交给模型。第二步模型判断是否需要工具调用。如果需要它会输出一个结构化的工具调用请求而不是直接给你最终答案。云端识别到这种行为后会把这个状态暴露给你等你执行完工具并把结果传回去。这里有个关键点工具的执行通常发生在你的服务器上而不是 OpenAl 的服务器。OpenAI 知道该调用哪个函数、参数是什么但函数本身是你的业务逻辑只能由你运行。你把函数返回的结果提交回 Run云端会带着这个新信息再次调用模型让模型判断下一步是继续调用工具还是输出最终结果。如此循环直到模型认为任务完成或者达到你设置的最大步数。注意一次 Run 可能包含多轮模型调用所以成本不是一次请求的成本而是多轮请求成本的总和。这在设计任务和评估费用时一定要提前想清楚。2.3 和 Responses API 的分工有些人会混淆 Agents API 和 Responses API。Responses API 是对 Chat Completions 的升级它可以一次返回文本、工具调用、搜索引用等信息但对 Agent 循环的支持是有限的。它更适合单轮或简单的多轮交互比如一个客服机器人用户问一句模型答一句偶尔查一下知识库。而 Agents API 更接近“全权委托”它内部帮你管理循环你主要负责定义任务和最终检查结果。这两者不是替代关系而是互补关系。我的习惯是如果应用只需要“模型 工具调用 返回结果”用 Responses API 就够了代码更简单如果需要“模型自行决定多步操作直到完成一个复杂目标”用 Agents API。举个例子一个翻译工具用 Responses API 很合适一个自动修 bug 的机器人则更适合 Agents API。选错抽象层级要么代码绕要么成本高。3. 实操一次调用在云端跑起 Codex 同款 Agent3.1 准备工作密钥、SDK、环境动手前先准备好环境。你需要一个 OpenAI 账号并在官方平台创建一个 API key。注意这个 key 有权限范围建议只赋予当前项目需要的模型权限不要使用一个有全部权限的超级 key。创建完成后把 key 放到环境变量里方便本地调试export OPENAI_API_KEYsk-你的密钥Python 环境建议用虚拟环境隔离避免污染全局依赖。安装官方 SDK 很简单python -m venv .venv source .venv/bin/activate pip install -U openai我建议把 SDK 升级到当前最新版本因为 Agents API 相关的客户端方法出现时间较晚老版本可能没有对应封装。装好后在 Python 里验证能不能正常读取 keyfrom openai import OpenAI client OpenAI() print(client.models.list())如果能正常返回模型列表说明环境没问题。如果报认证错误优先检查环境变量是否真的设置了以及 key 是否复制完整。这些基础问题占了调试初期的大半时间。3.2 最小可用示例创建 Agent 并提交任务下面我用一个“代码审查 Agent”作为示例。先创建一个 Agent给它明确的角色和指令然后创建一个 Run 提交任务。这里我用的字段是当前 SDK 里比较常见的写法具体命名可能随版本有小调整但整体流程一致import time from openai import OpenAI client OpenAI() # 1. 创建 Agent agent client.agents.create( namecode-reviewer, instructions( 你是一名资深代码评审工程师。你会收到一段代码 请分析其中潜在的问题并给出可执行的修改建议。 如果调用了工具请结合工具结果给出最终结论。 ), modelgpt-4.1, ) print(agent id:, agent.id) # 2. 创建一次运行 run client.agents.runs.create( agent_idagent.id, input请检查下面这段 Python 代码是否有问题\n\n def calc(x, y):\n return x / y\n, ) # 3. 轮询直到完成 while run.status not in (completed, failed, cancelled): run client.agents.runs.retrieve( agent_idagent.id, run_idrun.id, ) time.sleep(1) print(run status:, run.status) # 4. 获取结果消息 messages client.agents.messages.list( agent_idagent.id, run_idrun.id, ) for msg in messages.data: print(f[{msg.role}]: {msg.content})这段代码执行后agent 会分析 calc 函数很可能指出除零风险然后给出使用条件判断或异常处理的建议。整个过程你只需要创建一次 Run云端会自动完成后续推理。如果 run 状态卡在 pending多半是提交任务时参数没传完整或者是账户并发限制导致排队。3.3 给 Agent 装上自定义工具真正好用的 Agent 必须能调用你自己的业务函数。比如我希望这个代码审查 Agent 能直接执行一段测试代码看看能不能运行。那我需要定义一个工具把函数描述交给 Agent让它在需要时调用。工具定义格式和 Responses API 的函数调用类似tools [ { type: function, function: { name: run_code, description: 执行传入的 Python 代码并返回标准输出或错误信息, parameters: { type: object, properties: { code: { type: string, description: 要执行的 Python 代码 } }, required: [code] } } } ] agent client.agents.create( namecode-reviewer, instructions你是代码审查工程师可以调用 run_code 工具来验证代码能否运行。, modelgpt-4.1, toolstools, )创建 Run 后如果模型认为需要执行代码Run 状态会变成 requires_action并返回一个工具调用请求。这时你需要在代码里处理这个请求执行工具、把结果提交回去。核心代码逻辑如下if run.status requires_action: tool_calls run.required_action.submit_tool_outputs.tool_calls tool_outputs [] for call in tool_calls: if call.function.name run_code: code json.loads(call.function.arguments)[code] output execute_code(code) # 你自己的执行逻辑 tool_outputs.append({ tool_call_id: call.id, output: output, }) run client.agents.runs.submit_tool_outputs( agent_idagent.id, run_idrun.id, tool_outputstool_outputs, )提交工具输出后云端会自动继续循环。这个模式是核心中的核心建议反复练习直到写熟。我第一次写时就把 tool_call_id 传错导致 Agent 一直拿不到对应结果最后超时失败。这类问题排查起来很费劲所以参数名一定要对着文档抄。4. 关键参数、成本控制与云端运行细节4.1 参数调优别一上来就全默认创建 Agent 时除了 model 和 instructions有几个参数值得专门调。第一个是 max_steps它限制 Agent 在一次 Run 里最多循环多少轮。这个参数很重要因为如果任务描述不清晰Agent 有可能陷入反复调用工具的循环浪费大量 token。第二个是 temperature任务型 Agent 建议调低到 0 到 0.3减少随机发挥。第三个是 parallel_tool_calls开启后模型可以一次请求多个工具调用适合需要并行查多个数据的场景但对于有依赖关系的操作关闭更安全。Instructions 的写法同样关键。很多教程喜欢写一堆“你是一个优秀的助手”这类话实际作用不大。更好的做法是明确任务边界输入是什么、输出格式是什么、遇到什么情况可以直接结束。比如我上面代码里那句“如果调用了工具请结合工具结果给出最终结论”就是在强制 Agent 在拿到工具结果之后必须收尾而不是继续发散。参数推荐值说明model根据场景选择简单任务用 gpt-4.1 mini复杂代码用更强模型temperature0 到 0.3降低随机性适合工具密集型任务max_steps5 到 20防止死循环按任务复杂度调整parallel_tool_calls视业务而定无依赖操作可开启有依赖则关闭response_formatjson_object 等需要结构化输出时使用这些参数看似简单组合起来影响巨大。一开始可以用最小任务试跑逐步调整比一次上复杂任务瞎猜要高效得多。4.2 云端运行的正确打开方式异步轮询、超时和并发Agents API 是异步的你提交 Run 后它不会立即返回最终答案而是返回一个 Run 对象你需要轮询它的状态。轮询有个技巧不要用固定的 1 秒 sleep 无限循环很多简单任务几秒就完复杂任务可能要几分钟固定频率要么浪费请求要么等太久。我习惯从 0.5 秒开始重试次数增加后逐步拉长间隔类似指数退避。同时一定要给客户端请求设置超时时间。因为 Agent 任务可能因为外部工具无响应而挂起如果你的请求根本没有超时限制客户端会一直阻塞最后看起来像程序死了。官方 SDK 一般允许传入 timeout 参数建议设成 60 秒甚至更高但你自己心里要有数这不是接口有多快而是它可能要跑很久。并发方面Agents API 支持同一时刻跑多个 Run。实际使用中如果任务是批量处理比如一百个工单摘要建议控制并发数量不要一次性全打出去。因为一方面账户有速率限制另一方面并发太多会导致每个任务排队时间变长整体吞吐反而下降。我常用的策略是建一个简单的任务队列保持 5 到 10 个 Run 并发跑完一个再补一个。4.3 费用估算让每一轮 token 花在刀刃上费用是很多人容易忽略的点。Agents API 不是计一次费而是整个 Run 生命周期内所有模型调用费用的总和。一次复杂的代码任务可能会调用几十次模型每次都要算输入和输出 token。我的估算公式很朴素单次任务成本 ≈ 每步平均 token 数 × 步数 × 每 token 单价假设平均每步输入 3000 token、输出 1000 token跑 10 步按你所用模型对应价格一算一次任务可能是一笔不小的开销。所以我在设计 Agent 时会刻意降低输入长度无关上下文不放进去工具返回结果控制长度历史消息必要时截断。很多任务其实不需要把完整历史都喂给模型保留最近几轮就够了。成本控制还有一个思路把复杂任务拆成多个简单 Agent 串行执行每个 Agent 只负责一小段逻辑。这样每个 Agent 的上下文都比较短总 token 可能反而更低而且单个任务出错的定位范围更小。代价是多了一次编排的复杂度需要权衡。5. 常见问题与避坑实录5.1 我踩过的四个坑第一个坑是 Run 一直 pending。遇到过几次原因各不相同最常见的是提交创建 Run 时丢了 agent_id导致云端不知道该把这个任务派给谁。还有一个原因是工具调用参数格式不对模型一直没办法生成合法的工具调用请求结果就卡在排队或内部重试上。排查时我会先看 Run 的状态流转再检查参数格式。第二个坑是工具执行结果的格式。模型需要的是字符串、JSON 或结构化文本但我一开始把工具结果打印成了一个 Python 对象提交时没有序列化成字符串导致 Agent 读不懂后续循环完全跑偏。后来我统一在工具函数里返回字符串并且把异常信息也作为返回值的一部分。这样模型即使遇到异常也能根据提示调整方案。第三个坑是轮询太频繁。我有一次用 0.1 秒间隔去死循环查状态结果任务还没跑完自己先撞上了速率限制后面合法的请求也被拒了。后来我加了一个最小间隔和最大重试次数。轮询不是越快越好云端处理任务有自己的节奏耐心等就行。第四个坑是忘了检查 requires_action。当时我以为创建 Run 后只要轮询到 completed 就行结果工具调用请求一直没人处理Run 卡在中间状态白白消耗了费用。后来我把状态机完整写了一遍pending 排队中、requires_action 需要交工具结果、completed 完成、failed 失败、cancelled 取消。每个状态都要有对应的处理逻辑没有同一个状态多个处理入口才算完整。5.2 问题速查表现象可能原因处理方式Run 一直 pendingagent_id 错误或请求排队检查参数确认任务是否在排队工具调用后继续不下去工具输出不是字符串或格式错误统一返回字符串包含错误信息轮询请求被限流sleep 间隔太短增加间隔使用指数退避结果缺失或为空未处理 requires_action完善状态机提交工具输出费用远超预期没有设置 max_steps提前设置上限缩小上下文输出格式不符合要求instructions 不够明确明确输出格式或用 json_object这张表是我在实际项目中积累出来的不是官方文档原文。每个问题后面大概率还有其他环境因素但先对照这张表排查大部分基础问题都能快速定位。6. 适合用 Agents API 的场景以及下一步还能怎么玩6.1 三个立刻能落地的场景第一个场景是代码修复与审查。给 Agent 接上读取文件、执行测试的工具它就能自动定位问题、修改代码、跑测试确认。和完全人工操作相比它能节省大量前期排查时间。不过我不建议让它直接改生产代码最好在隔离环境里运行人工 review 一遍再合入。第二个场景是客服工单处理。Agent 接上知识库检索和工单系统 API 后可以自动判断工单分类、查找相似历史、生成初步回复。人工客服只需要看一遍草稿改几个字就能发送。这个场景的收益很直接重复性工作减少响应速度提升。需要注意的是涉及用户隐私数据时要严格控制 Agent 能访问的字段范围。第三个场景是批量数据处理。比如一批 PDF 文档需要提炼摘要、提取关键字段、生成表格。传统做法要写解析脚本规则稍微变一下就要改代码。用 Agents API 的话Agent 能理解语义可以直接根据提示词完成抽取和整理。成本比脚本高但应对复杂格式变化时反而更省心。6.2 从单个 Agent 走向多 Agent 协作Agents API 单跑一个 Agent 已经很强了但复杂业务往往需要多个 Agent 配合。我比较喜欢 Planner-Coder-Reviewer 模式一个 Agent 负责拆解任务形成方案一个 Agent 负责执行代码另一个 Agent 负责检查前者的产出。每个 Agent 专注一件事prompt 更简单效果也更容易评估。多 Agent 需要解决通信问题。最简单的方式是让它们共享一个 Thread前面 Agent 的输出作为后面 Agent 的输入。复杂一点可以给每个 Agent 配不同的工具然后由一个调度逻辑控制流程。Agents API 在这个方向上没有把话说完留了很多扩展空间我预计未来会有更多开箱即用的编排能力。我个人实际用下来最大的感受是Agents API 并没有让 Agent 变得“会思考”它只是把“如何把想法变成连续行动”这件事从客户端搬到了云端。使用它的前提是你对任务边界有清晰定义包括什么样的结果算完成、什么样的错误可以容忍。如果你习惯本地调试可以先从最小任务测试循环确认输出稳定后再加工具如果一上来就丢一个复杂仓库给 Agent费用和等待时间都会让你怀疑人生。最后分享一个小经验在 instructions 里明确写出“什么时候算完成”能帮你省掉大量无效步骤这个技巧在绝大多数 Agent 任务里都适用。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进