全书目录

第九编 框架层

第 44 章 OpenAI Agents SDK:把运行时对象产品化

11 分钟 4,912 字 第 45 / 161 个阅读单元

OpenAI Agents SDK 的设计重点,和 LangGraph 这类图框架非常不同。

它不是从图、节点、边开始讲系统。 它是从一组运行时对象开始讲系统:

  • Agent
  • Runner
  • Tool
  • Handoff
  • Guardrail
  • RunState
  • Session
  • Trace / Span

这意味着它真正想做的事情,是把一个 Agent 系统在运行时最常见的稳定对象,整理成一套产品化 SDK。

因此,第 44 章第一条结论应该是:

text
OpenAI Agents SDK 的中心不是图,
而是“一个 agent run 过程中会稳定出现哪些对象,以及这些对象如何协同”。

这件事听上去简单,但其实非常有力量。

因为很多团队自己写 Agent 时,都会零散地遇到这些问题:

  • agent 定义放在哪里
  • tool 如何描述和审批
  • handoff 如何发生
  • structured output 如何接
  • 会话历史如何保存
  • 中断如何恢复
  • 结果如何检查
  • tracing 如何串起来

而这个 SDK 的回答是:不要把这些能力散成工具箱,而要把它们组织成统一的 runtime 对象体系。

#44.1 它真正解决的,不是“图编排”,而是“运行时对象标准化”

如果把 OpenAI Agents SDKLangGraphLangChain 放在一起看,它的差异非常鲜明。

它不是从图结构出发,也不是从高层应用入口出发。 它的出发点更接近:

text
一个 agent 系统真正运行起来之后,
哪些对象会稳定出现,应该被固定成 SDK 标准件?

这就是为什么官方首页会把原语压缩得非常少。 它希望开发者主要围绕这些对象思考:

  • Agent
  • Tool
  • Handoff
  • Guardrail
  • Runner
  • Session
  • RunResult
  • RunState
  • Tracing

这与很多框架完全不同。

有些框架的核心问题是“执行结构如何表达”。 有些框架的核心问题是“高层应用如何快速构造”。 而 OpenAI Agents SDK 的核心问题更像是:

text
如何让一次 agent run 里的关键对象具有稳定边界、稳定职责和稳定生命周期。

这正是“产品化 runtime”的典型特征。

#44.2 对象模型:Agent 不是人格壳,而是静态能力边界

理解这个 SDK,第一件事就是不要把 Agent 看成“人格化对象”。

在这里,一个 Agent 更像一个声明式配置对象。 它聚合的是:

  • instructions / prompt
  • model
  • tools
  • handoffs
  • input / output guardrails
  • output type
  • hooks
  • tool use behavior

也就是说,在 OpenAI Agents SDK 里,Agent 首先回答的不是“它像谁”,而是:

text
这个运行单元拥有哪些能力、约束和委派边界。

再看 ToolHandoff,会更清楚。

Tool 不是自由文本外部函数,而是带有 schema、审批位、超时策略、guardrails 的运行接口对象。 Handoff 也不是抽象图边,而是一个显式声明“把当前控制权切给另一个 agent”的对象。

这说明 SDK 并没有把“多 agent”做成自由度极高的工作流语言。 它是在把最常见的运行时对象标准化。

#44.3 生命周期:真正的主语是 Runner.run(),不是单个 Agent

和前两章比起来,这一章最重要的主语变化是:

OpenAI Agents SDK 中,真正推进系统前进的,不是图,也不是某个 middleware 总线,而是 Runner.run() 所代表的 run loop。

它的核心循环非常清楚:

  1. 调当前 agent
  2. 如果得到 final_output,结束
  3. 如果触发 handoff,切换活动 agent
  4. 如果产生 tool calls,运行工具并继续
  5. 直到结束或超过 turn 限制

这套循环看起来朴素,但非常具有产品化风格。

因为它把运行中的关键分支限制在少数稳定类型上:

  • final output
  • tool call
  • handoff
  • interruption / approval

这意味着 SDK 不鼓励开发者一上来就定义无限多的自定义控制原语。 它更倾向于说:

