2.3 运行器 Runner 机制


2.3 运行器(Runner)机制

本节摘要:Runner 是"执行层"的主角——它把 Agent 的定义变成实际对话。本节讲清 Runner 的执行流程(模型循环 + 工具循环)、三种运行模式(同步/异步/流式)、结果对象的结构,以及如何用 Runner 处理复杂流程。

本节地图

阅读完本节,你应当能够:

  1. 复述 Runner 的执行流程
  2. 区分同步与异步运行
  3. 理解结果对象的结构
  4. 处理工具调用的自动循环
  5. 用 Runner 搭建复杂流程

一、问题与直觉

"智能体怎么自动调工具的?"——答案在 Runner 里。Runner 维护一个循环:调模型 → 模型说要调工具 → Runner 执行工具 → 结果回传 → 再调模型,直到模型给出最终答案。开发者不用写这个循环,Runner 全包了——这是 SDK 最省心的部分。

理解 Runner 还有一个更实际的动机:它是所有"执行细节"的集中地。同步还是异步、上下文怎么传、最多循环几轮、结果怎么取,这些工程问题都在 Runner 这一层解决。掌握了 Runner,你就掌握了 SDK 的执行模型。

二、核心原理

Runner 的执行本质是循环调度:

2.1 Runner 的执行循环

一次运行就是"模型调用 → 工具执行"的往复,直到模型输出最终答案。

2.1 Runner 的执行循环

2.2 运行模式与结果对象

模式 用法 场景
同步 run_sync 脚本、演示、简单调用
异步 await Runner.run Web 服务、并发
流式 run_streamed 打字机效果、长响应

结果对象包含:final_output(最终回答)、last_agent(哪个 Agent 收尾)、items(完整过程)。

2.3 三种模式代码对照

from agents import Agent, Runner agent = Agent(name="demo", instructions="用中文回答。") # 同步 r1 = Runner.run_sync(agent, "同步运行") # 异步(需要 async 环境) async def main(): r2 = await Runner.run(agent, "异步运行") print(r2.final_output) # 流式:逐段产出 r3 = Runner.run_streamed(agent, "流式运行") async for event in r3.stream_events(): print(event) # 处理文本增量、工具调用等事件

💡 关键直觉:Runner 帮你管住"循环",但你要看懂"循环"——排查"为什么没调工具"时,看模型输出与工具日志,就知道是模型没决定调,还是工具执行失败。

三、工程实践要点

3.1 结果对象的使用

result = Runner.run_sync(agent, "查一下订单状态") print(result.final_output) # 最终回答 print(result.last_agent) # 收尾的智能体 print(result.trace_id) # 本次运行的追踪 ID for item in result.new_items: print(type(item).__name__, item) # 本次新增的消息与工具调用

new_items 在多轮会话场景特别有用:你可以只取"本轮新增"的内容拼进下一轮,避免重复传历史。

3.2 异步模式与上下文

from agents import Agent, Runner agent = Agent(name="助手", instructions="回答用户问题。") # Web 场景用异步,避免阻塞 async def handle(user_input: str) -> str: result = await Runner.run(agent, user_input) return result.final_output

3.3 Runner 相关排查

现象 排查
工具没被调用 看模型是否"决定"调工具,看 tools 是否挂载
循环卡住 设置最大轮数限制
结果为空 检查模型与工具返回

⚠️ 常见坑:无限制循环。模型可能反复调工具(比如工具一直返回异常)。生产环境务必设置最大迭代次数,防失控。SDK 的 RunConfig 里可以配置 max_turns 等限制,上线前一定确认。

⚠️ 常见坑:在同步函数里跑 async。忘了 asyncio.run 或事件循环,程序会报错或阻塞——先想清楚自己的运行环境,脚本用同步,服务用异步。

3.4 流式输出的实战应用

流式模式(run_streamed)不只是"打字机特效",它有三个实用场景:第一,长回答的用户体验——先给用户"正在思考"的反馈,再逐步展示内容,避免白屏等待;第二,长流程的进度提示——智能体在处理多个工具时,可以先把每个阶段的状态流式推给前端;第三,实时拦截——输出过程中发现异常内容,可以在流式阶段就处理,而不是等完整结果出来再补救。实现时按事件类型消费即可:文本增量事件用于渲染,工具调用事件用于展示进度。

from agents import Agent, Runner agent = Agent(name="流式助手", instructions="用中文回答。") async def chat_stream(user_input: str): result = Runner.run_streamed(agent, user_input) async for event in result.stream_events(): # 文本增量:实时渲染;工具事件:展示进度 print(event)

3.5 多轮对话与 Runner

from agents import Agent, Runner agent = Agent(name="多轮助手", instructions="用中文回答。") # 第一轮 r1 = Runner.run_sync(agent, "我叫小明,记一下") # 第二轮:把上一轮结果作为输入的一部分,保持上下文 r2 = Runner.run_sync(agent, r1.to_input_list() + [{"role": "user", "content": "我叫什么?"}]) print(r2.final_output)

多轮对话的本质是"把历史消息喂回去"。to_input_list() 可以把上一轮结果转成可继续输入的消息列表,配合会话管理(第 3 章)使用,就能搭出真正连续的对话体验。

要点串联

  • 要点一:Runner 维护"模型-工具"自动循环
  • 要点二:三种模式——同步、异步、流式
  • 要点三:结果对象含最终输出与完整过程
  • 要点四:排查工具问题要看模型决定与工具日志
  • 要点五:生产环境设最大循环次数
  • 要点六:Runner 管循环,你要看懂循环

Runner 会用了,下一节看引擎——模型集成与管理。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U