执行结果
当您运行智能体时,将收到以下结果之一:
- 如果调用
run时未设置stream: true,则返回RunResult - 如果调用
run时设置了stream: true,则返回StreamedRunResult。有关流式传输的详细信息,另请参阅流式传输。
这两种结果类型都会公开相同的核心结果字段,例如 finalOutput、newItems、interruptions 和 state。StreamedRunResult 还提供 completed、toStream()、toTextStream() 和 currentAgent 等流式传输控制功能。
合适结果字段的选择
Section titled “合适结果字段的选择”大多数应用只需要使用少数几个属性:
| 如果您需要… | 使用 |
|---|---|
| 向用户显示最终答案 | finalOutput |
| 包含完整本地记录、可直接用于下一轮重放的输入 | history |
| 仅获取本次运行中新生成的模型格式条目 | output |
| 包含智能体、工具和交接元数据的丰富运行条目 | newItems |
| 通常应处理下一轮用户输入的智能体 | lastAgent 或 activeAgent |
使用 previousResponseId 进行 OpenAI Responses API 链式调用 | lastResponseId |
| 待处理的审批和可恢复快照 | interruptions 和 state |
| 应用上下文、审批、用量和嵌套智能体工具输入 | runContext |
当前嵌套 Agent.asTool() 调用的元数据,例如在 customOutputExtractor 内部 | agentToolInvocation |
| 原始模型调用或护栏诊断信息 | rawResponses 和护栏结果数组 |
finalOutput 属性包含最后一个运行智能体的最终输出。此结果可以是:
string—— 未定义outputType的任何智能体的默认类型unknown—— 如果智能体将 JSON schema 定义为输出类型。在这种情况下,JSON 已完成解析,但您仍需手动验证其类型。z.infer<outputType>—— 如果智能体将 Zod schema 定义为输出类型。输出将自动依据此 schema 进行解析。undefined—— 如果智能体未生成输出(例如在能够生成输出之前停止)
当流式运行仍在进行中,或者运行在产生最终输出前因审批中断而暂停时,finalOutput 也会是 undefined。
如果您使用具有不同输出类型的交接,应使用 Agent.create() 方法而不是 new Agent() 构造函数来创建智能体。
这样,SDK 就能推断所有可能交接的输出类型,并为 finalOutput 属性提供联合类型。
例如:
import { Agent, run } from '@openai/agents';import { z } from 'zod';
const refundAgent = new Agent({ name: 'Refund Agent', instructions: 'You are a refund agent. You are responsible for refunding customers.', outputType: z.object({ refundApproved: z.boolean(), }),});
const orderAgent = new Agent({ name: 'Order Agent', instructions: 'You are an order agent. You are responsible for processing orders.', outputType: z.object({ orderId: z.string(), }),});
const triageAgent = Agent.create({ name: 'Triage Agent', instructions: 'You are a triage agent. You are responsible for triaging customer issues.', handoffs: [refundAgent, orderAgent],});
const result = await run(triageAgent, 'I need to a refund for my order');
const output = result.finalOutput;// ^? { refundApproved: boolean } | { orderId: string } | string | undefined输入和输出字段
Section titled “输入和输出字段”这些属性分别用于回答不同的问题:
| 属性 | 包含的内容 | 最适合 |
|---|---|---|
input | 本次运行的基础输入。如果交接输入过滤器重写了历史记录,则此属性反映运行继续执行时使用的已过滤输入。 | 审核本次运行实际使用的输入 |
output | 仅包含本次运行中生成的模型格式条目,不含智能体元数据。 | 仅存储或重放新生成的模型增量 |
newItems | 包含智能体、工具和交接元数据的丰富 RunItem 包装器。 | 日志、UI、审核和调试 |
history | 根据 input + newItems 构建、可直接用于下一轮重放的输入。 | 手动聊天循环和客户端管理的对话状态 |
在实践中:
- 当您在应用中手动维护完整对话时,请使用
history。 - 当您已在其他位置存储之前的历史记录,只需要本次运行中新生成的条目时,请使用
output。 - 当您需要智能体关联信息、工具输出、交接边界或审批条目时,请使用
newItems。 - 如果您使用
conversationId或previousResponseId,通常无需将history传回run()。应只传入新的用户输入,并复用由服务器管理的 ID。完整对比请参阅运行智能体。
在类似聊天的使用场景中,history 是维护完整历史记录的便捷方式:
import { Agent, user, run } from '@openai/agents';import type { AgentInputItem } from '@openai/agents';
const agent = new Agent({ name: 'Assistant', instructions: 'You are a helpful assistant knowledgeable about recent AGI research.',});
let history: AgentInputItem[] = [ // initial message user('Are we there yet?'),];
for (let i = 0; i < 10; i++) { // run 10 times const result = await run(agent, history);
// update the history to the new output history = result.history;
history.push(user('How about now?'));}newItems 可提供本次运行期间所发生事件的最丰富视图。常见的条目类型包括:
RunMessageOutputItem,用于表示助手消息。RunReasoningItem,用于表示推理条目。RunToolSearchCallItem和RunToolSearchOutputItem,用于表示 Responses 工具搜索请求及其返回的已加载工具定义。RunToolCallItem和RunToolCallOutputItem,用于表示工具调用及其结果。RunToolApprovalItem,用于表示因等待审批而暂停的工具调用。RunHandoffCallItem和RunHandoffOutputItem,用于表示交接请求和已完成的转移。
只要您需要知道哪个智能体生成了某个条目,或者该条目是否表示工具、工具搜索、交接或审批边界,就应选择 newItems 而不是 output。使用 toolSearchTool() 时,这些工具搜索条目是检查在常规工具调用发生前加载了哪些延迟工具或命名空间的最简便方式。
如果本地工具或 MCP 服务器定义了 customDataExtractor,相应的 RunToolCallOutputItem.customData 将包含其返回的仅供 SDK 使用的元数据。这些数据可用于应用 UI 状态,例如渲染器提示或内部 ID。它们会在 RunState 序列化后保留,但不会包含在 history 中,也不会发送回模型。
对话的继续或恢复
Section titled “对话的继续或恢复”lastAgent 属性包含最后一个运行的智能体。在交接后,它通常是下一轮用户输入最适合复用的智能体。activeAgent 是同一值的别名。
在流式传输模式下,运行仍在进行时,currentAgent 会指示当前处于活跃状态的智能体。
中断和可恢复状态
Section titled “中断和可恢复状态”如果工具需要审批,运行会暂停,而 interruptions 将包含待处理的 RunToolApprovalItem 条目。这可能包括直接工具触发的审批、交接后调用的工具所触发的审批,或嵌套 agent.asTool() 运行所触发的审批。
通过 result.state.approve(...) / result.state.reject(...) 处理审批,然后将同一个 state 传回 run() 以恢复运行。您无需一次性处理所有中断。如果只处理部分条目后重新运行,已处理的调用可以继续执行,而未处理的调用会保持待处理状态并再次暂停运行。
state 属性是结果背后的可序列化快照。它适用于人机协作、重试流程,以及需要稍后恢复已暂停运行的任何场景。
服务器管理的续接
Section titled “服务器管理的续接”使用 OpenAI Responses API 链式调用时,lastResponseId 是下一轮应作为 previousResponseId 传入的值。
如果您已经通过 history、session 或 conversationId 继续对话,通常不需要使用 lastResponseId。如果需要获取多步骤运行中的每个原始模型响应,请改为检查 rawResponses。
嵌套智能体工具元数据
Section titled “嵌套智能体工具元数据”agentToolInvocation 用于嵌套 Agent.asTool() 的结果,尤其适用于您位于 customOutputExtractor 内部,并希望获取当前工具调用元数据的情况。它不是用于汇总”整个运行已完成”的通用字段。
在这种嵌套上下文中,agentToolInvocation 会公开:
toolNametoolCallIdtoolArguments
如果您还需要传入该嵌套智能体工具运行的结构化输入,可以将它与 result.runContext.toolInput 结合使用。
在普通的顶层 run() 结果中,此属性通常为 undefined。这些元数据仅在运行时可用,不会被序列化到 RunState 中。有关相关模式,请参阅 Agents as tools。
流式传输结果
Section titled “流式传输结果”StreamedRunResult 继承上述相同的结果字段,但增加了流式传输专用的控制功能:
toTextStream(),仅用于助手文本。toStream()或for await ... of stream,用于完整事件流。completed,用于等待运行和所有后处理回调完成。error和cancelled,用于检查流式传输的终止状态。currentAgent,用于在运行过程中跟踪活跃智能体。
如果需要流式运行完成后的最终状态,请先等待 completed,再读取 finalOutput、history、interruptions 或其他汇总属性。有关逐事件处理,请参阅流式传输。
如果流式运行被取消,completed 仍会在清理完成后兑现,且 cancelled 会变为 true,但由于当前轮次从未完成,finalOutput 等轮次结束字段可能仍未设置。应使用 result.state(如果使用了 session,还需使用同一个 session)恢复该未完成轮次,而不是追加一条新的用户消息。
诊断和高级字段
Section titled “诊断和高级字段”runContext 属性是在结果中查看运行上下文的受支持公共接口。result.runContext.context 是您的应用上下文,同一对象还包含由 SDK 管理的运行时元数据,例如审批、用量和嵌套 toolInput。完整结构请参阅上下文管理。
rawResponses 包含运行期间收集的原始模型响应。多步骤运行可能产生多个响应,例如跨交接或重复的工具与模型循环。
inputGuardrailResults 和 outputGuardrailResults 属性包含智能体级护栏结果。工具护栏结果则分别通过 toolInputGuardrailResults 和 toolOutputGuardrailResults 提供。
如果您希望记录护栏决策、检查护栏函数返回的额外元数据,或调试运行被阻止的原因,请使用这些数组。
如果某个护栏执行失败,其他已成功完成的同级护栏结果仍会保留在运行状态中。对于流式运行,请在 completed 被拒绝后检查结果数组;对于非流式运行,GuardrailExecutionError 会携带相同的最终 state。
令牌用量汇总在 result.state.usage 中,其中会跟踪本次运行的请求次数和令牌总数。也可以通过 result.runContext.usage 获取同一个用量对象。对于流式运行,这些数据会随着响应到达而更新。
import { Agent, run } from '@openai/agents';
const agent = new Agent({ name: 'Usage Tracker', instructions: 'Summarize the latest project update in one sentence.',});
const result = await run( agent, 'Summarize this: key customer feedback themes and the next product iteration.',);
const usage = result.state.usage;console.log({ requests: usage.requests, inputTokens: usage.inputTokens, outputTokens: usage.outputTokens, totalTokens: usage.totalTokens,});
if (usage.requestUsageEntries) { for (const entry of usage.requestUsageEntries) { console.log('request', { endpoint: entry.endpoint, inputTokens: entry.inputTokens, outputTokens: entry.outputTokens, totalTokens: entry.totalTokens, }); }}