1.3. OpenAI Agents SDK 提供了另一种 Skills 实现路径

OpenAI Agents SDK 提供了另一种 Skills 实现路径

2025年3月11日,OpenAI 正式发布了 Agents SDK,将其定位为“从实验走向生产”的轻量级多智能体框架。与此同时,Anthropic 的 Claude Skills 已完成两轮迭代,以声明式能力包的形式在 Claude 生态中沉淀出一套标准化的技能体系。表面上看,二者都在回答同一个关键问题:如何将 AI 能力封装为可复用、可组合的工程单元。但当你真正打开 SDK 文档、写下第一行代码时,你会发现它们走的其实是两条截然不同的路——一条用“Agent 间的手递手通信”编织能力网络,另一条用“能力包的声明式封装”构建可插拔的知识模块。

核心结论先行:
OpenAI Agents SDK 并不是对 Claude Skills 的替代,而是对同一问题的另一种极端解法。它将“技能”内化为 Agent 的推理与工具调用循环,适合需要动态分解任务、跨领域协作的复杂场景;代价是状态管理更黑箱、调试成本更高,且对 Prompt 工程的依赖并未减少。而 Claude Skills 用确定性的声明式配置,把专家知识、工具接口和安全边界一并打包,更适合需要高可控性、可追溯、可审计的生产流水线。

理解这两种路径的本质区别,是你在 2025 年做 AI 能力架构选型时,必须跨越的一道坎。

OpenAI Agents SDK 的核心抽象与薄弱点

Agents SDK 把世界建模成一组相互通信的 Agent。它的核心概念包括 Agent(智能体)Handoff(移交)Guardrails(护栏)Tool(工具)——其中前两者构成了其区别于传统 Function Calling 的骨架。

概念 在 Agents SDK 中的表现 与 Claude Skills 的对比 作者的结论
Agent 一个持久的对话与推理单元,拥有自己的指令、工具集和可能的 Handoff 目标 Skills 没有持久 Agent 概念,每个 Skill 是一个无状态的能力包,由宿主 Agent 按需调度 Agent 的持久性带来了上下文记忆,但也让使用者不得不管理对话生命周期
Handoff 允许一个 Agent 将整个对话上下文移交给另一个 Agent,完成后再移交回来 Skills 之间不存在直接通信,都由顶层 Orchestrator 控制数据流,避免网状依赖 Handoff 是 Agents SDK 最激进的设计,它把控制流写进了生态,但也导致了调试时的“上下文黑洞”
Guardrails 输入/输出检查器,可在 Agent 执行前后插入安全或业务规则 Skills 通过声明的约束字段和工具白名单实现,更偏向配置级而非代码级 Agents SDK 的 Guardrails 更灵活,但需要开发者自行实现逻辑;Skills 的安全性更“开箱即用”
工具封装 任意 Python 函数 → 自动 Schema 生成,支持 Pydantic 验证 工具定义在 YAML 或 JSON 中,由平台解析,与语言无关 Python 原生工具开发效率高,但跨语言复用性差;Skills 声明式工具更易被不同平台消费

这个表格里能读出两条关键信息:Agents SDK 把编排权交给了 Agent 自己,而 Skills 把编排权牢牢抓在开发者或平台手中。

在 Agents SDK 里,一个典型流程可能是:入口 Agent 理解用户意图 → 将任务 Handoff 给「数据分析 Agent」→ 这个 Sub-Agent 在沙盒中运行 Python 代码 → 结果回传入口 Agent → 再 Handoff 给「报告生成 Agent」——整个过程像一场接力赛,SDK 的内置 Agent 循环(built-in agent loop)自动处理工具调用、结果回传和任务继续,开发者只需要定义每个 Agent 的指令与工具。但这种便利性的代价是:一旦接力棒(上下文)在传递中产生错误,你很难像调试一个单体函数那样直接定位问题。

相比之下,Claude Skills 的声明式模型没有“接力”这一说。每个 Skill 是一个自包含的 YAML 文件,描述了它能做什么、需要什么输入、输出什么、以及它的使用条件和限制。宿主 Agent(无论是 Claude 还是其他兼容平台)在推理时决定调用哪个 Skill,但调用过程更像一次纯函数求值:输入进,结果出,无状态,无副作用。这种差异在生产环境中会被成倍放大——我们马上就会在代码层面看到它。

代码风格对比:Python SDK vs 声明式配置

为了让差异具象化,我们假设一个常见需求:搭建一个能响应“最新销售报告”查询的 AI 功能,它需要先调用内部 API 拉取原始数据,再做数据聚合,最后返回自然语言结论。我们分别用两种范式实现。

方式一:OpenAI Agents SDK(命令式)

from agents import Agent, Runner, function_tool, handoff

@function_tool
def fetch_sales(start_date: str, end_date: str) -> dict:
    """调用内部 API 拉取销售原始数据"""
    # 真实实现略
    return {"products": [...]}

