第 3 章:Runner、Event、Session 与中断恢复
本章把运行时的「外壳」讲清:谁启动执行(Runner)、流经系统的数据长什么样(Event)、对话和状态存哪(Session/State)、以及 ADK 的杀手锏——暂停后从断点恢复和人类介入(HITL)。
3.1 Runner:对外入口
Runner(runners.py:132)是你直接调用的对象。主方法 run_async(runners.py:937)。它做的事:
- 取/建 Session(
_get_or_create_session)。 - 决定根节点。若根是 chat 模式的
LlmAgent,可能先用_find_agent_to_run(runners.py:1622)挑出「上次活跃、该继续接话的那个 agent」,再用build_node包成节点(runners.py:1004)。 - 驱动节点(
_run_node_async),把产出的Event逐个 yield 给你。 - 落库:每个该持久化的事件经
session_service.append_event(runners.py:744)写入历史并应用状态增量。
# 真实源码节选 runners.py:982-1004(简化)
if isinstance(self.agent, LlmAgent):
if self.agent.mode is None:
self.agent.mode = 'chat' # 根 LlmAgent 默认 chat
if self.agent.mode == 'chat':
session = await self._get_or_create_session(...)
agent_to_run = self._find_agent_to_run(session, self.agent)
agent_to_run = build_node(agent_to_run) # 一切皆节点
else:
raise ValueError("LlmAgent as root agent must have mode='chat' ...")
重点看:根 LlmAgent 必须是 chat 模式(task/single_turn 只能当被委派方);而且无论根是 agent 还是 workflow,最终都 build_node 成节点走统一的节点运行路径(_run_node_async)。
InMemoryRunner(runners.py:2151)是开箱即用的子类,内置内存版 session/artifact/memory 服务,适合本地跑和测试。
3.2 InvocationContext vs Context
两个 context 容易混:
| 是什么 | 作用域 | 文件 | |
|---|---|---|---|
InvocationContext | 一次完整调用(一条用户消息触发的整轮)的全局把手:session、agent、run_config、plugin_manager、是否可恢复… | 整个 invocation | agents/invocation_context.py |
Context | 一个节点的一次执行 |