使用 OpenAI Agents SDK 构建智能体——OpenAI 代理(Agent)SDK 入门

352 阅读17分钟

SDK(Software Development Kit,软件开发工具包) 是一组经过精心整理的库、工具与文档,让开发者可以“站在他人的辛勤成果之上”。我很喜欢这个略带俏皮的定义,因为它用大白话点明了所有开发者对 SDK 的核心诉求:少写代码。优秀的 SDK 会把繁琐的“接线”(wiring)、配置与样板代码(boilerplate)剥离出去,让开发者把精力放在应用真正独特的部分。

OpenAI Agents SDK 用于构建 AI Agent,且以简洁优雅著称。它没有让你面对自定义的配置语言或迷宫般的类层级,而是提供了一小组清晰的原语——agents、runners、tools、handoffs、guardrails、tracing——并以地道的 Python 实现。有了这六块“乐高积木”,你可以在几分钟内启动一个单 Agent多 Agent的原型。

在本章(第二章)中,你将学到:

  • OpenAI Agents SDK 的设计原则:包含极简抽象与面向多 Agent 编排的框架——Pythonic、灵活且可扩展
  • SDK 的核心原语:逐一讲解每个原语的用途与示例,以及它们如何协同工作

读完本章,你不仅会理解每个原语做什么,还会明白为什么该 SDK 的极简架构能成为快速、可靠构建 Agent 系统的务实起点——而这些系统正是本书其余部分将带你落地的目标。

技术要求

整本书的实践示例与每章的完整代码,都会在配套 GitHub 仓库提供:
github.com/PacktPublis…

我们鼓励你克隆仓库、复用与改造示例代码,并在学习各章内容时按需参考。

OpenAI Agents SDK 的设计特性

OpenAI Agents SDK 以若干关键原则为设计出发点,旨在在易用性灵活性之间取得平衡。理解这些设计选择,有助于你把握 SDK 的工作方式(以及它和其他方案的差异)。

用于构建 AI Agent 的框架

从宏观上看,OpenAI Agents SDK 之于构建 AI Agent,正如 Django、Ruby on Rails 之于构建网站。这些框架抽象了 Agent 开发与编排的底层细节,使开发者能专注于更高层的关键业务逻辑,并尽快部署一个 Agent,而无需为脚手架烦恼。

使用该 SDK,我们只需几行 Python 代码就能创建一个 Agent:

agent = Agent(name="Assistant", instructions="You are an AI agent",
    model="gpt-4o")
result = Runner.run_sync(agent, "Tell me a joke")
print(result.final_output)

这个示例通过 OpenAI 的 GPT-4o 模型与简要系统指令实例化了一个基础 AI Agent。让 Agent 进行迭代式思考的控制逻辑框架已经内嵌于 Agent 本身,这是框架直接提供的能力。随后我们对一个用户问题运行该 Agent,并打印模型输出。

注意
这里引入代码只是为了展示实现 SDK 的简洁与易用。要真正运行代码,你需要先安装并导入必要的库,我们会在下一章详细说明。

如果没有这个 SDK,要做同样的编排通常需要成千上万行代码,更不用说还要再写同等规模的追踪(tracing)与日志系统——而这些在 OpenAI Agents SDK 中都是开箱即用的。

OpenAI Agents SDK 的工程目标,是解决不仅仅是生成文本的 LLM 流程所固有的挑战:例如让模型能够分步推理解决复杂问题、与外部数据源与 API 工具交互(tool use)、以及在多个 AI 实体之间协调动作

多 Agent 编排

作为框架的一部分,SDK 同样支持构建多 Agent解决方案。事实上,这也是其前身 Swarm 的最初目的(意指你可以像“蜂群”一样启动一系列 Agent 来完成任务)。其核心思想是:对于某些任务,一个 Agent 无法包打天下。取而代之,你需要一个分工明确的 Agent 团队,在必要时彼此交接(handoff)

设想一个客服工作流

image.png

图 2.1:客服工作流(示意)

工作流可以拆解如下:

  • 首问代理(First responder agent) :接待来电、理解问题、处理简单 FAQ,并在需要时交接给其它 Agent
  • 账号代理(Account agent) :查询用户订单与状态
  • 技术代理(Technical agent) :修复用户认证问题,为客户开通新的连接线路
  • 升级代理(Escalation agent) :在最后手段时引入人工介入

每个 Agent 都专注于自己的领域,但对终端用户而言,体验却是连贯一致的一次会话。上下文传递、角色切换、错误处理都在 SDK 的编排层内完成(通过 handoffs 原语)。你只需配置一次交接路由,其余的“编舞”就交给框架。代码也只需寥寥几行:

account_agent = Agent(name="Account agent")
technical_agent = Agent(name="Technical agent")
escalation_agent = Agent(name="Escalation agent")
first_responder_agent = Agent(
    name="First Responder Agent",
    handoffs=[account_agent, technical_agent, escalation_agent]
)