@function_tool
def aggregate_sales(raw: dict) -> dict:
    """对原始数据执行聚合计算"""
    return {"total": 125000, "top_product": "A23"}

# 数据获取 Agent
data_agent = Agent(
    name="data_fetcher",
    instructions="根据用户时间范围调用 fetch_sales,成功后 handoff 给分析 agent。",
    tools=[fetch_sales],
    handoffs=[analysis_agent]  # 定义移交目标
)

# 分析 Agent
analysis_agent = Agent(
    name="analyst",
    instructions="接收来自 data_fetcher 的原始数据,调用 aggregate_sales,然后把结果 handoff 给报告 agent。",
    tools=[aggregate_sales],
    handoffs=[report_agent]
)

# 报告 Agent
report_agent = Agent(
    name="reporter",
    instructions="基于分析结果生成自然语言报告,直接返回给用户。",
    tools=[],
)

# 入口 Agent
entry_agent = Agent(
    name="orchestrator",
    instructions="接收用户查询,判断需要销售报告时 handoff 给 data_fetcher。",
    handoffs=[data_agent]
)

result = await Runner.run(entry_agent, input="上周的销售情况")

这段代码展现了一个清晰的“拆分-移交”链。它使用了 Agents SDK 的 Handofffunction_tool 装饰器,自动处理 Schema 生成和数据流转。开发者在本地 Python 环境中就能写好全部逻辑,调试工具也相对熟悉(例如 pdb、logging)。

方式二:Claude Skills(声明式)

在 Skills 方式下,同样功能会被拆解为多个能力包,但编排逻辑不写在代码里,而是由宿主 Agent 根据声明式描述决定调用顺序。一个 Skills 定义可能像这样:

# skill: sales_data_fetcher
name: sales-data-fetcher
description: 从内部系统拉取给定时间范围的原始销售数据。
tools:
  - id: fetch_sales
    description: 调用内部 API。
    parameters:
      start_date: string
      end_date: string
    output: raw_sales_json
conditions:
  - when: 用户要求查询销售数据
    then: 必须使用此 skill
# skill: sales_aggregator
name: sales-aggregator
description: 对原始销售数据执行聚合计算,返回汇总结果。
tools:
  - id: aggregate
    description: 聚合计算
    parameters:
      raw: raw_sales_json
    output: aggregated_json
# skill: report_generator
name: report-generator
description: 将聚合后的销售数据生成自然语言报告。
tools:
  - id: generate_report
    description: 生成报告
    parameters:
      aggregated: aggregated_json
    output: natural_language_text

Skill 之间不存在直接引用。宿主 Claude Agent 通过读取这些声明文件,在推理时动态规划调用顺序,并将各 Skill 的输出作为下一个 Skill 的输入。整个编排行为完全由 Prompt 和工具描述驱动,没有硬编码的控制流

开发体验与维护成本

维度 OpenAI Agents SDK (Python) Claude Skills (声明式) 作者的结论
上手速度 Python 开发者几乎零门槛,10 分钟可跑通 demo 需理解 YAML 结构和平台约束,初期投入更大 短期原型阶段,SDK 更快
控制流可见性 控制流显式写在代码中,方便调试 控制流隐式,由 LLM 推理决定,调试需检查对话日志 前者更适合逻辑确定性强的场景
可维护性 代码量随 Agent 数膨胀;Handoff 嵌套深时复盘困难 每个 Skill 是独立文件,修改不影响其他模块 长期维护中,声明式更抗熵增
跨平台复用 强依赖 Python 生态,其他语言需重写 YAML/JSON 描述,只要平台兼容即可复用 跨国队或跨服务时,Skills 优势明显
Prompt 依赖 每个 Agent 的指令仍需精确调试 Skill 描述被翻译成工具注释,但同样依赖良好的 Prompt 工程 两者都未能摆脱 Prompt 黑洞,但 Skills 将影响面限制在单个模块内

我们在这里面临的不是“哪个更好”的问题,而是“你更愿意在哪个层面承担复杂度”。选择 Agents SDK,你承担的是架构层面的复杂度——你要设计 Agent 间的边界、定义 Handoff 的时机、处理上下文膨胀。选择 Skills,你承担的是声明式配置与 LLM 推理不确定性之间的张力。接下来,我们把镜头拉远,看看这两种选择在生产环境中会演化成什么模样。

生产就绪度的真实差距

任何一个 SDK 或框架,从“能跑”到“能扛住生产流量”,中间隔着三个硬指标:流式与实时性、故障自愈、可观测性。我们对照一下两者在这三条线上的现况。

流式处理

