会话状态与可观测性:Chat、Session 与 Dev UI
30 秒导读: 前几章讲的
generate(03)和工具循环 (04)都是单次调用——喊一声、答一句、忘干净。本章补上 把 demo 变成产品的两条能力:① 让多轮对话记得住(Session + SessionStore 用快照持久化 消息和自定义状态);② 让开发者看得见(每个 Action 自动生成 OpenTelemetry span,汇成 trace, 再由 ReflectionServer 喂给本地 Dev UI 可视化调试)。
1. 这是什么(零基础也能懂)
一个问题起头: 你用 03 章的 ai.generate() 写了个聊天机器人。
用户问"我叫小明",模型回"你好小明";用户再问"我叫什么",模型答"我不知道"。因为每次 generate
都是全新的,上一句根本没带过来。
-
一句话定义: 「会话(Session)」= 一个把多轮消息和自定义状态跨多次
generate攒起来、并能存盘/读盘的容器;「可观测性」= 让你在浏览器里逐帧回放一次调用到底 经过了哪些 prompt、工具、模型。 -
解决什么问题 / 给谁用:
- 给做多轮 Agent 的人:不想每轮手工拼
messages数组、不想自己写数据库存对话。 - 给调 Agent 卡壳的人:模型为什么突然罢工?工具传了什么参数?肉眼看 log 太痛苦, 要一张可点开的调用树。
- 给做多轮 Agent 的人:不想每轮手工拼
-
它能做什么(功能):
- 跨多次生成累积消息、维护一坨类型安全的自定义状态(
custom,如"当前订单")。 - 把每一轮的状态存成快照(snapshot),进程重启后还能按
sessionId接着聊。 - 每个 Action(flow / prompt / tool / model 调用)自动产出一个 span,零埋点。
- 本地跑
genkit start,浏览器打开 Dev UI,列出所有 Action、点一下就能跑、看 trace。
- 跨多次生成累积消息、维护一坨类型安全的自定义状态(
-
用起来什么样: 一个最小的有状态 Agent(源码里
defineAgent的 doc 示例,js/genkit/src/genkit-beta.ts:154-162):// 示意,非源码(改编自 defineAgent 的文档示例)const chatAgent = ai.defineAgent({name: 'chatAgent',model: 'googleai/gemini-2.5-flash',system: 'Talk like a pirate.',store: new FileSessionStore('./.snapshots'), // ← 有 store 就自动存盘});const chat = chatAgent.chat(); // 开一轮新会话await chat.send('我叫小明'); // 第 1 轮:记住了await chat.send('我叫什么?'); // 第 2 轮:答"小明"——历史被带上了console.log(chat.sessionId); // 这个 id 下次可以 loadChat 接着聊 -
一句话直觉/类比: 把 Session 当"这次对话的工作内存",把 SessionStore 当"磁盘"; 每轮结束拍一张快照存进磁盘,下次开机把最新快照读回内存,对话就无缝续上。可观测性那半边, 就像给整个程序装了行车记录仪:每个动作自动录一段,事后能倒带看。
本节不碰底层。记住两个词:Session(内存里的对话状态) 和 trace(一次调用的录像)。