Genkit JS 会话与持久化实战:SessionStore、快照链与 Firestore 扩展方案
Genkit JS 会话与持久化实战SessionStore、快照链与 Firestore 扩展方案【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills本指南聚焦 Genkitgenkit在 Node.js/TypeScript 下 Agent 的**会话Session与持久化Persistence机制是 Agents 基础参考 的进阶专题。围绕agents-sessions.md展开你会掌握服务端如何通过不可变快照链snapshot chain**拥有对话历史学会选用InMemorySessionStore、FileSessionStore与生产级FirestoreSessionStore理解snapshotId续传、链剪枝、checkpointInterval调优并能按SessionStore接口实现自定义存储。这些能力是 Agent 的分支branching与后台执行background的前提——它们都要求 Agent 配置store。一、会话模型谁拥有历史就决定谁来存储在 Genkit 的 Agent 设计中store是一个分水岭当 Agent 带有store时服务端拥有完整的会话历史反之服务端无状态历史由客户端自行管理见 Agents 基础 中的 client-managed state 模式。带store的服务端会话模型有三个关键概念每次轮次产生一个不可变快照snapshot每执行一轮对话服务端就把当时的完整状态固化成一个快照快照一旦生成就不可修改快照链承载会话状态会话的前进不是“就地修改”而是不断追加新的快照形成一条链条链条的末端即当前会话状态快照是分支与后台执行的支点正因为快照不可变才能从任意快照分叉出独立时间线branching也才能把一轮对话放到后台并随时查询其状态background。本仓库的 agents-branching.md 明确写道分支需要 session store 以保证快照持久化agents-background.md 也要求 detach 必须配置 store——服务端需要地方写入后台任务的最终结果。而中断interrupt人机协同与持久化是正交的无论是否配置store中断都能工作。有 store 时靠快照把暂停的轮次带回 resume 调用无 store 时靠客户端回传状态 blobremoteAgent客户端自动处理。详见 Human-in-the-loop / interrupts。Beta 提示Session store 属于 preview API。InMemorySessionStore、FileSessionStore从genkit/beta导入FirestoreSessionStore从genkit-ai/google-cloud/beta导入Agent 相关 API 统一要求使用genkit/beta而非genkit且需要genkit 1.39.0见 genkit-js SKILL。二、选择并挂载 SessionStore1. 内存存储测试与开发的默认选择InMemorySessionStore把所有快照保存在进程内存中零配置、速度最快但重启即丢失import { InMemorySessionStore } from genkit/beta; // In-memory: great for tests/dev; lost on restart. const memStore new InMemorySessionStore();2. 文件存储本地方案与链剪枝FileSessionStore将每个快照以 JSON 文件形式持久化到磁盘快照按dir/global/snapshotId.json的结构存放import { FileSessionStore } from genkit/beta; // File-backed: snapshots persisted under dir/global/snapshotId.json const fileStore new FileSessionStore(./.snapshots);它支持一个实用的构造选项maxPersistedChainLength限制每条快照链最多保留的最近 N 个快照用于剪枝、防止磁盘无限膨胀。例如只保留链上最近 3 个快照// File store with chain pruning — keep only the last N snapshots in a chain. const pruning new FileSessionStore(./.snapshots, { maxPersistedChainLength: 3, });剪枝只影响“保留多少历史”被剪掉的是链上更早的旧快照当前会话状态不受影响如果你还需要从更早的时间点分支则应调大该值或换用可扩展存储。3. 挂载到 Agent通过defineAgent的store选项把存储实例绑定到 Agentimport { ai } from ./genkit.js; export const logbookAgent ai.defineAgent({ name: logbookAgent, system: You are a personal logbook assistant., store: fileStore, });ai来自genkit/beta而非genkit这是 Agent API 的硬性要求。挂载后该 Agent 的所有轮次都会自动写入存储并向前传递快照。三、多轮对话与快照自动续传挂载了store之后同一个chat实例会在多轮之间自动携带历史你无需手工拼接上下文const chat logbookAgent.chat(); const res1 await chat.send(Log this: I started studying Genkit today.); const res2 await chat.send(What did I study today?); // remembers turn 1 console.log(res1.snapshotId, res2.snapshotId);这里有两个要点chat.send()每轮返回一个res.snapshotId即本轮结束时固化的不可变检查点 ID。两次调用打印出的snapshotId不同说明状态确实以快照链形式前进chat对象内部维护着“当前快照”指针第二轮send会基于第一轮的快照继续所以“What did I study today?”能回忆起第一轮的内容。通过 snapshotId 恢复历史会话当会话被打断例如服务重启、客户端刷新可以用任意已知快照 ID 打开新chat并从该快照继续// Continue an existing session from its latest snapshot. const resumed logbookAgent.chat({ snapshotId: res2.snapshotId }); await resumed.send(Add another note.);chat({ snapshotId })是续传与分支共用的入口传“当前链末端”的 ID 是续传传“链中间”的 ID 则是从该点分叉出一条新的独立时间线原快照保持不变。这也是把snapshotId存进 URL、刷新后恢复 UI 的基础——配合服务端暴露的getSnapshotDataAction见 agents-deployment.md可以先只读快照、渲染历史再在用户继续对话时用chat({ snapshotId })无缝接上。四、Typed Session State给会话绑定类型化自定义状态除了消息历史一个会话还可以持有类型化的自定义状态用户档案、任务列表、工作流状态等业务数据。方式是在defineAgent中声明stateSchemaZod schemaimport { z } from genkit; const Profile z.object({ name: z.string(), tier: z.enum([free, pro]) }); export const profileAgent ai.defineAgent({ name: profileAgent, system: Greet the user by name and tailor answers to their tier., store: new InMemorySessionStorez.infertypeof Profile(), stateSchema: Profile, });这里值得注意的类型细节SessionStoreS是泛型接口S即自定义状态类型这里传入z.infertypeof ProfileState由stateSchema推断得出且在快照加载时会执行 Zod 校验——如果持久化的状态与 schema 不匹配加载即失败从源头杜绝脏数据。打开会话时用state参数播种初始自定义状态。自定义数据放在SessionState的.custom字段下stateSchema校验的正是这个字段与messages、artifacts平级// Seed custom state when opening the chat. Custom state lives under .custom // of the SessionState (thats what stateSchema validates). const chat profileAgent.chat({ state: { custom: { name: Ada, tier: pro } }, });在轮次进行中工具可以通过ai.currentSessionS()拿到当前会话再用session.getCustom()/session.updateCustom(mutator)读取和原子修改自定义状态详见 Working with Agent State。在浏览器/HTTP 客户端一侧remoteAgentT会把你声明的状态类型自动同步到chat.state注意客户端上自定义字段会被扁平化到chat.state顶层例如chat.state.tasks而非chat.state.custom。五、中断Interrupts与持久化正交组合agents-sessions.md专门强调中断不需要 store。中断的实质是一次“作为控制流使用的工具调用”——中断工具不会在服务端真正执行只是让当前轮次暂停等你收集到人类输入后再用chat.resume({ respond: [...] })从暂停点精确恢复。持久化方式只是决定“暂停的轮次如何被带回 resume 调用”带 store快照链自动完成这件事resume 时根据快照恢复上下文不带 storeclient-managed state客户端把状态 blob 随请求回传remoteAgent客户端自动处理。因此你可以自由组合无存储 中断 轻量审批流有存储 中断 可审计、可续传的审批流。完整的定义、检测res.interrupts、builderrespond/restart与 resume 校验规则见 agents-human-in-the-loop.md。一个值得提前知道的约束只有completed状态的快照可以 resumefailed/aborted/pending 的快照仅供检查。六、FirestoreSessionStore面向生产的可扩展持久化Beta对于生产环境的长会话如长期使用的聊天机器人、编码助手内存与单文件存储都不够前者重启即失后者整个会话链会越滚越大。Genkit 提供FirestoreSessionStore来自genkit-ai/google-cloud/beta作为可扩展方案其核心设计是增量 JSON Patch diff 周期性分片检查点每一轮对话只把“相对上次状态的差异”写成 JSON Patch 增量而不是重写整个会话每隔checkpointInterval轮次才落一个完整的全量检查点并把累计的 diff 分片存储每个分片有字节上限shardSize结果是没有任何单个文档会逼近 Firestore 的 1 MiB 单文档上限且每轮读写量由checkpointInterval决定而不是随会话总长度线性增长——这正是长生命周期会话聊天/编码 Agent需要的行为。import { genkit } from genkit/beta; import { FirestoreSessionStore } from genkit-ai/google-cloud/beta; const ai genkit({ plugins: [/* ... */] }); const myAgent ai.defineAgent({ name: myAgent, system: You are a helpful assistant., // Defaults to a new Firestore() using Application Default Credentials. store: new FirestoreSessionStore(), });构造选项详解选项默认值说明调优建议db自动新建Firestore()显式指定 Firestore 实例默认实例遵循FIRESTORE_EMULATOR_HOST环境变量本地模拟器可用需要复用连接、配置项目/凭据时传入显式实例collectiongenkit-sessions快照主集合名伴生集合collection-pointers指针与collection-shards分片由其推导多环境隔离时按环境命名checkpointInterval25每多少次轮次做一次全量检查点状态小而读密集→调小每轮状态很大→调大shardSize512 KiB单个分片/diff 文档的最大字节数默认值已贴近 Firestore 文档上限的安全余量一般无需改动选项背后是存储的读改写放大权衡checkpointInterval越小全量检查点越频繁恢复路径越短、读越轻但写放大越大反之适合每轮增量很大的场景。如果运行在Firebase环境genkit-ai/firebase会以 Firebase app 初始化方式提供firebaseApp选项重新导出该 store详见其包 README。七、实现自定义 SessionStore内置存储覆盖了本地内存/文件与云端Firestore场景但如果你需要对接 Redis、PostgreSQL 或自建持久化层可以按SessionStoreS接口实现自己的 store。接口来自genkit/beta包含三个方法import type { SessionStore } from genkit/beta; // S is the custom state type. const store: SessionStoreMyState { // Load a snapshot by snapshotId OR sessionId (exactly one). async getSnapshot(opts) { /* ... */ return undefined; }, // Atomically read → mutate → persist. Returns the snapshotId used, // or null when the mutator returns null. async saveSnapshot(snapshotId, mutator, options) { /* ... */ return snapshotId ?? new-id; }, // Optional: subscribe to snapshot state changes (used by background agents). onSnapshotStateChange(snapshotId, callback, options) { return () {}; // unsubscribe }, };逐个方法拆解getSnapshot(opts)按snapshotId或sessionId加载快照两者必须恰好传一个。这是续传、分支、后台轮询getSnapshotaction与 UI 恢复的读取入口找不到时返回undefined。saveSnapshot(snapshotId, mutator, options)核心的**原子“读→改→写”**操作。mutator接收当前快照状态、返回新状态实现需要保证并发下不会相互覆盖Firestore store 正是用事务/Patch 来保证这一点。返回值是实际落盘的snapshotId当mutator返回null表示放弃写入时返回null。onSnapshotStateChange(snapshotId, callback, options)可选方法订阅某个快照的状态变化返回一个取消订阅函数。后台 Agent 依赖它来感知pending→completed/failed/aborted/expired的状态迁移见 agents-background.md 的状态机。实现时还要考虑两个与上层能力的契约快照必须不可变分支语义依赖这一点已存在的快照不能被原地覆盖后台轮询要求getSnapshot能随时读到最新状态。八、选型建议与能力矩阵综合本仓库 SKILL.md、agents.md 与agents-sessions.md可以做如下决策场景推荐存储理由单元测试、本地原型、快速 DemoInMemorySessionStore零配置、无副作用、重启即清空单机开发/演示、需要重启后保留历史FileSessionStore可配合maxPersistedChainLength剪枝快照落盘为 JSON简单可查生产环境、长会话、多实例FirestoreSessionStorediff分片检查点设计规避 1 MiB 文档上限每轮读写量与会话长度解耦已有自建存储Redis/PG 等自定义SessionStore只需实现getSnapshot/saveSnapshot可选订阅需要store 作为前置条件的能力有分支branching从旧快照分叉时间线、后台执行background/detach服务端需要写最终结果、通过snapshotId跨进程续传会话。仅做普通多轮对话且不关心服务端持有历史时可以不配 store改用客户端管理状态remoteAgent自动回传状态 blob两者都能配合中断使用。最后提醒 Beta 期使用要点Agent 相关 import 一律走genkit/beta与genkit-ai/google-cloud/beta需要genkit 1.39.0生产部署时若需要快照恢复/后台轮询记得通过expressHandler暴露agent.getSnapshotDataAction与agent.abortAgentAction这两个伴生 action对应路径/api/name/getSnapshot、/api/name/abort与remoteAgent客户端默认路径一致完整服务编排见 agents-deployment.md。【免费下载链接】skillsAgent Skills for Google products and technologies项目地址: https://gitcode.com/GitHub_Trending/skills29/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考