极简抽象(Minimal Abstraction)

OpenAI Agents SDK 的指导思想之一是: “尽可能少但足够用的原语” ,让学习门槛更低。SDK 不会叠加一层又一层的新类,而是提供简短且好记的词汇表。实际上,只要你记住这些核心原语及其工作方式,就已经掌握了框架的 80%

这些原语包括:agents、runner、tools、handoffs、guardrails、tracing。我们将在下一节逐一深入,并且本书的章节结构也刻意映射到这些原语——因为逐个讲解它们,是学习该框架的最佳路径。

也就这些而已。没有隐藏的元语言,也没有会生成你看不见代码的不透明运行时。你用纯 Python把 Agent 拼装起来,给少数函数加上 @function_tool 装饰器,然后点击“运行”即可。这种方式带来极快的上手体验:多数开发者午休翻翻文档或示例 notebook,下午就能做出可用原型。

需要权衡的是:这更像一个轻量库,而非庞大的全家桶框架。因此与某些大而全的框架(如 LangChain)不同,OpenAI Agents SDK 不内置上百种即插即用的集成(如文档加载器、记忆存储等);这些概念需要由用户自行实现

Pythonic、可扩展与开源

OpenAI Agents SDK 以 Python 为核心且“说一口地道的 Python”。没有 YAML 清单可折腾、没有私有 DSL 要背、也没有把真实工作藏起来的“元编程魔法”。Agent 就是一个 Python 对象Tool 就是一个带特殊装饰器的普通 Python 函数。你用日常熟悉的 Python 语言结构去编排它们。对于 Python 开发者,这既好用顺手,与 FlaskPydantic 等广受喜爱的极简库在气质上颇为相似。

SDK 默认可用、即刻部署,但也被刻意设计为可扩展。你可以随时“热插拔”自己的组件:

  • 模型:Agent 中使用的模型可替换为任意 LLM,例如本地的 LLaMA(只要它遵循 Chat Completions 标准——这是 OpenAI 针对与基础 LLM 交互制定的标准协议;我们将在第 10 章详述)。正如我们之前讨论的,这个框架对模型完全中立
  • 工具(Tools) :本质上是带装饰器的 Python 函数,因此可以随时替换为另一个函数或托管 API 调用,包括连接到 MCP 服务器
  • 追踪(Tracing) :默认发送到 OpenAI 的 Traces 面板,但也可对接 Azure Monitor Logs、DataDog 等任意遥测工具。
  • 执行循环:甚至连 Agent 的执行循环也是模块化的。高层的 runner 负责重试、步数上限与并发调用;而高级用户可绕过它,直接在现有事件循环或任务队列中驱动更低层的原语。

举例来说,与其调用 Runner.run_sync(agent, input),高级用户可以手动使用 agent.run_step(...) 逐步推进,或通过 agent.get_initial_state()agent.step(...) 自行控制循环。在需要把 Agent 执行与其它异步操作交错进行的场景(如 FastAPI 路由内部)尤其实用,你可以完全掌控时序、并发与资源管理

最后,SDK 是开源的,这意味着它具备完全透明性,并由不断增长的开发者群体持续改进与加固

OpenAI Agents SDK 提供了一个精炼、Pythonic 的框架,专为简化并加速复杂 AI Agent 的创建与编排而生。通过数量不多却力量强大的抽象(agents、runners、tools、handoffs、guardrails、tracing),它让开发者无需与过多样板或隐蔽配置搏斗,就能快速搭建多 Agent解决方案。同时,它与现有 Python 生态高度兼容且易于扩展,既支持即刻部署,也能在需要时进行深度定制,从而更高效地构建可靠的 Agent 系统。

核心原语(Core primitives)

如前所述,OpenAI Agents SDK 只引入少量核心概念(原语,primitives) 来构建 Agent 系统。它们是用该 SDK 开发任意 Agent 应用的“积木块”。

为了理解什么是原语,想象你在设计一个智能家居的机器人助理:能关灯、调恒温器、响应语音指令、并在窗户未关时提醒你。与其从零开始造轮子,SDK 提供一小组基础构件:用于定义 Agent 知道什么(state)能做什么(tools)如何思考(policy) ,等等。它们就是原语。你把这些像组装机器零件一样拼起来,就能得到一个可工作的 Agent。

把原语想成乐高里的标准积木。SDK 以后或许会提供“预制配方”(就像乐高的说明书),但积木本身就是这些原语。

Agent