Agents SDK 在最新的 Chat Completions / Responses API 基础上原生支持流式传输,你可以对 Agent 的每一次工具调用和文本生成启用 stream=True,并实时推送到前端。Claude Skills 的宿主 API 同样支持流式,但因为 Skill 是“调用即完成”的封装,流式交互的粒度只能到 Skill 级别,无法嵌入 Skill 内部的中间步骤。这让 Agents SDK 在需要逐步展示推理过程的聊天应用(比如逐步显示“查询 API → 得到结果 → 分析 → 报告”)中更自然。

错误重试与降级

Agents SDK 内置了简单的重试机制(基于 API 返回状态码),并提供沙盒 Agent(Sandbox Agent)来隔离高风险任务。但定制重试策略(如指数退避、条件重试)仍要由开发者自己实现。Claude Skills 的错误处理依赖平台,如果平台稳定,你几乎不需要操心;但如果平台没有暴露重试钩子,你就只能干瞪眼。从当前调研资料看,两者在自动降级和熔断方面的能力都不够成熟,都需要引入外部中间层(如你的网关或编排框架)。

可观测性

这是差距最大的地方。Agents SDK 的“内置 Agent 循环”是一把双刃剑:它可以自动记录工具调用和 Handoff 过程,但这些日志的结构化程度有限,且缺乏开箱即用的 trace ID 跨 Agent 串联。你通常需要自行集成 OpenTelemetry 或使用 OpenAI 的 Dashboard 来补全监控。而 Claude Skills 由于本身是无状态的,每次 Skill 调用都会返回清晰的输入/输出对,你可以用 API 网关直接截获这些请求,做完整的审计和策略检测。这对于合规性要求高的企业场景,是一个实打实的加分项。

生产就绪度对比速览:

能力项 OpenAI Agents SDK Claude Skills 作者的结论
流式响应 Agent 级别原生支持 Skill 级别支持,无法流式输出内部步骤 SDK 更适合渐进式 UI
错误重试 基础重试,需自行扩展 依赖平台;较难自定义 都需要额外设计容错层
沙盒/隔离 内置沙盒 Agent Skill 运行在平台沙箱内 两者安全性都足够
监控与追踪 日志有结构,但跨 Agent 追踪需自建 请求/响应天然可记录 Skills 的审计成本更低
会话管理 内建 Sessions 机制,需管理生命周期 无状态,每次调用独立 SDK 的状态管理更容易出 bug

看完这些,你可能会形成一个印象:Agents SDK 更灵活但更“重”,Skills 更克制但更“稳”。 这个印象基本正确。但为了不让决策停留在直觉层,我们最后把它固化为可操作的建议。

结论与选型建议

回到开头的那句话:它们是对同一问题的两种极端解法。 我们无法断言哪种方法绝对领先,但可以根据团队的技能栈、产品的可预测性需求,以及你对调试成本的承受力,做出一张清晰的决策地图。

对比维度 OpenAI Agents SDK Claude Skills
核心编排模型 Agent 间 Handoff(命令式) 声明式能力包 + LLM 调度
适合的任务特征 多步推理、动态分解、多 Agent 协作 明确步骤、可枚举工具、需审计安全
开发调试难度 中高(Agent 间上下文调试困难) 中(单 Skill 调试简单,多 Skill 协作需观察 Prompt)
生产运维成本 需要自建监控、重试、状态管理 依赖平台 SLA,运维边界清晰
生态系统兼容性 强绑定 OpenAI 模型(虽支持其他 API 但 Handoff 特性可能受限) 理论上模型无关,但目前主要在 Claude 上实现

具体场景推荐:

  1. 你的团队是 Python 原生,需要快速搭建一个能动态决定“接下来让哪个 Agent 干活”的智能体系统,并且可以接受在调试阶段投入较多时间排查 Handoff 问题 → 选 OpenAI Agents SDK
  2. 你需要的是为已有的 Claude 工作流增加可复用的知识模块,每个模块独立测试、独立上线,且要求每次调用行为都可审计、可解释 → 选 Claude Skills
  3. 你正处在一个混合生态中(既有 OpenAI 模型也有 Claude,或者未来可能切换模型提供商),并且看重能力模块的跨平台移植性 → 优先考虑声明式 Skills 方向,或者将 Agents SDK 的工具封装也用声明式描述的方式组织,以降低锁定风险。

无论选择哪条路,有一个准则不会变:不要把控制流全部扔给模型你自己又不管。 在 Agents SDK 里,这意味着你要主动限制 Handoff 深度,为每个 Agent 写清退出条件;在 Skills 里,这意味着你要在声明文件中明确使用条件和权限边界,避免模型在“自由发挥”中偏离预期。

在下一章,我们会跳出这两个具体实现,站在更高的视角俯瞰整个多智能体框架的演进路线。CrewAI、AutoGen、LangGraph 各自带着不同的设计主张和典型故障模式走上牌桌,而你将学会如何从“编排方式”和“故障模式”两个维度,为后续的深度选型打下基础。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 查看所有版本


暂无话题~