跳到主要内容

模型抽象、流式、追踪与兄弟包

前四章讲完了引擎主线和挂件。这一章收尾三个「横切」能力——模型怎么解耦、流式怎么走、追踪怎么记——再俯瞰两条建立在引擎之上的扩展线(sandbox agent、realtime 语音)。

1. 模型抽象:provider 无关靠两个方法

1.1 思路

整个引擎只通过一个窄接口跟 LLM 打交道。换供应商(OpenAI / Vercel AI SDK / 自研),只要实现这接口,循环代码一行不改。

1.2 真实实现

Model 接口(model.ts:573)只有三个方法,两个是核心:

// model.ts:573 Model(真实源码,节选)
export interface Model {
getResponse(request: ModelRequest): Promise<ModelResponse>; // 非流式
getStreamedResponse(request: ModelRequest): AsyncIterable<StreamEvent>; // 流式
getRetryAdvice?(args: ModelRetryAdviceRequest): ...; // 可选:重试建议
}
  • 输入 ModelRequestmodel.ts:439):系统指令、input items、工具/交接的序列化形式、modelSettings、tracing 开关。
  • 输出 ModelResponsemodel.ts:542):usageoutput(消息/工具调用等)、responseIdproviderData
  • 查找模型ModelProvider.getModel(name)model.ts:600)——把字符串模型名解析成 Model 实例。

主循环里调用点是 getResponseWithRetry(preparedCall.model, {...})run.ts:1008),preparedCall.model 就是一个 Model。引擎从不直接 import OpenAI。

1.3 默认实现在哪

默认 provider 是惰性加载的 LazyDefaultModelProviderrun.ts:409),它转调 getDefaultModelProvider()(来自 providers.ts)——具体 OpenAI 实现住在 @openai/agents-openaiopenaiResponsesModel.tsopenaiChatCompletionsModel.ts)。默认模型名见 defaultModel.tsgetDefaultModel,当前默认是一个 gpt-5 系模型,见 agent.ts:328-330 注释)。

1.4 巧妙之处:gpt-5 的 modelSettings 隔离

构造 Agent 时有段防呆逻辑(agent.ts:565-581):如果默认是 gpt-5、但你显式指定了非 gpt-5 模型且没自定义 modelSettings,它会把 modelSettings 清空——因为 gpt-5 默认的 reasoning 设置喂给别的模型会报错。这是「best-effort 让换模型不炸」的细节。

2. 流式

2.1 思路

流式不是「把非流式包一层」,而是一条几乎平行的循环 Runner.#runStreamLooprun.ts:1188)。它和非流式共用准备/决议逻辑,区别在:边收模型事件边 emit 给调用方。

2.2 真实路径

  • getStreamedResponseWithRetry(...)run.ts:1476),for await 逐个事件。
  • 每个原始事件包成 RunRawModelStreamEvent 推进结果流(run.ts:1525);response_done 事件用来组装 finalResponserun.ts:1508-1517)。
  • 收完后照样 processModelResponseAsync + resolveTurnAfterModelResponserun.ts:1568:1587)——和非流式同一套决议。
  • 取消对账:用户提前退出消费 stream,或 abort 时,要跟服务端「对账」流到一半的函数调用,靠 reconcileStreamAbortIfNeededrun.ts:1412)补一次请求把状态拉齐。这是流式特有的复杂度。

用户侧看到的事件类型在 events.tsRunRawModelStreamEventRunItemStreamEventRunAgentUpdatedStreamEventindex.ts:40-45 导出)。

3. 追踪 Tracing

3.1 思路

每次 run 包在一个 trace 里,run 内的每个有意义动作(一次 agent 执行、一次模型调用、一次工具调用、一次交接)是一个 span。span 形成树,导出后能在 UI 里看「这次 run 到底干了啥、哪步慢」。

3.2 真实路径

  • run 入口用 getOrCreateTrace(...)run.ts:707)或 withTrace(...)(恢复带 trace 的状态时,run.ts:700)把整次执行包进 trace context。
  • span 创建用 withFunctionSpan / withHandoffSpan 等(tracing/createSpans.ts,在 toolExecution.ts:42 被引)。
  • 默认就开:index.ts:338 在模块加载时 addTraceProcessor(defaultProcessor())——defaultProcessor 批量把 trace/span 导出到后端。要换行为用 addTraceProcessor / setTraceProcessorstracing/index.ts:62:71),要关用 setTracingDisabledtracing/index.ts:80)。
  • 敏感数据开关:RunConfig.traceIncludeSensitiveDatarun.ts:269-273)控制工具入参/模型生成要不要进 trace。

OpenAI 的 trace 导出实现在 @openai/agents-openaiopenaiTracingExporter.ts

4. 兄弟扩展线(俯瞰)

引擎之上有两条独立的产品线,本文档不深入其内部机制,但给出定位以便导航:

扩展线是什么在哪
Sandbox Agentagent 配一个文件系统 workspace + 沙箱环境,能跑命令、改文件、跨多轮带工作区状态(适合「编码任务」类长任务)agents-core/src/sandbox/SandboxAgentSandboxRuntimeManager),README「Run your first Sandbox Agent」
Realtime(语音)实时语音 agent,走 WebRTC / SIP / WebSocket 传输@openai/agents-realtimeopenaiRealtimeWebRtc.tsopenaiRealtimeSip.ts
Extensions第三方适配:Vercel AI SDK 模型、Twilio / Cloudflare 实时传输@openai/agents-extensionsai-sdk/TwilioRealtimeTransport.tsCloudflareRealtimeTransport.ts

sandbox 在主循环里是有「钩子」的:Runner.#runIndividualNonStreamSandboxRuntimeManagerprepareSandboxInterruptedTurnResumefinalizeSandboxRuntimerun.ts:852:916:1171)把沙箱生命周期挂在循环的准备/中断/收尾处——这也印证了「一切都挂在主线上」这条设计主轴。

5. 横向对比与精华回顾

纵观全库,几个值得带走的设计模式:

  • 窄接口换 providerModel 只两个方法(model.ts:573),是「依赖倒置」的教科书用法。
  • 四个控制流标签统御一切next_step_*runner/steps.ts:6)——工具、交接、人审、最终输出,全压缩进这四个分支。新特性优先复用标签而非加机制(HITL 复用 interruption 即是例证)。
  • 错误即反馈:工具异常默认转文本回喂模型(tool.ts:1953-1963),让模型自我纠错。
  • 安全不付延迟税:输入护栏默认与模型并行(guardrail.ts:138)。
  • 状态可序列化 = 可暂停可恢复RunStaterunState.ts:474)带 schema 版本,让 HITL 能跨进程。

6. 代码地图

主题文件符号
模型接口model.tsModelModelProviderModelRequestModelResponse
默认 providerrun.ts · providers.ts · defaultModel.tsLazyDefaultModelProvidergetDefaultModel
OpenAI 模型实现agents-openai/srcopenaiResponsesModel.tsopenaiChatCompletionsModel.ts
流式循环run.tsRunner.#runStreamLoopreconcileStreamAbortIfNeeded
流式事件类型events.tsRunRawModelStreamEventRunItemStreamEvent
追踪tracing/index.ts · tracing/createSpans.tsaddTraceProcessorwithTracewithFunctionSpan
sandbox 钩子runner/sandbox.ts · sandbox/runtimeSandboxRuntimeManagerfinalizeSandboxRuntime
realtimeagents-realtime/srcopenaiRealtimeWebRtc.tsopenaiRealtimeSip.ts