text
大多数 agent run 可以先被组织成有限几类事件。

这正是 SDK 易用性的来源。

#44.4 输入契约:input items 才是第一性输入,不是 prompt 字符串

理解这个 SDK 的输入模型,最重要的一步,是放弃“输入就是一段字符串”的思维。

虽然它当然支持字符串输入,但那只是高层便利接口。 从更本质的角度看,它真正的一等输入是:

text
Responses API 风格的 input items 序列。

这件事非常关键。

因为一旦输入被理解成 items,而不是一整段 prompt,很多系统能力就自然出现了:

  • 可以区分用户消息、工具调用、工具结果、handoff 项、审批项
  • 可以把历史表示成可重放序列
  • 可以把一次 run 的新产出重新变回下一轮输入
  • 可以把结果对象和会话对象接到同一输入协议上

也就是说,这个 SDK 的输入契约不是“聊天文本”,而是“可序列化、可回放的运行项”。

#44.5 状态分层:RunContextWrapperSessionRunResultRunState 不是一回事

这一章最需要讲透的,就是状态分层。

因为 OpenAI Agents SDK 最容易被误解的一点,就是把“上下文”“会话”“结果”“恢复状态”全混成一层。 而它实际上分得很清楚。

第一层,是 RunContextWrapper。 这是本地运行上下文。 它服务于工具、guardrails、handoffs、hooks。 官方明确强调:这里面的 context 默认不会自动发给模型。

第二层,是 Session。 这是跨 run 的会话记忆层。 它的职责非常明确:

  • 取历史 items
  • 存新历史 items
  • 清理或裁剪历史

第三层,是 RunResult。 它是一次运行的结果观察面,回答的是“这次 run 发生了什么、得到了什么”。

第四层,是 RunState。 它解决的不是“以前聊了什么”,而是:

text
这次执行停在了哪里,如何从这里继续。

所以可以把这四层压缩成一句非常重要的话:

text
RunContextWrapper 是本地运行上下文,
Session 是跨轮历史,
RunResult 是观察结果,
RunState 是可恢复执行快照。

这也是为什么 SessionRunState 绝不能混为一谈。 前者偏“记住之前发生过什么”,后者偏“从哪里继续跑”。

#44.6 多 Agent:agents as toolshandoff 的本质分界

这个 SDK 的多 Agent 设计也非常值得注意。

它没有把多 Agent 做成复杂图模式集,而是主要集中在两条主线:

  1. agents as tools
  2. handoff

这两者的区别并不只是写法不同,而是控制权结构不同。

agents as tools 的本质是:

  • 上层 manager 保持最终控制权
  • 下层 specialist 被当作能力接口调用
  • specialist 的结果回到 manager 再做整合

handoff 的本质则是:

  • 当前 active agent 发生切换
  • specialist 接管当前对话后续
  • 本轮控制权不再由原 agent 保持

因此,本章必须把一条边界写得很清楚:

text
handoff 是活动 agent 切换,不是通用流程编排。

如果你真正需要的是复杂工作流状态机,仅靠 handoff 这个原语通常不够。

#44.7 guardrails、审批与 tracing:它没有通用 middleware,而是拆成三类治理对象

这一点是它和 LangChain 很不一样的地方。

LangChain 倾向于用 middleware 形成统一控制面。 而 OpenAI Agents SDK 并没有走这条路。

它在治理层采用的是另一种更“强类型、窄接口”的设计:

  • guardrails 负责校验与阻断
  • human in the loop 负责审批式暂停与恢复
  • tracing 负责观测、审计和链路可见性

这三个面不是一个大 middleware 总线,而是三个职责明确的治理对象族。

这恰恰反映了 SDK 的产品化姿态:

text
它宁愿把常见治理问题做成专门对象,
也不急着把一切都抽象成一个万能拦截层。

#44.8 HITL 的真实边界:它是工具审批暂停,不是通用图中断

很多人看到 SDK 支持 human-in-the-loop,就会自然联想到:

  • 那是不是等价于图框架里的通用 interrupt?

答案是否定的。

