OpenAI Agents SDK 是 OpenAI 面向 agentic AI 应用推出的一套 Python 框架。它不是另一个简单的 API wrapper,也不是把提示词、工具调用和多轮对话随意拼在一起的示例项目。按照仓库文档里的定位,它是 OpenAI 早期实验项目 Swarm 的生产化升级,目标是用尽量少的核心原语,把真实 Agent 应用里最常见的几件事放到同一个运行时里:模型调用、工具执行、多 Agent 协作、上下文管理、安全校验、人工介入、流式输出、运行追踪,以及面向文件系统长任务的 SandboxAgent。
如果换一个更工程化的角度看,它也可以被理解为 OpenAI 把 Agent harness 实践抽象成开发者可用 SDK 的结果。所谓 harness,不只是“给模型几个工具”,而是围绕模型建立一套受控执行外壳:它提供上下文、文件、工具、审批、状态、日志和恢复机制,让模型在明确边界内行动。普通 Agent 侧重模型、工具和多 Agent 编排;SandboxAgent 则更直接继承了 harness 思路,把文件系统、shell、patch、snapshot、审批和运行状态纳入受控执行环境。
如果只看最小示例,Agents SDK 很容易被误解成“创建一个 Agent,然后调用 Runner”。但真正有价值的地方不在这个 hello world,而在它承认了一个现实:一个能落地的 Agent 应用,通常不只是一次模型请求。它需要在多个模型步骤之间保持状态,决定什么时候调用工具,什么时候把工具结果交还给模型,什么时候把任务交给另一个专门的 Agent,什么时候中断并等待人类审批,什么时候把运行过程记录下来用于调试和评估。Agents SDK 把这些流程收束成一个可组合的运行模型。
这篇文章基于当前 openai-agents-python 仓库的 README、docs、examples 和源码结构,面向还没有系统使用过 Agents SDK 的开发者,介绍它解决的问题、核心抽象、工具体系、多 Agent 编排方式,以及新近被放到显眼位置的 SandboxAgent。
为什么需要 Agents SDK
直接使用 Responses API 或 Chat Completions API 时,开发者拥有最大的控制权。你可以自己构造消息、自己发送请求、自己解析工具调用、自己存储上下文、自己处理重试和异常。这种方式很适合短链路任务:输入一个问题,返回一个回答;或者在一层应用逻辑里做少量确定性的模型调用。
但 Agent 应用的复杂性通常来自“模型调用之外”。一个客服 Agent 需要先判断问题类型,再查订单、查政策、必要时转交退款专员;一个研究 Agent 需要搜索资料、读取文件、调用代码分析数据、汇总报告;一个代码 Agent 需要打开仓库、理解任务、编辑文件、运行测试、再根据失败信息继续修复。这些流程里,模型请求只是其中一个节点,真正难的是模型周围的 harness:它要把外部世界变成模型可以安全使用的工具面,同时把模型行为约束在应用能审计、能恢复、能回滚的范围里。其他同样重要的部分包括:
- 如何把 Python 函数、MCP 工具、OpenAI 托管工具和本地执行能力暴露给模型。
- 如何在工具调用之后,把结果追加回上下文并继续下一轮推理。
- 如何让一个 Agent 调用另一个 Agent,或者把对话控制权交给另一个 Agent。
- 如何在输入、输出和工具调用边界做校验。
- 如何在多轮运行之间保存历史,或者使用 OpenAI server-managed conversation。
- 如何追踪一次运行中的模型生成、工具调用、handoff 和 guardrail。
- 如何让 Agent 在真实文件系统中做长任务,而不是只在 prompt 里“假装”自己能编辑文件。
Agents SDK 的价值就在这里。它没有把 Agent 应用抽象成复杂的图编排 DSL,而是保留 Python-first 的写法,用少数核心对象覆盖常见流程。你仍然用普通 Python 函数、类、asyncio 和上下文对象组织业务代码,但把最容易重复造轮子的 Agent loop、工具派发、session、tracing 和 handoff 交给 SDK。换句话说,它把“每个团队都要自己写一遍的 Agent harness”沉淀成了框架能力。
从这个角度看,Agents SDK 和底层 API 不是互斥关系。Responses API 更像模型和工具能力的底层接口;Agents SDK 则是在其上提供一层应用运行时。当你只需要一次短问答,直接调用 API 更轻;当你的应用进入多步骤、多工具、多 Agent 和可观测性的范围,SDK 的收益会明显变大。
最小可用模型:Agent 加 Runner
Agents SDK 最小的心智模型只有两个对象:Agent 和 Runner。Agent 描述“谁在工作”,包括名称、指令、模型、工具、输出类型、guardrails 和 handoffs;Runner 负责“如何运行”,包括调用模型、执行工具、处理 handoff、维护 turns,直到得到最终输出或触达限制。
一个最小例子大致是这样:
import asyncio
from agents import Agent, Runner
async def main():
agent = Agent(
name="Assistant",
instructions="You only respond in haikus.",
)
result = await Runner.run(agent, "Tell me about recursion in programming.")
print(result.final_output)
if __name__ == "__main__":
asyncio.run(main())
这里的 Agent 并没有启动任何东西,它只是一个配置对象。真正的执行发生在 Runner.run。根据 src/agents/run.py 中的说明,Runner 的循环大致是:
- 使用当前 Agent 和输入调用模型。
- 如果模型产生最终输出,结束运行。
- 如果模型触发 handoff,切换到新的 Agent 并继续。
- 如果模型产生工具调用,执行工具,把工具结果加入输入,再继续下一轮。
- 如果超过
max_turns,抛出MaxTurnsExceeded,除非调用方配置了对应错误处理。
这个循环就是 Agent 应用中最基础但也最容易写乱的部分。SDK 把它固化下来,并让工具、handoff、guardrail、session、streaming 和 tracing 都围绕这个循环工作。
Runner 提供了三种常见调用方式:run 是 async 版本,run_sync 在同步代码里使用,run_streamed 用于流式消费运行事件。对应用层来说,这意味着你可以从最简单的阻塞式脚本开始,也可以接入 Web 服务、后台任务或实时界面。
Agent:把模型变成可配置的工作单元
在 Agents SDK 里,一个 Agent 是“带有指令、工具和约束的模型工作单元”。它不是某种远程实体,也不是独立进程。它更接近一个可复用的角色定义:当 Runner 需要它时,才把这个定义解析成一次或多次模型请求。
Agent 上最关键的字段包括:
instructions:Agent 的系统指令,可以是字符串,也可以是根据上下文动态生成的函数。model:该 Agent 使用的模型,可以是字符串,也可以是自定义Model实现。model_settings:模型参数配置,例如采样、reasoning 或工具选择相关设置。tools:Agent 可用的工具列表,包括函数工具、OpenAI 托管工具和本地 runtime tools。mcp_servers和mcp_config:用于把 MCP server 暴露的能力接入 Agent。handoffs:这个 Agent 可以转交给哪些其他 Agent。input_guardrails和output_guardrails:对输入和最终输出做校验。output_type:期望的结构化输出类型,可以结合 Pydantic、dataclass 或 TypedDict 使用。tool_use_behavior:控制函数工具调用之后是否继续让模型处理结果,或直接把工具输出当最终结果。
这种设计的好处是,Agent 的行为边界比较清楚。比如一个“订单查询 Agent”可以只持有订单相关工具和输出类型;一个“退款 Agent”可以带有更严格的审批规则;一个“写作 Agent”可以没有外部工具,只负责改写和总结。多 Agent 协作时,每个 Agent 的 prompt 和工具面都可以保持较小,从而减少“一个万能 Agent 什么都知道、什么都能做”的复杂性。
同时,Agent 是泛型的,可以绑定一个应用自定义 context。这个 context 会传给工具、guardrails、hooks 等运行时回调。实际业务里,context 通常可以放用户身份、租户信息、数据库连接、权限对象、请求 ID 等本地依赖。这样,模型看到的是工具 schema 和必要的上下文描述,而真正敏感的执行依赖仍然在你的 Python 进程里。
Runner:Agent loop 的运行时
Runner 是 Agents SDK 的运行入口。它的职责不是简单地调用一次模型,而是管理完整工作流。文档把 Runner 的生命周期描述为一个 loop:模型生成结果,SDK 判断结果类型,如果需要工具就执行工具,如果需要 handoff 就切换 Agent,如果已经得到最终输出就返回。
这个 loop 让开发者不用在每个项目里重复写以下逻辑:
- 解析模型返回的 tool calls。
- 找到对应 Python 函数或 MCP 工具并执行。
- 把工具结果转回模型输入。
- 在 streamed 和 non-streamed 两条路径上维持相同行为。
- 处理 handoff 后当前 Agent 的变化。
- 保存 session history 或 server-managed conversation 所需的增量。
- 把运行过程打点到 tracing span。
- 在 guardrail 触发时中断并提供可处理的异常。
max_turns 是 Runner 的一个重要安全阀。Agent loop 的本质是“模型可以继续请求工具或继续推理”,这也意味着如果 prompt、工具结果或模型行为出现问题,循环可能无法自然结束。max_turns 给了应用层一个硬边界,避免 Agent 在错误路径里无限消耗资源。
另外,Runner 支持 RunConfig。这是全局运行配置,适合放“本次运行”的决策,例如覆盖模型、配置 model provider、设置 tracing 信息、指定 session settings、配置 handoff input filter、使用 sandbox 运行配置等。Agent 负责稳定角色定义,RunConfig 负责单次运行环境,这是一个比较重要的分层。
工具系统:Agent 能做什么
没有工具的 Agent 只能生成文本。有了工具,Agent 才能读取外部信息、调用业务系统、搜索、执行代码、操作文件或委托其他 Agent。Agents SDK 的工具体系覆盖了几类不同执行边界。
第一类是函数工具。你可以用 @function_tool 把普通 Python 函数变成工具。SDK 会基于函数签名和类型信息生成 schema,并用 Pydantic 做输入校验。一个简化例子:
from agents import Agent, Runner, function_tool
@function_tool
def get_order_status(order_id: str) -> str:
"""Return the status of an order."""
return f"Order {order_id} is being processed."
agent = Agent(
name="Support Agent",
instructions="Answer customer questions. Use tools when needed.",
tools=[get_order_status],
)
result = Runner.run_sync(agent, "Please check order A1001.")
print(result.final_output)
函数工具适合接入业务 API、数据库查询、内部服务和确定性计算。它们运行在你的 Python 进程里,因此权限、网络、审计和异常处理都由应用控制。
第二类是 OpenAI 托管工具。官方的托管工具包括 web search、file search、code interpreter、hosted MCP、image generation 和 tool search。这类工具运行边界更靠近 OpenAI Responses API,适合使用 OpenAI 平台已有能力,而不是自己实现所有执行逻辑。
第三类是本地或 runtime execution tools,例如 ComputerTool、ShellTool、ApplyPatchTool 和 legacy 的 LocalShellTool。这些工具让 Agent 能够与本地执行环境交互,但通常需要你提供具体实现或配置执行环境。对于需要 GUI/browser 自动化、shell 命令、补丁应用的场景,这类工具是关键。
第四类是 MCP。Agents SDK 支持多种 MCP transport,包括 hosted MCP、Streamable HTTP、SSE 和 stdio。对开发者来说,MCP 的价值是把外部数据源和工具用标准协议接入 Agent,而不是为每个服务单独写一套工具注册方式。Agent 可以通过 mcp_servers 获取 server 暴露的工具,并且这些工具在运行时会被合并进可用工具列表。
第五类是 agents-as-tools。一个 Agent 可以通过 Agent.as_tool() 暴露成另一个 Agent 可调用的工具。这种模式在多 Agent 架构里很常用:manager Agent 负责最终回答,研究 Agent、校验 Agent、写作 Agent 作为工具被调用,各自完成有边界的子任务。
工具系统的关键不是“支持很多工具类型”本身,而是这些工具都能进入同一个 Agent loop。模型决定调用工具,SDK 执行工具,工具结果回到上下文,模型继续推理。应用开发者可以把注意力更多放在工具的语义、权限和可靠性上。
这也是 harness 视角最明显的地方:工具不是随便暴露给模型的函数列表,而是一个受控执行面。函数工具运行在你的 Python 进程里,MCP 工具通过协议接入外部能力,Computer/Shell/ApplyPatch 则把本地或 sandbox 的执行能力映射成模型可调用动作。SDK 负责把这些能力包装成统一的运行边界,并把结果重新接回 Agent loop。
Handoffs 与 agents-as-tools:两种多 Agent 编排
多 Agent 编排是 Agents SDK 的核心卖点之一。它重点区分了两种模式:handoffs 和 agents-as-tools。
Handoff 的语义是“交接对话控制权”。一个 triage Agent 可以根据用户问题选择把任务转给 billing Agent、refund Agent 或 technical support Agent。一旦 handoff 发生,新的 Agent 会成为当前 Agent,并负责后续响应。SDK 会把 handoff 暴露为模型可调用的工具,例如 transfer_to_refund_agent 这样的形式,但它的运行语义不同于普通函数工具:它改变的是当前对话由谁继续。
一个简化的 handoff 例子:
from agents import Agent, Runner
refund_agent = Agent(
name="Refund Agent",
handoff_description="Handles refund questions.",
instructions="Help users with refund requests.",
)
billing_agent = Agent(
name="Billing Agent",
handoff_description="Handles billing questions.",
instructions="Help users with invoices and charges.",
)
triage_agent = Agent(
name="Triage Agent",
instructions="Route the user to the right specialist.",
handoffs=[refund_agent, billing_agent],
)
result = Runner.run_sync(triage_agent, "I was charged twice.")
print(result.final_output)
Agents-as-tools 的语义则不同。这里 manager Agent 仍然拥有最终回答权,只是在需要时调用专家 Agent 完成一个子任务。专家 Agent 得到的是为这个工具调用构造的输入,完成后把结果交还给 manager。最终用户看到的回答仍由 manager 生成。
这两种模式适合不同场景。Handoff 适合“路由到专员”的对话流,尤其是你希望专家 Agent 直接接管后续交互。Agents-as-tools 适合“主 Agent 协调多个专家”的工作流,尤其是需要一个统一出口整合多个子结果、统一执行 guardrails 或保持一致语气。
更实际的应用里,两者可以组合。比如入口 triage Agent 先 handoff 到“研究 Agent”,研究 Agent 内部再把“数据分析 Agent”和“事实核查 Agent”作为工具调用。SDK 没有强迫你使用某一种图模型,而是把 handoff 和 tool agent 作为 Python 对象组合起来。
Guardrails、Sessions、Tracing:把 demo 推向生产
很多 Agent demo 看起来可运行,但离生产还差几件事:安全边界、状态管理和可观测性。Agents SDK 把这些能力放进了框架层。
Guardrails 用于输入、输出和工具调用边界的校验。文档里明确区分了 agent-level input guardrails、output guardrails 和 tool guardrails。输入 guardrails 只在链路中的第一个 Agent 上运行;输出 guardrails 只在产生最终输出的 Agent 上运行;tool guardrails 则围绕每次 custom function-tool 调用执行。这个边界很重要,因为多 Agent 运行时并不是每个 Agent 的每个 guardrail 都会在所有位置自动执行。应用需要根据风险点选择校验位置。
输入 guardrail 可以并行执行,也可以 blocking 执行。并行方式延迟更低,但如果 guardrail 后来失败,主 Agent 可能已经消耗了一部分 token 或执行了部分操作;blocking 方式先完成校验再启动 Agent,更适合成本敏感或副作用敏感的场景。这种执行模式选择,体现了 SDK 对工程权衡的尊重。
Sessions 解决多轮历史管理。最手动的方式是把 result.to_input_list() 传回下一次 Runner.run;更托管的方式是传入 session,让 SDK 自动加载和保存历史;如果只使用 OpenAI Responses 模型,也可以用 previous_response_id 或 conversation_id 使用 OpenAI server-managed state。官方文档给出的经验法则是:需要 provider-agnostic 和完全控制时用手动输入列表;需要 SDK 管理历史时用 session;需要 OpenAI 服务端续接时用 previous response 或 conversation。
Tracing 是另一个生产化关键点。Agents SDK 默认会追踪 Runner 运行、Agent span、LLM generation、function tool call、guardrail、handoff,以及语音相关 span。调试 Agent 应用时,最终答案往往不足以定位问题;你需要知道模型看到了什么工具、为什么调用它、工具返回了什么、handoff 是何时发生的、guardrail 是否触发。Tracing 把这些过程变成可观察数据。SDK 还提供 flush_traces(),适合在 Celery、RQ、FastAPI background task 这类长运行 worker 里确保任务结束后及时导出 trace。
Human-in-the-loop 则用于审批和中断场景。不是所有工具调用都应该自动执行,例如删除资源、发起退款、修改生产数据、访问敏感系统。SDK 在工具和 MCP 审批路径上提供了让人类或程序化策略介入的机制,使 Agent 不必在“完全自动化”和“完全不能行动”之间二选一。这类机制本质上也是 harness 的一部分:模型可以提出动作,但动作是否执行、以什么权限执行、失败后如何回到对话,都由运行时控制。
Streaming 让运行过程可以逐步展示。Runner.run_streamed 返回的是 streaming result,调用方可以消费 stream_events()。这对于聊天 UI、长任务进度显示、实时调试都很重要。SDK 同时维护 streamed 和 non-streamed 路径的一致性,这减少了应用自己维护两套逻辑的负担。
模型配置方面,SDK 默认推荐 OpenAI Responses 模型路径,同时保留 Chat Completions 支持。它也提供 model provider 接口、set_default_openai_client、MultiProvider、LiteLLM 和 any-llm 扩展路径,用于接入非 OpenAI 或 OpenAI-compatible 后端。但需要注意,不同 provider 对工具、Responses-only 特性、websocket transport、structured output 等能力的支持并不完全一致。复杂 provider 混用时,最好先验证目标功能路径,而不是假定所有模型后端行为相同。
SandboxAgent:从“会说”到“能在工作区里做事”
官方文档明确标注:Sandbox agents 是 beta feature,API、默认值和能力在 general availability 前可能变化。因此它值得关注,但不应该在没有验证的情况下假定接口长期稳定。
SandboxAgent 解决的是一类普通文本 Agent 很难优雅处理的问题:真实工作往往发生在文件系统里。代码修复要读仓库、改文件、跑测试;财务文档处理要读取多个文件、生成结果文件;报告审阅要检查附件、创建 artifacts;长任务可能需要今天做一半,明天从同一个工作区继续。把这些都塞进 prompt,不仅上下文昂贵,而且无法可靠表达“文件真的被修改了”。
从 harness 实践看,SandboxAgent 是这套 SDK 里最直接的产品化结果。一个代码或文档 Agent 真正需要的不是“知道有文件存在”,而是一个能被准备、挂载、执行、保存和恢复的工作区。harness 负责把 repo、文件、技能、shell、补丁、审批和状态组织起来;模型通过工具在这个边界内行动;Runner 则继续维护 Agent loop、handoff、tracing 和 resume bookkeeping。
SandboxAgent 的设计是:它仍然是 Agent,但额外带有 sandbox-specific defaults。源码里 SandboxAgent 继承自普通 Agent,新增了 default_manifest、base_instructions、capabilities 和 run_as 等字段。运行时的 sandbox client、session 或 snapshot 不存在 Agent 本身,而是通过 RunConfig(sandbox=SandboxRunConfig(...)) 在单次运行里提供。
一个概念性示例:
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import Manifest, SandboxAgent, SandboxRunConfig
from agents.sandbox.entries import LocalDir
from agents.sandbox.sandboxes import UnixLocalSandboxClient
agent = SandboxAgent(
name="Workspace Assistant",
instructions="Inspect the workspace before editing files.",
default_manifest=Manifest(
entries={
"repo": LocalDir(src="/path/to/repo"),
}
),
)
result = Runner.run_sync(
agent,
"Read the task, fix the issue, and run the targeted test.",
run_config=RunConfig(
sandbox=SandboxRunConfig(client=UnixLocalSandboxClient())
),
)
print(result.final_output)
这里有几个关键概念。
Manifest 是 fresh sandbox session 的工作区契约。它声明新 session 启动时应该有哪些文件、目录、repo、mount 或环境内容。它不是每次运行的完整真相,因为复用 session、恢复 session state 或从 snapshot 启动时,真实工作区可能来自已有状态。
SandboxRunConfig 决定本次运行如何拿到 sandbox session。可以直接注入 live session,也可以从 serialized session state 恢复,或者通过 sandbox client 创建新 session。官方文档建议本地开发从 UnixLocalSandboxClient 开始,需要容器隔离或镜像一致性时使用 Docker sandbox client,需要规模化托管时再考虑 hosted provider。
Capabilities 是 sandbox-native 能力的组合。默认能力包括 filesystem、shell 和 compaction。filesystem 让 Agent 能读写文件、应用 patch、查看图片;shell 让 Agent 执行命令;compaction 用于长上下文运行时的裁剪。还可以加入 skills、memory 等能力。重要的是,如果你显式传入 capabilities=[...],这个列表会替换默认能力,因此需要保留你仍然想用的默认项。
run_as 则描述模型面向 sandbox 工具执行时使用的用户身份。它属于执行边界设计的一部分,尤其在多用户、权限隔离或托管环境中需要认真对待。
SandboxAgent 的意义不只是“给 Agent 一个 shell”。单独的 shell 工具适合偶尔执行命令;SandboxAgent 则适合 workspace boundary 本身就是产品能力的场景。比如给一个代码审查 Agent 独立工作区,让它查看 repo、运行测试、产生补丁;给文档处理 Agent 一个包含输入文件和输出目录的 sandbox,让它生成可下载 artifact;给多个 reviewer Agent 分配隔离 session,避免互相污染文件状态。
从架构上看,SandboxAgent 把 Agent 应用从“对话状态”扩展到“工作区状态”。普通 session 解决的是模型历史;sandbox session 解决的是文件和执行环境。Runner 仍然负责 Agent loop、handoff、approval、tracing 和 resume bookkeeping;sandbox session 负责命令、文件变化和环境隔离。这个边界清楚之后,开发者才能设计出可恢复、可审计、可复现的长任务 Agent。
所以更准确的说法是:整个 SDK 并不是“必须依赖 harness 才能运行”的框架,普通 Agent + Runner 完全可以只做文本、工具和多 Agent 编排;但它的长任务、计算机使用和 SandboxAgent 能力,明显来自 harness 化经验。OpenAI 把这类实践中反复出现的执行外壳、权限边界、状态保存和工具映射,抽象成了开发者可以直接组合的 SDK 对象。
什么时候该用,什么时候不该用
Agents SDK 适合这些场景:
- 任务需要多轮模型推理和工具调用,而不是一次回答。
- 你希望工具调用、handoff、session、streaming 和 tracing 有统一运行时。
- 你需要多个专家 Agent 分工协作,并希望 prompt 和工具面保持可控。
- 你需要在输入、输出或工具调用边界做校验和审批。
- 你需要把 Agent 放进真实工作区,处理文件、仓库、命令、artifact 或可恢复长任务。
它不一定适合这些场景:
- 只是一次简单问答,直接 Responses API 更轻。
- 业务流程完全确定,模型只负责填一个字段或分类一次,自己写两三行调用可能更清楚。
- 你已经有成熟的 workflow/orchestration 平台,并且只需要把模型作为其中一个节点。
- 你需要的是完全跨生态、跨 provider 的统一抽象,而不是 OpenAI 生态里与 Responses API 深度配合的轻量运行时。
这最后一点尤其重要。Agents SDK 虽然支持非 OpenAI provider 和多种扩展,但它的设计重心明显还是 OpenAI 模型、Responses API、OpenAI 托管工具、tracing 和 realtime 生态。把它看成“OpenAI 生态里构建 Agent 应用的标准运行时”会更准确;如果把它期待成所有 LLM workflow 的通用平台,可能会高估它的抽象目标,至少目前是这样。
最后
OpenAI Agents SDK 最值得关注的地方,不是它能用几行代码创建一个 Agent,而是它把 Agent 应用中最容易分散的部分收束到了一条清晰的运行线:Agent 描述角色和能力,Runner 执行 loop,Tools 连接外部世界,Handoffs 和 agents-as-tools 组织多 Agent 协作,Guardrails 管住边界,Sessions 保存状态,Tracing 提供可观测性,Realtime/Voice 扩展交互形态,SandboxAgent 则把 Agent 带进真实文件系统和可恢复工作区。
也正因为如此,它可以被看作 OpenAI 对 harness 工程实践的一次 SDK 化总结:把模型放在一个受控运行环境里,让它能使用工具、读取上下文、请求审批、产生可追踪的行动,并在需要时恢复工作现场。普通 Agent 抽象保留了轻量入口,SandboxAgent 则把这个 harness 工程思路推向更完整的工作区执行模型。
如果你正在做的是一个短链路 LLM 功能,直接调用底层 API 仍然是合理选择。但如果你的目标是构建一个会使用工具、能分工协作、可调试、可恢复,并且最终要进入生产环境的 Agent 应用,Agents SDK 提供了一个值得认真评估的起点。它的抽象不多,进入门槛不高,但覆盖了真实 Agent 工程里绕不开的关键问题。