OpenAI Agents SDK 流式运行中途怎么取消并拿到已完成结果?
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
用 OpenAI Agents SDK 的Runner.run_streamed()启动流式运行后,你可能会遇到这种情况:用户中途点了停止,或者你希望一个多轮任务只执行到当前这一步就不再继续,但已经产出的回复、工具调用结果不能丢。SDK 对这个问题有明确接口:在RunResultStreaming上调用cancel(...)停止运行,然后继续消费result.stream_events()直到迭代器结束,再从result.new_items、result.final_output等结果面上取出已完成的部分。下面按实际操作顺序说明两种取消模式、取消后如何取结果、以及如何接着已完成的进度继续对话。
两种取消模式:立即停止,还是等当前轮做完
cancel()接受一个mode参数,两个取值的行为差异直接决定你能拿到多少已完成结果(见 cancel 源码说明):
result.cancel(),即默认的mode="immediate":立即停止,取消所有运行中的任务并清空事件队列。适合用户明确中断、不需要保留后续状态的场景。result.cancel(mode="after_turn"):让当前轮(turn)优雅完成后才停止。它会允许 LLM 响应结束、执行完挂起的工具调用、正确保存 session 状态、准确记录 usage,然后在下一次模型调用开始前停下。适合需要保留已完成工作、稍后继续的场景。
两种模式都有一个共同前提:调用cancel()之后必须继续消费stream_events(),让取消和清理流程走完,不要提前break离开循环。这是 Streaming 文档 和 Results 文档 都明确强调的。另外cancel()是幂等的,重复调用不会报错。
操作路径:在事件循环里取消,然后让流排空
Runner.run_streamed()返回RunResultStreaming,事件通过result.stream_events()这个异步迭代器逐个到达。取消的时机就放在消费事件的循环里,按你的条件触发。下面这个示例基于 streaming.md 中的工具调用示例改写:agent 带一个工具,当工具执行完毕(tool_output事件)后触发after_turn取消,随后流自然排空,检查运行状态和已完成的项目:
import asyncio from agents import Agent, Runner from agents.decorators import tool import random @tool def how_many_jokes() -> int: return random.randint(1, 10) async def main(): agent = Agent( name="Joker", instructions="First call the `how_many_jokes` tool, then tell that many jokes.", tools=[how_many_jokes], ) result = Runner.run_streamed(agent, input="Hello") async for event in result.stream_events(): if event.type == "run_item_stream_event" and event.name == "tool_output": # 条件满足:当前轮的工具结果已产出,让这一轮收尾后停止 result.cancel(mode="after_turn") # 注意:不要在这里 break,继续消费直到迭代器结束 # 流结束后,is_complete 反映最终运行状态 print("is_complete:", result.is_complete) for item in result.new_items: print("--", item.type) print("final_output:", result.final_output) if __name__ == "__main__": asyncio.run(main())触发条件的选择取决于你的业务:可以按事件类型、按轮数、或按外部信号(比如前端停止按钮置位的标志位)。after_turn模式下,SDK 会在当前轮收尾后停下,不会发起下一次模型调用。
如果你确定不需要保留任何状态,只需把上面一行换成默认模式:
result.cancel() # 等价于 result.cancel(mode="immediate")immediate 模式会立即取消所有任务并清空队列,因此流很快结束,new_items里可能只剩取消前已经送达的项目。
从结果对象取已完成的内容
流排空之后,已完成的成果都在同一个result对象上,取用位置如下(参见 Results 文档):
result.new_items:运行中富化后的RunItem列表,是"完成了什么"最完整的答案。常见类型包括MessageOutputItem(助手消息)、ToolCallItem和ToolCallOutputItem(工具调用及其结果)、ReasoningItem、HandoffCallItem等。即使final_output为空,已完成轮次产出的消息和工具结果也会在这里。result.final_output:最后一个运行 agent 的最终输出。流式模式下它在流处理结束前保持None;如果运行在产生最终输出之前就停下了(例如after_turn恰好停在工具轮之后、下一次模型调用之前),它同样是None。所以判断"有没有拿到最终答案"要看这个属性是否为None,不能只看循环是否结束。result.is_complete:stream_events()迭代器退出后读取它,确认运行是否到达终态。result.context_wrapper.usage:after_turn模式下已完成轮次的 usage 会被准确记录;immediate模式只覆盖已执行的部分。result.current_agent/result.last_agent:取消时运行停在哪个 agent 上,多 agent 场景下判断下一步该用谁。
还有一个容易踩的坑:如果后台运行循环在产生任何流事件之前就失败了(例如沙箱初始化早期出错),异常不会从stream_events()里重新抛出。消费完流之后检查result.run_loop_exception,非None就表示存在这种静默失败,见 run_loop_exception 文档:
if result.run_loop_exception: raise result.run_loop_exception如果运行配置了session=...,after_turn取消会把已完成轮次的项目写入 session,之后可以带同一个 session 直接Runner.run(agent, "继续"),历史仍在。
取消之后接着原来的进度继续
after_turn停在工具轮之后时,当前用户轮其实还没有被模型"回答完"。streaming.md 给出的接续方式分三种情况:
手动维护历史的情况:用
result.to_input_list(mode="normalized")取规范化输入,然后重新运行result.last_agent并用这份输入继续,这样是接着未完成的用户轮走,而不是立刻追加一条新的用户轮。新用户输入先到达的情况:把已排空的结果转成状态再入队,见 Add input before resuming:
state = result.to_state() state.add_input("Also keep the generated report in the project folder.") result = Runner.run_streamed(agent, state)暂存的输入会在下一次模型调用前被立刻接纳,并且随
RunState序列化。运行是停在工具审批上的情况:不要把审批暂停当成新轮次。先消费完
stream_events(),检查result.interruptions,通过result.to_state()批准或拒绝后再用Runner.run_streamed(agent, state)恢复。完整流程见 human-in-the-loop 指南。
边界与验证小结
- 必须排空流:
stream_events()迭代器结束前,运行不算完成,final_output、interruptions等汇总属性可能还在收尾,after_turn下 session 持久化和历史整理也可能在最后一个可见 token 之后才结束。 final_output为None不等于什么都没完成:它只说明最终输出没有产生(停在工具轮之后、或暂停在审批上),已完成的消息和工具结果仍从new_items取。- immediate 模式会清空队列:取消后已入队但未消费的事件会被丢弃,能拿到的完成内容以取消前已送达事件和
new_items为准。 - 验证取消是否按预期生效,看三处即可:
stream_events()循环是否如预期退出、result.is_complete是否为True、result.new_items是否包含你预期的已完成项目类型。仓库里 tests/test_soft_cancel.py 对after_turn的各行为(等待当前轮完成、执行挂起工具、保存 session、阻止下一轮开始、幂等性)有一组可直接参考的断言用例。
更多流式事件类型(raw_response_event、run_item_stream_event、agent_updated_stream_event)的说明见 docs/streaming.md,结果面各属性的完整对照表见 docs/results.md。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考