Agent 原语是 OpenAI Agents SDK 中最基础的概念。本质上,它是对 LLM 的一个高度可配置的包装,使其具备“代理性”(agentic):也就是赋予它角色/系统指令工具接口及其它能让它自主决策、追求目标所需的设置。用该原语实例化一个 Agent 时,可以配置:

  • Name(名称) :标识用途
  • Instructions(指令) :等同上一章讨论的 system prompt,规定 LLM 的角色、目标、行为与人设
  • Model(模型) :驱动 Agent 智能的底层 LLM
  • Tools(工具) :Agent 可调用的一组工具
  • Handoffs(交接) :该 Agent 可委派的其它 Agents 列表

示例:

Customer_service_agent = Agent(
    name="Customer Service Agent",
    model="gpt-4o",
    instructions="""
        You are an AI agent that helps resolve customer issues in a positive cheerful manner.
    """,
    tools=[get_account_information, refund_customer_payment,
        track_customer_order],
)


Agent 还可接收其它有用参数,如 guardrails输出类型等,后文章节会详细介绍。

可以看到,这些组件基本对应上一章所述的 AI Agent 架构。得益于这种可配置性,开发者能快速启动面向特定角色/任务的专业化 Agent

该 Agent 既可以自然语言回答,也可以调用配置的工具。值得一提的是,SDK 仅提供一个 Agent 类;不同于有些框架按 Agent 类型区分多个类,这里行为仅由配置决定

Runner

Runner 原语是 Agent 的“引擎”。上一章我们提到,优秀的 Agent 应用需要具备迭代且自主地求解问题的能力(能根据后续输入不断决策与调整以实现目标)。这种Agent 循环(loop) 能力由该原语内建提供。Runner(也称 Agent Loop)会循环完成:与 LLM 交互、管理工具调用、决定下一步动作并重复此过程。

回顾我们抽象过的伪代码:

读取用户目标并创建行动计划
对计划中的每一步:
    构造行动输入
    执行动作
    获取结果
    将结果加入记忆
    如有必要或尚未达成目标则修改计划
    若目标已达成:
        将输出返回用户

将这段核心逻辑自动化,极大简化了开发者的工作:它把 LLM 交互与工具调用的底层编排抽象掉,让你专注于通过指令定义高层行为、通过工具定义能力,而不用深陷执行循环的机械细节。历史上,管理这个“推理循环”是构建 Agent AI 的难点之一(开发者得自己捕获模型的思维链路并实现循环逻辑)。

调用 Runner 很简单:

result = await Runner.run(agent, "My order number is XYZ - help me figure out where my order is")


Runner.run() 提供 max_turns 参数用于限制 Agent 的循环次数。它像一个安全阀,防止因错误配置或无解任务导致的无限循环。细节将在后续章节展开。

Tools

Tool 原语是 SDK 的核心之一,且以其简洁优雅著称。任意 Python 函数只需加上特定的工具装饰器,即可变成工具。装饰器会让 LLM 通过函数名、docstring 与参数自动理解该工具;当 LLM 决定调用它时,会自动构造所需的参数/模式。

例如,我们写一个根据订单号返回订单状态的函数,并把它注册为工具。装饰器会自动解析其 docstring 与参数,并把相关信息作为系统指令提供给 LLM,使 Agent 知道自己拥有哪些工具、能做什么、需要哪些入参

Customer_service_agent = Agent(
    instructions="""
        You are an AI agent that helps resolve customer issues in a positive cheerful manner.
    """,
    tools=[get_order_status],
)

@function_tool
def get_order_status(order_id: str) -> str:
    """Gets the order status based on order_id
    Args:
        order_id: the order_id of the order
    """
    # API call to get order status
    return order_status

此外,OpenAI Agents SDK 还支持两类额外工具形式:

  • Hosted tools(托管工具) :由 OpenAI 提供并托管的内置工具,如联网搜索、文件检索、图像生成等,也包括连接本地计算机 shell/terminal 或通过MCP 服务器提供的功能。
  • Agents as tools(Agent 作为工具) :将你已实例化的某个 Agent 转换为工具。但实务上更常用的是handoffs 来在 Agents 间交接(携带上下文),而不是把 Agent 当作“函数”调用。

Handoff

Handoff 原语控制 Agent 向其它 Agent 移交/委派的机制,是实现多 Agent 编排的关键(亦是前身 Swarm 的基石特性之一)。通过让 Agents 各司其职(各自具备独立的人设与工具),你可以用专业化 Agent 团队达成目标,而非依赖一个“全能”体。

例如构建一个研究报告 Agent:
A 负责拟定研究计划;将计划交给 B,B 负责联网检索并提炼;再把摘要交给 C,C 依据规格生成终稿。Agents SDK 会顺畅地管理每一次交接。代码上非常直接:

research_plan_agent = Agent(name="Research plan agent")
web_search_agent = Agent(name="Web search agent")
final_report_agent = Agent(name="Final report agent")
research_report_agent = Agent(
    name="Research report agent",
    handoffs=[research_plan_agent, web_search_agent, final_report_agent]
)

