执行结果
当你运行智能体时,你会收到以下其中一种:
- 如果调用
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() 时,这些工具搜索项是检查在常规工具调用发生之前加载了哪些延迟工具或命名空间的最简单方式。
对话的继续或恢复
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。
StreamedRunResult 继承了上述相同的结果接口,但增加了流式传输专用控制:
toTextStream(),仅用于助手文本。toStream()或for await ... of stream,用于完整事件流。completed,用于等待运行和所有后处理回调完成。error和cancelled,用于检查流式传输的终止状态。currentAgent,用于在运行过程中跟踪活动智能体。
如果你需要流式运行已确定的最终状态,请先等待 completed,再读取 finalOutput、history、interruptions 或其他摘要属性。有关逐事件处理,请参阅流式传输。
如果流式运行被取消,completed 仍会在清理完成后解析,且 cancelled 会变为 true,但 finalOutput 等轮次结束字段可能仍未设置,因为当前轮次从未完成。请使用 result.state(以及同一个 session,如果你使用了的话)恢复这个未完成的轮次,而不是追加一条新的用户消息。
诊断和高级字段
Section titled “诊断和高级字段”runContext 属性是结果上运行上下文的受支持公共视图。result.runContext.context 是你的应用上下文,同一对象还携带 SDK 管理的运行时元数据,例如审批、用量和嵌套 toolInput。完整结构请参阅上下文管理。
rawResponses 包含运行期间收集到的原始模型响应。多步骤运行可能会生成多个响应,例如跨交接或重复的工具/模型循环。
inputGuardrailResults 和 outputGuardrailResults 属性包含智能体级护栏结果。工具护栏结果会通过 toolInputGuardrailResults 和 toolOutputGuardrailResults 单独暴露。
当你想记录护栏决策、检查护栏函数返回的额外元数据,或调试某次运行为何被阻止时,请使用这些数组。
Token 用量汇总在 result.state.usage 中,它会跟踪本次运行的请求次数和 token 总数。同一个用量对象也可以通过 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, }); }}