想象你开了一家餐厅,请来一位“多看一步”的主厨。他接到订单后不会直接报菜名,而是先拆解任务:查库存、定烹饪方案、开火、调味、试味,最后装盘端出。每一步都在验证上一个结果,遇到甜品订单还会喊甜点师傅接手。OpenAI 官方的多步 Agent SDK,就是帮你把这样的“多工序主厨”从概念变成代码的整套厨具。本文带你从搭厨房到掌勺,亲手做出能拆解任务、调用工具、多步协作的智能体应用。
掌握 OpenAI 官方多步 Agent 开发,你将能独立搭建具备工具调用与多步规划能力的生产级智能体,这是智能客服、数据分析助手、自动化办公等一线 AI 岗位的核心硬技能。
可视化演示
动态演示OpenAI官方多步Agen的核心机制,通过概览/流程/对比/趋势四种模式展示关键概念与交互流程。
本节配有交互动效(进入视口后自动加载,约 3KB)。
OpenAI官方多步Agen:Open OpenAI Agents S Agent编排调度与多步执行流 核心机制可视化 OpenAI官方多步Agen整体架构与关键组件
智能体认知
普通聊天机器人像一位只会背菜谱的解说员:你把订单念给他,他能流利地复述“这道菜要先焯水再爆炒”,但绝不会碰一下锅铲。而多步 Agent 是真正上岗的主厨——他看完订单,会自己规划“先备菜、再热锅、依次下料、试味装盘”,然后真的一步一步把菜做出来。
在 OpenAI Agents SDK 的世界里,一个 Agent 对象就是这位“会动手的主厨”。它由四件套组成:模型是大脑,负责理解与决策;指令是后厨手册,规定做事风格与边界;工具是厨具清单,让它具备“干活”的能力;上下文是订单便签,记录当前一切已知信息。所谓“多步”,指的是模型在给出最终回答之前,可以反复经历“思考→调用工具→拿到结果→再思考”的内部循环。
SDK 的核心编程模型是把 Agent 声明为一个对象,再把执行交给 Runner。你不需要手写循环去拼 prompt,框架会在内部自动维护“工具调用→结果回填→继续推理”的循环,直到模型认为信息足够、输出最终答案。这也是它与普通 Chat 接口本质上的区别:Chat 接口默认一步到位,Agent 则允许“多走几步”。
所以别再让 AI 当“只会背菜谱的解说员”了。用 SDK 定义出模型、指令、工具、上下文这四件套,你的应用就从“能聊”进化成了“会干活”,这正是多步 Agent 的第一课。
- A_agent(智能体整体)代表一个完整的智能体,相当于后厨中那位真正动手做菜的主厨。
- M(模型大脑)主厨的头脑,负责读订单、做判断、决定下一步动作。
- I(指令手册)后厨规章制度,规定口味风格、做事边界和流程偏好。
- T(工具清单)菜刀、炒锅等厨具的集合,让主厨具备动手完成任务的资本。
- C(上下文便签)订单和备忘板上的全部信息,供主厨每一步决策时翻阅。
环境快速搭建
新餐厅开业,第一件事不是招厨师,而是给后厨通水通电、买齐锅碗瓢盆。没有这些基础,再好的手艺也施展不开。对开发者来说,装好 SDK、配好密钥,就是给这间“AI 后厨”完成开荒。
安装过程只有一行命令:写代码前先在你的 Python 环境里执行 pip install openai-agents。接着配置环境变量 OPENAI_API_KEY,相当于给厨房办一张“供应商通行证”,模型服务才会响应你的请求。最后确认网络能访问 OpenAI 接口,就像确认食材供应链畅通。
搭好环境后,可以立刻写一个最小 Agent 验证链路:只给一个 name 和一段 instructions,用 Runner.run() 跑一句“你好”,能返回内容就说明厨房通水通电了。这个最小原型虽然还不会用工具,但它已经是一个合法的多步 Agent——你随时可以把工具和更复杂的指令加进去。
厨房通了水电气,主厨才能上岗。环境这一关看似琐碎,却决定了后面所有代码能不能跑起来——记住,先让“最小可用厨房”转起来,再逐步加设备。
- E(运行环境)让 Agent 能跑起来的整个“AI 后厨”基础设施。
- S(SDK 依赖)已经装好的 openai-agents 包,相当于购置齐备的厨具套件。
- K(API 密钥)区分身份的通行证,证明你有权限调用模型服务。
- N(网络连通)厨房到供应商之间的物流链路,保证请求能送达、结果能返回。
Agent定义配置
主厨上岗前,老板会递上一份《本店手册》:口味偏淡、“不要香菜”必须划重点、上菜不得超过十五分钟。这份手册决定了主厨做事的方式。在 SDK 里,它对应的就是 instructions 参数。
定义一个 Agent 通常是这样:给它起个名字、写清楚指令、选一个模型、挂上工具列表。指令的质量几乎直接决定多步执行的成败——你想让它先查库存再报价,就把这个顺序写进手册;你想让它语气简洁,也在手册里注明。
模型选型方面,复杂推理任务适合 gpt-4o 系列,追求成本和速度可以用 gpt-4o-mini;此外还能调整 temperature 等参数,控制回答的随机性——好比规定主厨“按标准菜谱走,不许自由发挥”。SDK 把这些都收敛成 Agent 构造函数的参数,改动一行就能更换一个“人设”。
手册写得好,主厨才不跑偏。Agent 定义阶段花十分钟打磨 instructions,往往比后面调试十次工具调用更有效——这是所有多步 Agent 项目的“免费杠杆”。
- y(最终输出)主厨端给客人的那道菜,也就是 Agent 的最终回答。
- P_θ(模型决策能力)主厨大脑里的厨艺,由训练阶段决定,推理时固定不变。
- I(指令条件)手册约束,每一项“必须、禁止”都在缩小输出范围。
- C(上下文条件)当前订单详情,让模型围绕真实问题作答。
- T(工具条件)可用厨具列表,决定模型能不能“动手”以及怎么动手。
工具函数开发
厨房里每样工具都贴着一张说明卡:名称“切片刀”、用途“处理食材”、用法“请递入菜名”。模型读卡之后,就能判断此刻要不要用这个工具、参数该怎么填。这张卡做得越清楚,工具被正确调用的概率越高。
SDK 提供了 @function_tool 装饰器:你只要写一个普通的 Python 函数,加上类型注解和 docstring,SDK 就会自动把它翻译成模型能读懂的“说明卡”(JSON Schema)。函数名就是工具名,docstring 就是用途说明,参数注解就是填卡模板。
调用过程同样顺滑:模型在推理中说“我要调用 query_stock_price,参数 AAPL”,Runner 就真的去执行这个函数,把返回值(普通字符串即可)追加到上下文,交回给模型继续推理。工具返回“未收录该股票”这类兜底文案时,模型往往还会换个参数重试——这正是多步循环的魅力。
好工具要“单一职责”:一把刀只负责切菜,一个工具只干一件事。把工具设计得简单、说明写得清楚,主厨(模型)才能像用自家厨具一样顺手,这是整个 Agent 能力的天花板。
- ToolSpec(工具规格卡)贴给模型看的工具说明卡片,决定它是否调用、如何调用。
- Φ(自动转换器)
@function_tool装饰器的幕后工作,把代码翻译成说明卡。 - name(工具名称)卡片上的工具名,如“查询股价”。
- description(用途说明)解释“何时该用这个工具”,是决策匹配的关键。
- params(参数模板)说明参数有哪些类型,模型照着模板填参数。
多步执行流程
做佛跳墙不可能一锅端:要泡发、焯水、炖煮、收汁,每完成一步还得看看火候对不对,不行就调整。多步 Agent 的执行过程也是如此——它不是在“写答案”,而是在“做任务”。
这一切由 Runner 驱动。Runner.run(agent, input) 一发出,内部就开启循环:模型判断要不要调用工具,需要就输出调用指令,Runner 执行工具并把结果回填,再让模型继续想;直到模型认为信息足够,才输出最终回答,整个过程结束。这就是多步执行的核心机制。
结果追踪方面,运行结束后可以从 Result 对象里拿到 final_output(最终回复)、last_agent(最后负责的 Agent)等字段;如果接入流式事件,还能实时看到每一步的工具调用记录,像透过后厨玻璃看主厨做菜一样。
多步执行把“一道大菜”拆成“一道道工序”,每一步的结果都成为下一步的输入。理解了这条循环链,你就掌握了 Agent 从“想”到“做”的引擎——后面所有复杂编排都建立在这条循环之上。
- S_t(当前状态)做菜进行到第几步、锅里是什么状态,对应 Agent 当前的中间上下文。
- step(单步执行)一次“推理→决策→行动”的完整工序。
- r_t(工具结果)这一步工具返回的信息,比如“查到股价是 190.2”。
- tool(args_t)(工具调用)按模型给出的参数执行具体工具函数。
- 下标递进每一步都建立在上一步之上,直到状态满足终止条件。
上下文管理
后厨的备忘板上贴满便签:订单最初只有一句“宫保鸡丁”,中途又贴上新备注“不要花生”,旁边还挂着刚才查到的“鸡胸肉库存不足”。主厨每做一步都要瞄一眼板子。对 Agent 来说,这块板子就是上下文。
SDK 里每次 Runner.run 都是独立会话,相当于一张新订单,不会自动继承上一单的便签。如果你希望 Agent“记得”之前的对话,需要显式地把历史消息传进去,或者使用持久化能力把状态存到外部。默认“不记忆”不是缺陷,而是把控制权交还给开发者。
更精细的状态管理可以用 RunContextWrapper:工具函数可以通过它读取和写入上下文数据,比如用户身份、订单编号、中间计算结果。这套机制相当于给主厨配了个“随身笔记本”,写什么、什么时候擦掉,都由你决定。
上下文串起了多步 Agent 的整个生命周期:上一轮的工具结果、用户的隐含偏好、系统的固定守则,全都在这块“备忘板”上汇合。善用上下文,你的 Agent 才能像老主厨一样“心里有数”。
- C_t(当前上下文)主厨做第 t 步时知道的所有信息,贴满便签的整块备忘板。
- concat(拼接操作)把不同来源的信息按顺序拼成一段完整输入。
- I(固定指令)永远排在最前面的后厨手册,任何一轮都不能丢。
- H_{<t}(历史记录)t 这步之前的所有对话与工具结果,像墙上层层叠叠的旧便签。
- x_t(当前输入)刚收到的这条新订单备注。
编排与协作
大餐厅不会只靠一个主厨:热炒间、凉菜间、甜品间各司其职。主厨看到订单是生日蛋糕,喊一声“甜品组接单”,就把这单转了出去。在 SDK 里,这个动作叫 handoff(交接)。
实现交接非常简单:在 Agent 的 handoffs 参数里列出可交接的其他 Agent,模型会根据当前请求的意图,自动决定是留下来亲自处理,还是把整段会话转给更合适的专家。一个典型的架构是“三明治”:派一个调度 Agent 接单,按问题类型分发给不同的专家 Agent,每个专家只负责自己那摊事。
子 Agent 是另一种协作形态:主 Agent 可以把一个子任务“委派”给子 Agent,拿到它的输出后继续自己的工作。当你需要 Agent 同时具备“总览全局”和“深耕细节”的能力时,这种主从结构比把所有逻辑塞进一个 Agent 思路清晰得多。
单个主厨再强也有上限,团队协作才能应付满堂客人。多 Agent 编排让你把复杂业务拆给多个“专精主厨”,各管一摊、随时交接——这也是多步 Agent 从玩具走向生产的必经之路。
- q(当前请求)用户刚刚说出的那句话,比如“我要退款”。
- intent(q)(意图识别)判断这单属于甜品、凉菜还是热炒,即问题属于哪个领域。
- a_i(候选 Agent)后厨里所有可以接单的师傅,即
handoffs列表。 - handoff(交接动作)把整段会话连同便签一起转给目标师傅。
- next(接手者)最终接单的那个人,后续任务由它继续完成。
AI 应用场景
智能客服工单分级
阶段:意图识别 + 多步工具调用
解决的问题:传统客服需要人工判断用户是问物流、改订单还是退款,再转给对应系统;用多步 Agent 后,先拆解用户诉求,调用订单查询工具,再按规则生成答复,超权重诉求自动 handoff 给人工坐席通道。
具体案例:某电商售后机器人收到“我 6 号买的数据线还没到”,Agent 先调用订单查询工具确认物流状态,再调用物流轨迹工具拿到最新节点,最后用预设语气输出“预计明天送达,如超时可申请补偿”,全程多步自动完成。
数据分析助手
阶段:任务规划 + 工具调用 + 结果汇总
解决的问题:过去数据分析师要手动查库、调聚合、画图,步骤繁琐;多步 Agent 把“算一下各区域 Q3 销售额”拆成查数据表 → 聚合计算 → 生成图表 → 输出结论,一条指令跑完整条链路。
具体案例:面向业务线的自助分析助手,运营人员用自然语言提问,Agent 依次调用 query_sales_data、aggregate_by_region、plot_chart 三个工具,最终返回带图表和结论的完整周报。
自动化办公流程
阶段:多步执行 + 外部工具集成
解决的问题:会议纪要到待办入库往往需要人肉搬运;多步 Agent 串联“转写 → 摘要 → 提取待办 → 写入项目管理工具”等动作,一次命令完成整条流水线。
具体案例:项目周会后,Agent 调用 transcription_to_text 获取纪要,调用 extract_todos 抽取负责人与截止时间,再调用 create_task 批量写入飞书,并把结果汇总发送到项目群。
Python 演示
import asyncio from agents import Agent, Runner, function_tool @function_tooldef query_stock_price(symbol: str) -> str: """查询指定股票代码的最新成交价, 返回字符串形式的价格""" prices = {"AAPL": "190.20 美元", "MSFT": "420.30 美元", "TSLA": "248.50 美元"} return prices.get(symbol.upper(), "未收录该股票") @function_tooldef calc_roi(cost: float, current: float) -> str: """根据买入成本与当前价格计算投资回报率, 返回百分比字符串""" roi = (current - cost) / cost * 100.0 return f"回报率 {roi:.2f}%" async def main() -> None: analyst = Agent( name="股票分析师", instructions="先用 query_stock_price 查最新价, 再用 calc_roi 算收益, 最后给出投资结论", model="gpt-4o-mini", tools=[query_stock_price, calc_roi], ) result = await Runner.run(analyst, "我 180 美元买入 AAPL, 现在赚了多少?") print(result.final_output) if __name__ == "__main__": asyncio.run(main())
from agents import Agent, Runner, function_tool导入 SDK 三大件,对应主厨、传菜员和厨具注册表。@function_tool把普通 Python 函数注册成模型可调用的工具。def query_stock_price(symbol: str) -> str:类型注解帮助 SDK 生成参数模板,模型据此填参数。prices.get(symbol.upper(), "未收录该股票")命中返回价格,没命中给兜底文案,模型会据此换参数重试。instructions="先用 query_stock_price 查最新价..."在多步执行中引导工具调用顺序,像后厨手册一样。Runner.run(analyst, ...)启动多步执行循环,直到模型不再需要工具为止。
常见误区
误区我以为接上 SDK 后,Agent 和普通聊天机器人差不多,只是多了几个工具按钮,用户点哪个就调哪个,回答还是模型一次性生成。
正解把多步 Agent 想成主厨就明白了:模型收到问题后,会先在大脑里做多轮决策——要不要查工具?查完结果如何解释成答案?工具返回异常是不是换参数再来?SDK 的 Runner 内部有一个自动循环:模型输出工具调用指令 → 执行工具 → 把结果追加给模型 → 模型再决定下一步,直到输出最终答案。它是“自己决定多走几步”,不是靠用户点按钮。
为何常见:很多人用惯了 prompt 直出式的聊天接口,没看过 Runner.run 内部的工具调用循环,容易误以为 Agent 能力来自“按钮多”。
误区我以为工具函数必须返回严格 JSON,比如 {"price": 190.2},不然大模型就解析不了,跑起来会报错。
正解实际上 SDK 对返回值的要求非常宽松:返回普通字符串即可,例如“190.20 美元”。模型看到的是自然语言文本,反而比裸 JSON 更易理解。真正重要的不是返回格式,而是 docstring 写清楚“这个工具干嘛用、参数什么意思”,模型才能正确选择并调用。
为何常见:看了一些传统 API 对接教程,习惯性地以为结构化数据必须 JSON 序列化,忽略了 LLM 本身就是处理文本的。
误区我以为每次运行 Runner.run 之后,Agent 都会自动记住上一轮聊了什么,上下文会一直积累,不用我管。
正解每次 Runner.run 都是独立的一次会话,相当于厨房新开一个订单,不会自动带着上一单的便签。要想跨轮记忆,得手动把历史消息传给下一次 run,或者在工具函数里通过 RunContextWrapper 读写持久化内容。把上下文想象成备忘板——板子不会自己贴便签,是你贴它才有。
为何常见:聊天 ChatGPT 有自动历史记忆给很多人留下了先入为主的印象,但 SDK 为了灵活可控,把“记什么”的权利交给了开发者。
误区我以为只要 instructions 写满几十条“必须”“禁止”,Agent 就一定会严格按步骤执行,不会出岔子。
正解指令能大幅提高执行正确率,但模型是概率推理而不是程序执行,即使手册写得很细,也可能漏步或顺序颠倒。因此工程上要做校验:工具返回异常时设计重试兜底,关键步骤让 Agent 明确输出中间状态,必要时用一个小 Agent 检查另一个 Agent 的结果。
为何常见:把自然语言指令误当成硬编码逻辑,低估了模型推理的随机性。
面试题
Q1. 下列哪一项不是多步 Agent 的核心组件?
- A.大语言模型
- B.指令系统
- C.工具函数
- D.光驱设备← 正确答案
答案:D。多步 Agent 的四件套是模型、指令、工具、上下文,相当于主厨的大脑、手册、厨具和便签。光驱设备与厨房无关,自然不是核心组件,其他三个选项都对应 Agent 的必要部分。
Q2. 安装 OpenAI 官方多步 Agent SDK 的正确方式是?
- A.安装 openai 基础包
- B.安装 openai-agents 包← 正确答案
- C.安装 agents 官方包
- D.安装 AgentRunner 包
答案:B。openai-agents 是官方 SDK 的包名,相当于给厨房买标准厨具套装。安装 openai 只是打开了基础聊天能力,agents 和 AgentRunner 都不是官方指定的完整 SDK 包名。
Q3. 工具返回“未收录该股票”时,多步 Agent 最可能的下一步行为是?
- A.报错并终止整个会话
- B.修正参数后重新调用工具← 正确答案
- C.忽略错误继续下一步
- D.自动删除该工具定义
答案:B。工具返回“未收录”属于正常的业务反馈,不是致命错误。Runner 循环会把字符串结果交给模型,模型看到后大概率会判断“是不是代码写错了”,然后换个参数重试或主动向用户说明。直接报错退出、忽略结果或删除工具都不符合多步循环的设计。
Q4. 关于 Runner.run 的多步执行,下列说法正确的有?
- A.内部会循环调用工具直至完成← 正确答案
- B.每次运行自动保留全部历史
- C.返回结果中包含最终输出文本← 正确答案
- D.只能处理单轮的用户提问
答案:AC。Runner.run 内部是一个多步循环:模型提出工具调用→执行→结果回填→再次推理,A 正确;返回的 Result 对象中有 final_output 字段,C 正确。SDK 每次 run 是独立会话,不会自动保留全部历史,B 错;多轮任务正是多步 Agent 的强项,D 错。
Q5. 在 SDK 中,handoff 的主要作用是?
- A.交换两个模型的网络权重
- B.将会话转交另一个智能体← 正确答案
- C.把工具迁移到其他进程
- D.清空当前全部上下文
答案:B。handoff 就像主厨把生日蛋糕订单喊给甜品师傅:模型根据意图,把整段会话连同上下文转交给另一个 Agent 处理。交换权重、迁移工具、清空上下文都与交接无关。
Q6. 最适合让 Agent 按“先查库存、再改价格”固定顺序执行的做法是?
- A.在指令中写清工具调用顺序← 正确答案
- B.把全部逻辑塞进一个工具
- C.禁用工具让模型自由发挥
- D.加大模型上下文窗口
答案:A。多步 Agent 最推荐的做法是在 instructions 里描述清楚顺序,模型会把它当作工作流执行。把全部逻辑塞进一个工具违背“单一职责”原则,代码会越来越难维护;禁用工具或加大上下文都解决不了顺序问题。
Q7. 上下文管理中可以包含哪些信息?
- A.历史对话消息记录← 正确答案
- B.用户身份标识信息← 正确答案
- C.工具执行中间结果← 正确答案
- D.模型训练完整权重
答案:ABC。运行上下文里既能放历史对话消息(之前的便签),也能放用户身份标识(是谁下的单),还常常需要工具执行的中间结果(刚查到的数据),这些都会拼进下一次模型输入。模型训练权重属于训练阶段的东西,不会出现在运行上下文里。
Q8. 关于工具函数的返回值,以下哪种写法正确?
- A.直接返回 None 表示成功
- B.返回普通字符串即可← 正确答案
- C.必须返回 JSON 格式
- D.必须抛出异常结束
答案:B。工具函数返回普通字符串即可被模型理解,SDK 会自动把字符串放进下一轮上下文。返回 None 会让模型没有信息可用,强制 JSON 并非必需,抛异常更会中断整个执行流。
Q9. 多步 Agent 中“拆解任务”指的是?
- A.把长文本压缩成一句话
- B.拆成多个可执行的小步骤← 正确答案
- C.把数据集切成多块并行
- D.把工具分散到多个进程
答案:B。多步 Agent 的优势就是把大问题拆成“查数据→算结果→写结论”等小步骤,逐步执行。压缩长文本是摘要任务,切分数据集是数据处理,分发工具是工程部署,都不是 Agent 的任务拆解。
Q10. 以下哪些方式可以保证工具按固定顺序执行?
- A.在指令中写明固定的工具顺序← 正确答案
- B.完全交给模型自由发挥即可
- C.把多步逻辑合并进一个工具← 正确答案
- D.禁用所有工具强制固定路径
答案:AC。保证固定顺序最稳妥的两条路:一是在 instructions 中明确写出先调用哪个再调用哪个,让模型按手册执行;二是把多步逻辑合并进一个工具函数,顺序在函数内部彻底固化。完全交给模型自由发挥无法保证顺序,禁用所有工具则会让任务根本无法完成。