OpenAI Agents SDK 里,HITL 的原生语义更窄,也更明确:

text
它主要是围绕敏感工具调用的审批暂停与恢复。

也就是说,它最适合的是:

  • shell 执行
  • apply_patch
  • 外部系统写操作
  • 敏感业务动作
  • 高风险 MCP 工具

而不是:

  • 任意节点都可以随时暂停
  • 任意状态都可以人工编辑后再继续
  • 任意图结构都能靠同一 interrupt 机制控制

这就是它和 LangGraph interrupt() 的本质差异。

LangGraph interrupt() 是通用 runtime primitive。 OpenAI Agents SDK 的 HITL 是产品化审批机制。

#44.9 业务适配:它为什么更适合“run-centered agent app”

从业务适配角度看,这个 SDK 最适合的不是一切 agent 系统,而是一类特定形状的问题:

  • 一次 run 的回合语义很重要
  • session 历史很重要
  • 工具审批很重要
  • handoff 或 manager-style 协作已经足够表达业务
  • 你希望 tracing、guardrails、session 一体化

这类问题通常长得像:

  • 客服分诊与专家接管
  • 企业助理与工具执行
  • 标准多轮对话式 copilot
  • 以 Responses API 与 built-in tools 为中心的应用 agent

它不太适合的,则通常是:

  • 复杂显式状态机
  • 大量自定义控制节点
  • 以图结构为第一性对象的系统
  • 深度依赖自定义并发图编排的系统

也就是说,OpenAI Agents SDK 最适合的不是“所有 Agent”,而是:

text
那些真正以 run、session、approval、handoff、tracing 为核心对象的 agent application。

#44.10 团队价值:统一运行时语言,而不是统一图语言

从团队角度看,这个 SDK 的价值也很有特色。

如果说 LangChain 更像统一高层应用接口,那么 OpenAI Agents SDK 更像统一运行时语言。

它让团队围绕以下稳定对象协作:

  • Agent
  • Tool
  • Handoff
  • RunResult
  • RunState
  • Session
  • Trace

这件事非常重要。 因为在真实团队里,很多协作问题都不是“能力不够”,而是没有共同对象语言。

而这个 SDK 最大的产品化价值之一,就是把这些对象固定下来。

#44.11 它和 LangGraph、LangChain 的真正分界

现在可以把三者边界并列写清:

  • LangGraph 的中心是图、状态、检查点和中断
  • LangChain 的中心是高层入口、中间件和应用接口
  • OpenAI Agents SDK 的中心是 runtime objects、run loop、session、guardrails、tracing

三者都能做 agent。 但它们真正放在中心的系统对象完全不同。

所以不要用“谁功能更多”去比较。 更准确的比较方式是:

  • 你想先控制图结构,还是先控制应用入口,还是先控制运行时对象

#44.12 最常见的误用:把它期待成通用 orchestration kernel

真正理解一个框架,也要看它最容易被误用成什么。

OpenAI Agents SDK 最常见的误用,至少有六种。

第一,把它期待成图框架。 结果会在复杂流程和显式状态机需求上持续受挫。

第二,把 SessionRunState 混成一件事。 结果会把会话历史与执行恢复语义搅在一起。

第三,把 handoff 当成通用编排边。 结果会误以为复杂流程问题只靠 agent 切换就能解决。

第四,把 guardrails 当成统一 middleware。 结果会高估它在任意点拦截和治理复杂流程的能力。

第五,把 HITL 当成通用 interrupt。 结果会把审批暂停和任意节点暂停混为一谈。

第六,只把它看成“Agent 类 + 工具调用”封装。 这样会完全低估 RunResult / RunState / Session / Tracing 这些真正有系统含义的对象。

因此,本章最后应留下的判断是:

text
OpenAI Agents SDK 的强项,不在于把任意流程表达成图,
而在于把 agent run 中最关键的对象、状态边界和生命周期产品化。

进一步压缩成一句话就是:

text
它不是图语言,也不是高层应用壳,
而是一套以 run、session、result、state、handoff、approval、trace 为中心的 runtime object framework。