Agent 交接工具调用 的差异:

  • 上下文传递:交接时,SDK 会把必要上下文(如对话历史,而不是僵硬的固定参数)传给下一个 Agent,使工作无缝继续
  • 控制权转移:交接将“驾驶权”交给另一个 Agent,后者可调用自己的工具,并按需再交接给第三个 Agent;而工具调用更像是“外包一个子任务”。

Guardrails

Guardrails 原语提供安全护栏,用于对用户输入Agent 输出进行校验。它们与工具类似,以装饰器包装的 Python 函数形式存在,并按你定义的逻辑触发。例如,我们可以设置一个护栏:确保用户确实在向客服 Agent 咨询客服相关问题,而不是随意提问。

@input_guardrail
async def input_guardrail(
    ctx: RunContextWrapper[None], agent: Agent,
    input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
    # 判断输入是否与客服查询相关
    if is_customer_service_query:
        return GuardrailFunctionOutput(
            output_info = "This is a customer query question",
            tripwire_triggered = False,
        )
    else:
        return GuardrailFunctionOutput(
            output_info = "This is NOT a customer query question",
            tripwire_triggered = True,
        )

若护栏校验未通过,就会触发绊线(tripwire)并抛出特定异常。你可以按需处理:提示用户使用不当、或直接终止执行并返回错误码。

try:
    await Runner.run(agent, "What is the meaning of the universe?")
except InputGuardrailTripwireTriggered:
    print("Please enter a customer service related inquiry, not a random question")

护栏在 Agent 领域重要却常被忽视。例如在计算/费用昂贵的场景,先运行输入护栏可避免无谓开销。任何非确定性的自治系统都需要护栏来确保正确运行,而该原语让实现这一机制变得简单。


护栏通常以带装饰器的 Python 函数体现,内部嵌入校验规则;既可作用于用户输入也可作用于返回输出。并且,这些函数本身还可以调用另一个 Agent来审查候选输入/输出是否满足规则。也就是说,除了“Agent 作为工具”,你也可以有“Agent 作为护栏”。

Tracing

Tracing 原语用于观测与调试 Agent 系统:在运行期间捕获与记录详细的执行轨迹,就像 Agent 推理循环的“黑匣子”。包括:每一步决策、工具调用(含参数与返回)、中间消息、多 Agent 的交接等。没有追踪,尤其在复杂/多 Agent 工作流中,要理解为何得到某个结果会非常困难。

SDK 提供内置追踪工具,可手动使用;更常见的是通过 SDK 的集成追踪系统自动启用,并把追踪数据保存到本地或发送到远端后端(如 OpenAI 的 Traces UI,或你自建的观测系统)。

示例:我们想调试客服 Agent 在收到请求时的行为:

from agents import Runner, enable_tracing
await Runner.run(agent, "Please cancel my last order.")

启用追踪后,SDK 会捕捉并记录:

  • 初始用户输入与系统指令
  • 模型的内部推理(thoughts)
  • 所有工具调用(含入参与输出)
  • 触发的任何交接(含完整上下文)
  • 返回给用户的最终响应

这些可在 OpenAI Traces UI 或你偏好的 UI(如 DataDog)中查看。


Tracing 与 Guardrails 搭配极其有力。例如当护栏绊线触发时,追踪能精确定位哪个输入导致问题,以及此前走过的步骤,从而更容易调参或在敏感应用中校验业务逻辑

总结(Summary)

本章我们深入剖析了 OpenAI Agents SDK 及其与众不同之处。你可以看到,它以极简抽象为理念,剥离样板代码、让纯 Python成为主角,同时依然足够强大,能够构建复杂的 AI Agent 与多 Agent 解决方案。我们也看到它完全开源,既便于社区审视,也方便扩展与生态共建。

接着我们回顾了构成 SDK 的核心原语,重点包括:

  • Agent:把 LLM 包装成自治 Agent 的轻薄外衣;携带名称、系统指令、可选的“工具腰带”,以及用于交接的同伴 Agent 列表。
  • Runner:驱动 Agent 迭代推理循环的执行引擎;负责重试与安全边界,防止无休止空转。
  • Tools:带装饰器的普通 Python 函数(或托管 API/Agent),模型可据此识别用途、构造有效参数,并在需要时准确调用。
  • Handoffs:让 Agent 将控制权(连同完整对话上下文)委派给另一 Agent 的编排机制,优雅实现多 Agent 协作。
  • Guardrails:为循环的每一步加上的策略校验,确保输出、工具调用与交接遵循业务与合规边界。
  • Tracing:对每个提示、响应与工具调用进行自动、结构化记录——调试、可观测性与事后分析的必备基础。

有了这套“乐高积木”原语,我们可以用寥寥数行代码在几分钟内搭起实用的 Agent。下一章将搭建开发环境并创建你的第一个 Agent,把以上概念落到实操