做 Agent 项目最怕的一件事,不是模型不够聪明,而是架构选错了。我见过太多团队在 Demo 阶段用一套简单的对话循环跑得飞快,一上生产就发现工具调用乱套、上下文爆炸、多轮任务中途断链、成本失控。问题往往不在模型本身,而在于一开始就没搞清楚 OpenAI 这套东西里,Agents API、Agents SDK、Responses API 到底各自解决什么问题、边界在哪、什么时候该用哪个。
这三个名字听起来像同一类东西,实际上处在完全不同的抽象层级。Responses API 是底层的能力入口,Agents SDK 是帮你把 Agent 逻辑写清楚的编排框架,而 Agents API(平台侧的 Agent 配置能力)则是把 Agent 作为一种可托管资源来管理。把它们混为一谈,选型必然翻车。这篇内容我会从实际生产架构的角度,把三者的定位、适用场景、组合方式和踩坑经验讲透,适合正在做 Agent 架构选型、或者已经写了一版想重构的开发者参考。
1. 先把三个东西的抽象层级摆正
选型混乱的根源,是大家习惯性地把这三个名词当成"三个可以互相替代的选项"。实际上它们不是并列关系,而是不同层次的东西。你完全可能在一个生产系统里同时用到三者,也可能只用其中一个就够。搞清楚层级,后面的决策才有依据。
1.1 Responses API 是能力底座,不是 Agent 框架
Responses API 本质上是 OpenAI 提供的一个统一的模型交互接口,它把过去 Chat Completions 那套消息数组的交互方式,升级成了更结构化的输入输出。它原生支持工具调用、内置工具(比如网页检索、文件检索、代码执行这类托管工具)、多模态输入、以及有状态的对话延续。
关键点在于:Responses API 本身不负责"Agent 该怎么决策"。它给你的是"一次请求里,模型可以调用工具、可以返回结构化结果、可以保留状态"这些原子能力。至于要不要循环、循环几次、工具结果怎么回灌、什么时候终止,这些编排逻辑得你自己写。
我常打一个比方:Responses API 像是给你一套很趁手的电动工具,钻头、锯片、砂轮都有,但怎么组装成一条流水线,是你的事。很多人误以为用了 Responses API 就等于有了 Agent,结果写出来的东西就是一个 while 循环套 API 调用,工具一多就乱。
它最适合的场景是:你的 Agent 逻辑相对简单、可控,你希望完全掌控编排细节,不想引入额外框架的抽象成本。比如一个只做"检索 + 总结"的问答机器人,或者一个固定三步走的处理流程,用 Responses API 直接写反而最干净。
1.2 Agents SDK 解决的是"编排"这件事
Agents SDK 是官方提供的轻量级编排框架,它的核心价值是把 Agent 开发里那些重复出现的模式抽象出来:Agent 定义、工具注册、handoff(任务移交)、guardrails(护栏)、会话状态管理、追踪(tracing)。
它要解决的真实痛点是:当你手写编排逻辑时,代码会迅速膨胀成一坨难以维护的状态机。工具调用的解析、异常处理、多 Agent 之间的转交、上下文裁剪,这些如果每次都自己写,既容易出 bug,也没法复用。Agents SDK 把这些模式固化成了一套原语,你只需要声明"有哪些 Agent、每个 Agent 有哪些工具、什么条件下移交给谁",剩下的循环和状态管理它帮你兜住。
这里有个容易被忽略的点:Agents SDK 是框架,不是服务。它跑在你自己的进程里,用的是你配置的模型接口。它不托管任何东西,也不替你管理部署。所以它的灵活性很高,但运维责任也在你自己身上。
它适合的场景是:Agent 逻辑有明显分支、需要多个角色协作(比如一个分诊 Agent 把任务派给不同的专业 Agent)、需要护栏做输入输出校验、需要可观测性来调试。这类需求手写会非常痛苦,用 SDK 能省下大量胶水代码。
1.3 Agents API 是把 Agent 当成可托管资源
平台侧的 Agents API(也就是在平台里配置 Agent 的那套能力)走的是另一条路:它把 Agent 的配置(模型、指令、工具、知识库)作为一种持久化的资源存在平台上,你通过 API 去创建、更新、调用它。调用时你只需要给一个 Agent 的标识和输入,平台负责按配置执行。
这条路的核心优势是"配置与代码分离"。Agent 的行为定义不再散落在你的代码库里,而是集中在平台上,产品、运营甚至非工程角色都能参与调整。对于需要频繁调优指令、快速迭代 Agent 行为的团队,这个模式很省事。
代价是灵活性。平台托管意味着你能控制的东西变少了,一些非常定制化的编排逻辑、特殊的工具执行环境,可能就没法完全按你的想法来。它更适合标准化程度高、需要快速上线和集中管理的场景。
把三者放一起对比,层级关系就清楚了:
| 维度 | Responses API | Agents SDK | Agents API(平台托管) |
|---|---|---|---|
| 抽象层级 | 模型交互接口 | 编排框架 | 托管资源 |
| 运行位置 | 平台侧推理 | 你的进程内 | 平台侧执行 |
| 编排控制权 | 完全自己写 | 框架提供原语 | 平台按配置执行 |
| 配置存放 | 代码里 | 代码里 | 平台上 |
| 灵活性 | 最高 | 高 | 中 |
| 上手成本 | 中(要自己搭) | 中 | 低 |
| 适合团队 | 追求极致可控 | 需要复杂编排 | 需要快速迭代 |
注意:这三者不是"选一个"的关系。很多生产系统是 Agents SDK 做编排 + Responses API 做底层调用,或者平台托管 Agent 处理标准场景 + 自建 SDK 处理复杂场景的混合模式。
2. 生产环境真正卡人的几个决策点
知道了层级,接下来是实际选型时最纠结的几个问题。这些不是理论问题,是我在真实项目里反复遇到的岔路口。
2.1 状态管理:谁来记住上下文
Agent 和普通对话最大的区别,是它要在多轮工具调用之间维持状态。这个状态包括对话历史、工具执行结果、中间推理过程。状态放哪、怎么裁剪,直接决定了你的系统能不能撑住长任务。
Responses API 提供了服务端的状态延续能力,你可以用 previous_response_id 把上一轮的响应关联起来,平台帮你保留上下文。这在简单场景下非常省事,不用自己维护消息数组。但要注意,状态存在平台侧意味着你对上下文的可见性和裁剪控制变弱了,长对话累积的 token 成本需要你自己盯。
Agents SDK 则是把会话状态放在你的进程里管理,它提供了 session 的概念来持久化对话历史。好处是你完全掌控,可以自定义裁剪策略、可以做摘要压缩、可以把状态存到自己的数据库。坏处是你得自己实现持久化和并发控制,多实例部署时还要考虑状态共享。
平台托管 Agent 的状态由平台管理,你基本不用操心,但也基本没法干预。对于需要精细控制上下文成本的高并发场景,这可能是个隐患。
我的经验是:短任务、低并发、追求快速上线,用平台托管的状态;长任务、需要成本控制、需要审计上下文,自己管状态。别小看这个选择,上下文管理做不好,Agent 跑到第十轮就开始胡言乱语或者成本飙升。
2.2 工具执行:在哪里跑、谁来兜底
工具调用是 Agent 的心脏。工具在哪执行、失败了怎么办、超时怎么处理,这些细节决定了系统的健壮性。
Responses API 支持两类工具:一类是平台托管的内置工具(比如检索、代码执行),你声明了平台就帮你跑;另一类是自定义函数工具,模型返回调用意图,你的代码负责实际执行并把结果回灌。后者给了你完全的灵活性,但也意味着所有异常处理、重试、超时都得自己写。
Agents SDK 在工具这块做了不少封装,函数工具的注册、参数校验、执行、结果回传都有约定俗成的模式,还支持把工具执行放到特定的运行环境里。它让工具的定义更声明式,减少了样板代码。
平台托管 Agent 的工具通常限制在平台支持的类型里,自定义工具需要走特定的接入方式。灵活度受限,但胜在稳定,平台帮你处理了执行环境的隔离和容错。
这里有个血泪教训:工具执行一定要有超时和幂等设计。我见过一个 Agent 因为某个外部 API 卡住,整个任务链挂死,最后靠人工重启。无论用哪套方案,工具层都要自己加超时、重试上限和失败降级,别指望框架或平台帮你兜住所有情况。
2.3 可观测性:出问题时你怎么查
Agent 的调试难度远高于普通接口,因为它的执行路径是动态的、非确定的。同样一个输入,模型可能走完全不同的工具调用链。没有好的追踪能力,出了问题你只能干瞪眼。
Agents SDK 内置了 tracing 能力,能把一次 Agent 运行里的每一步(模型调用、工具调用、handoff、护栏检查)都记录下来,形成完整的执行轨迹。这在排查"为什么 Agent 做了这个奇怪决策"时非常关键。
Responses API 层面你能拿到的是每次请求的输入输出和工具调用记录,但跨多轮的完整链路需要你自己串联。平台托管 Agent 一般提供运行日志,但粒度取决于平台。
选型时一定要把可观测性当成硬指标。一个没有追踪能力的 Agent 系统,上线后就是黑盒,出了问题排查成本极高。如果选了自己写编排,务必在早期就把日志和追踪埋点做进去,别等出事了再补。
3. 三种典型生产架构的落地方式
理论讲完,来看三种我实际用过或见过的架构组合,以及它们各自适合什么样的团队和业务。
3.1 纯 Responses API 手写编排:适合小而美的场景
这套方案的核心是:不引入任何框架,直接用 Responses API 的循环来驱动 Agent。伪代码大概长这样:
def run_agent(user_input, tools, max_turns=10):
response = client.responses.create(
model="gpt-4o",
input=user_input,
tools=tools,
)
turns = 0
while turns < max_turns:
tool_calls = extract_tool_calls(response)
if not tool_calls:
return extract_final_text(response)
tool_results = []
for call in tool_calls:
result = execute_tool(call.name, call.arguments)
tool_results.append(build_tool_result(call.id, result))
response = client.responses.create(
model="gpt-4o",
previous_response_id=response.id,
input=tool_results,
tools=tools,
)
turns += 1
return "达到最大轮次限制"
这套写法的好处是透明,每一行你都知道在干什么,没有任何黑盒。适合工具数量少(三五个以内)、流程相对固定、团队想完全掌控细节的场景。
坑在于:一旦工具变多、出现分支逻辑、需要多角色协作,这个循环会迅速膨胀。你会开始写一堆 if-else 来判断该走哪条路,然后发现自己在重新发明 Agents SDK。所以我的建议是,如果预判到 Agent 逻辑会复杂化,别硬扛,早点上框架。
3.2 Agents SDK 编排 + Responses API 底层:复杂场景的主力方案
这是目前我认为最平衡的生产方案。用 Agents SDK 定义 Agent、工具、handoff 和护栏,底层模型调用走 Responses API。SDK 负责编排的骨架,Responses API 负责单次交互的能力。
一个典型的多 Agent 结构是这样的:一个分诊 Agent 负责理解用户意图,根据意图 handoff 给不同的专业 Agent(比如订单查询 Agent、售后处理 Agent、技术支持 Agent),每个专业 Agent 有自己的工具集。护栏负责在输入和输出两端做校验,防止越权或不当内容。
from agents import Agent, Runner, function_tool
@function_tool
def query_order(order_id: str) -> str:
"""根据订单号查询订单状态"""
return order_service.get(order_id)
order_agent = Agent(
name="订单助手",
instructions="你负责处理订单相关查询,只回答订单问题。",
tools=[query_order],
)
triage_agent = Agent(
name="分诊",
instructions="判断用户意图,订单问题移交给订单助手。",
handoffs=[order_agent],
)
result = Runner.run_sync(triage_agent, "我的订单到哪了")
这套方案的价值在于:编排逻辑声明式,可读性高;handoff 让多 Agent 协作变得自然;护栏和追踪开箱即用。代价是引入了框架依赖,需要理解 SDK 的心智模型。
我踩过的坑是:handoff 不是越多越好。早期我设计了一个五六个 Agent 互相转交的结构,结果调试时链路长得吓人,一个简单问题绕了三四个 Agent。后来收敛成"一个分诊 + 少量专业 Agent"的扁平结构,效果好很多。Agent 数量要克制,能一个搞定的别拆成三个。
3.3 平台托管 Agent + 自建兜底:快速上线与深度定制的混合
对于需要快速验证、或者有非工程角色参与调优的场景,平台托管 Agent 很香。产品经理可以直接在平台上改指令、调工具,改完即时生效,不用等发版。
但纯托管的问题在于天花板。当业务出现平台不支持的定制需求时,你会被卡住。所以成熟团队往往走混合路线:标准场景用托管 Agent 快速覆盖,复杂或特殊的场景用自建 SDK 方案兜底,两者通过统一的入口路由。
这套架构的关键是路由层要设计好,明确哪些请求走托管、哪些走自建,避免逻辑重叠和状态割裂。我见过一个团队因为路由规则没理清,同一个用户的问题被两个系统分别处理,结果给出矛盾的回答,体验很差。
4. 选型时最容易踩的四个坑
前面讲了架构,这里集中说说选型过程中反复出现的坑。这些坑的共同特点是:Demo 阶段完全看不出来,一上生产就爆发。
4.1 把 Demo 的简单循环直接搬上生产
Demo 阶段大家往往用最简单的循环,工具就一两个,输入也很规整,跑起来丝滑。于是有人觉得"Agent 不过如此",直接把这套代码往生产搬。结果真实用户的输入千奇百怪,工具调用频繁失败,多轮任务中途断链,系统立刻崩盘。
根本原因是 Demo 和生产的复杂度不在一个量级。生产要考虑:并发、超时、重试、幂等、成本、审计、降级。这些在 Demo 里一个都没有。我的建议是,Demo 验证完概念后,立刻按生产标准重构一遍,把状态管理、工具容错、可观测性补齐,别心存侥幸。
4.2 忽视 token 成本,上下文无限膨胀
Agent 的多轮工具调用会让上下文快速膨胀。每一轮的工具结果都塞进上下文,几轮下来 token 消耗惊人。我见过一个 Agent 单次任务消耗几十万 token,成本直接失控。
控制手段有几个:一是对工具结果做裁剪,只保留关键字段,别把整个 API 返回原样塞进去;二是对历史对话做摘要压缩,超过一定轮数就把早期内容总结成一段;三是设置最大轮次上限,防止死循环。这些策略无论用哪套方案都要自己实现,框架和平台不会替你省钱。
4.3 工具设计得太"胖"
新手常犯的错是把工具设计得功能很全,一个工具干好几件事,参数一大堆。结果模型经常传错参数,或者搞不清该用哪个工具。
正确的做法是工具要"瘦"且语义单一。一个工具只做一件事,名字和描述要清晰到模型一看就懂。参数尽量少,能用枚举就别用自由文本。工具描述里要写清楚什么时候用、什么时候不用。这些细节直接决定了工具调用的准确率。我实测下来,把工具拆细、描述写清楚,调用成功率能提升一大截。
4.4 没有护栏,输出不可控
Agent 直接面向用户时,输出必须可控。没有护栏的系统,模型可能输出不当内容、可能泄露不该泄露的信息、可能执行危险操作。护栏要在输入和输出两端都做:输入侧过滤明显恶意的请求,输出侧校验格式和内容合规性。
Agents SDK 提供了护栏原语,用起来很方便。如果自己写编排,也要在关键节点加校验。别觉得"模型应该不会乱来",生产环境里什么输入都可能出现,护栏是底线。
5. 我的选型决策清单
讲了这么多,最后给一个可以直接对照的决策思路。选型没有标准答案,但有几个问题问清楚,方向就明确了。
先问自己几个问题:Agent 的逻辑复杂度如何?是固定几步走,还是有明显分支和多角色协作?如果逻辑简单,Responses API 手写就够;如果复杂,上 Agents SDK。团队里有没有非工程角色需要参与调优?如果有且需求标准化,考虑平台托管。对上下文成本和可观测性的要求有多高?要求高就自己管状态、自己埋追踪。
再考虑演进路径。我的建议是从简到繁:先用 Responses API 把核心逻辑跑通,验证价值;当编排复杂度上来后,迁移到 Agents SDK;如果出现需要集中管理和快速迭代的标准化场景,再引入平台托管。不要一上来就上最重的方案,过度设计同样是坑。
还有一个现实因素:团队的技术储备。Agents SDK 需要理解它的心智模型,平台托管需要熟悉平台的配置方式。选团队能驾驭的方案,比选理论上最优的方案更重要。一个用不起来的先进架构,不如一个用得顺手的简单架构。
最后分享一个我自己的体会:Agent 架构选型不是一次性的决定,而是随着业务演进的持续调整。我做过的一个项目,最开始是纯 Responses API,半年后迁到 Agents SDK,最近又把一部分标准场景挪到了平台托管。每次迁移都是因为业务需求变了,而不是因为原来的方案"错了"。所以别纠结于一次选对,选一个能平滑演进的起点,比什么都重要。
3351




被折叠的 条评论
为什么被折叠?



