
Genkit Reflection 协议 V2 深度解析基于 WebSocket 与 JSON-RPC 2.0 的双向反射架构【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit本文以 Genkit 仓库中的 docs/reflection-v2-protocol.md 为骨架结合 genkit-toolsCLI/Manager、JS 与 Go 运行时中的 V2 实现源码系统讲解 Genkit Reflection V2 协议的设计动机、传输层规范、JSON-RPC 2.0 消息格式、流式扩展、五大协议方法register / listActions / listValues / runAction / cancelAction的完整参数语义、健康检查机制以及从 V1 到 V2 的迁移要点。读完本文你将能够理解 Genkit CLI 与用户应用Runtime之间基于 WebSocket 的反射通道是如何建立、保活、断线重连并承载流式执行的也能据此在自己的 Runtime 实现中正确实现或对接 V2 协议。一、为什么需要 V2从「Runtime 开 HTTP 服务」到「CLI 起 WebSocket 服务」Reflection反射是 Genkit 开发者工具链的核心机制CLIRuntime Manager需要枚举用户应用中注册的 ActionFlow、Model、Tool 等、执行它们、读取输出从而驱动 Dev UI、genkit start等交互。V1 与 V2 的架构对比官方文档给出了精炼的对照版本架构V1Runtime 上启动 HTTP ServerCLI 通过 Polling/Request 方式访问V2CLI 上启动 WebSocket ServerRuntime 建立持久连接并主动连入V2 的核心变化是连接方向反转Server 角色Genkit CLIRuntimeManagerV2启动一个 WebSocket 服务器Client 角色Genkit Runtime用户应用作为 WebSocket 客户端连接到 CLI 的服务器。这一设计带来两个直接收益一个 CLI 管理多个 Runtime对于多服务multi-service项目多个 Runtime 可以各自建立一条 WebSocket 连接CLI 侧通过runtimeId区分与路由见下文listRuntimes/getRuntimeByIdRuntime 不再需要自行管理 HTTP 服务与端口反射能力不再依赖 Runtime 进程内额外的监听端口降低了用户应用的部署复杂度。二、传输层与消息结构2.1 传输规范特性规范协议WebSocket数据格式JSON消息结构JSON-RPC 2.0为流式做了扩展所有消息都遵循 JSON-RPC 2.0 规范每条消息都携带jsonrpc: 2.0版本字段并依据是否携带id区分请求/响应与通知。2.2 Request请求Manager 向 Runtime 发起调用时发送请求id由发送方Manager生成{ jsonrpc: 2.0, method: methodName, params: { ... }, id: 1 }id生成规则源码可证id可以是数字自增计数或字符串UUID在同一个 WebSocket 会话内对每个 pending 请求必须唯一。查看 manager-v2.ts 的实现RuntimeManagerV2内部维护pendingRequests: Mapnumber | string, ...通过requestIdCounter自增生成请求 ID(this.requestIdCounter).toString()而 Go 运行时 reflection_v2.go 使用atomic.Uint64自增序列生成字符串 ID。2.3 Response成功响应{ jsonrpc: 2.0, result: { ... }, id: 1 }响应通过id与请求对应。Manager 侧收到响应后会依据请求方法对result做 Zod Schema 校验例如listActions会经过ReflectionListActionsResponseSchema校验甚至对 Go 运行时可能携带的metadata: null做归一化处理见 manager-v2.ts 的normalizeListActionsResult。2.4 Response错误响应{ jsonrpc: 2.0, error: { code: -32000, message: Error message, data: { code: 13, message: Error message, details: { traceId: ..., stack: ... } } }, id: 1 }error.data中是一个与 V1 API 对齐的Status对象包含codeGenkit 规范状态码例如 13 表示 INTERNAL、3 表示 INVALID_ARGUMENTmessage错误信息details附加上下文包括traceId与stack堆栈。JSON-RPC 2.0 标准错误码在三端实现中保持一致见 reflection_v2.go错误码含义-32601Method not found方法不存在-32602Invalid params参数不合法-32000Server error服务端错误如 action 执行失败以runAction失败为例Go 运行时的sendRunActionErrorreflection_v2.go会把底层错误转换为status.Error并装配上述Status形状的data若错误链中存在context.Canceled则强制将状态码置为status.Cancelled方便 Dev UI 区分「用户主动取消」与「执行失败」并尽力提取traceId与stack写入details。2.5 Notification通知不带id的请求即为通知发送方不期待任何响应{ jsonrpc: 2.0, method: methodName, params: { ... } }Runtime 侧的sendNotificationreflection_v2.go发送的消息ID字段留空Manager 侧的sendNotificationmanager-v2.ts同样构造不带id的请求帧——这正是流式扩展得以实现的基础。三、流式扩展用 Notification 弥补 JSON-RPC 2.0 的短板JSON-RPC 2.0 原生不支持流式响应。V2 协议通过在 Runtime - Manager 方向上使用与特定 Request ID 关联的 Notification来扩展流式能力消息类型Method方向描述Stream ChunkstreamChunkRuntime - Manager在流式runAction请求执行期间Runtime 逐块发送输出State UpdaterunActionStateRuntime - Manager在返回最终结果之前Runtime 提供状态更新如 trace ID3.1 Stream Chunk Notification{ jsonrpc: 2.0, method: streamChunk, params: { requestId: 1, chunk: { ... } } }Manager 侧收到后通过streamCallbacks映射找到对应的StreamingCallback并调用之manager-v2.ts。JS 运行时在runAction的流式分支中把action.run的onChunk回调逐块转换为streamChunk通知reflection-v2.ts。3.2 Run Action State Notification{ jsonrpc: 2.0, method: runActionState, params: { requestId: 1, state: { traceId: ... } } }该通知用于在 span 启动时尽早把 trace ID 推送给 Manager使 Dev UI 能在 action 尚未结束时就开始关联追踪数据。Go 实现的runActionTelemetry.callbackreflection_v2.go在根 span 启动回调中记录 traceId、注册可取消的 active action并立即发送runActionState通知Manager 侧通过traceIdCallbacks把 traceId 回传给调用方manager-v2.ts。四、协议方法总览Method方向类型描述registerRuntime - ManagerRequest向 Manager 注册 Runtime 并获取初始配置listActionsManager - RuntimeRequest获取可用 Action 列表listValuesManager - RuntimeRequest获取 Value 列表prompts、schemas 等runActionManager - RuntimeRequest执行某个 ActioncancelActionManager - RuntimeRequest取消正在运行的 Action除此之外从双端实现源码可以看到还有一个文档方法表之外的通知方法configureManager - Runtime携带telemetryServerUrl用于在注册之后动态下发遥测服务器地址见 manager-v2.ts 与 reflection-v2.ts以及与双向流式输入相关的sendInputStreamChunk/endInputStreamManager - Runtime见本文第六节。五、详细 API 规范5.1 Registration注册方向Runtime - Manager类型Request参数字段类型描述idstring唯一 Runtime IDpidnumber进程 IDnamestring应用名称可选genkitVersionstring例如 0.9.0reflectionApiSpecVersionnumber协议版本号envsstring[]已配置的环境可选结果字段类型描述telemetryServerUrlstring遥测服务器 URL可选源码佐证参数组装JS 运行时在连接建立后立即注册reflection-v2.tsid取自process.env.GENKIT_RUNTIME_ID或默认的${process.pid}[-index]pid为process.pidgenkitVersion为nodejs/${GENKIT_VERSION}envs默认[dev]若注册响应的telemetryServerUrl非空且环境变量GENKIT_TELEMETRY_SERVER未设置则调用setTelemetryServerUrl完成遥测握手。Go 运行时reflection_v2.go的register同样组装这些字段runtimeID取自GENKIT_RUNTIME_ID环境变量缺省时回退为os.Getpid()genkitVersion为go/ internal.VersionreflectionApiSpecVersion使用internal.GENKIT_REFLECTION_API_SPEC_VERSION。协议版本号reflectionApiSpecVersion当前取值为1在 manager.ts 与 version.go 中均有常量定义。Manager 侧handleRegistermanager-v2.ts用 Zod SchemaReflectionRegisterParamsSchemareflection.ts校验参数构造RuntimeInfo存入runtimesMap触发RuntimeEvent.ADD事件并把telemetryServerUrl作为成功结果返回。5.2 List Actions列出 Action方向Manager - Runtime类型Request参数void结果类型描述{ actions: Recordstring, Action }一个包含actions字段的对象字段值为 Action key 到 Action 定义的映射源码佐证JS 运行时handleListActionsreflection-v2.ts从 registry 获取所有可解析 Action将key / name / description / metadata / inputSchema / outputSchemaJSON Schema 由toJsonSchema转换逐项写入响应Go 运行时则用listResolvableActions枚举后原样组装reflection_v2.go。Manager 侧收到后会补全缺失的action.keymanager-v2.ts。5.3 List Values列出 Value方向Manager - Runtime类型Request参数字段类型描述typestring要列出的 Value 类型例如 model、prompt、schema结果类型描述{ values: Recordstring, any }一个包含values字段的对象字段值为 Value key 到 Value 定义的映射实现限制以当前源码为准虽然文档示例中type可以是model、prompt、schema但当前 JS 与 Go 运行时实现均只接受defaultModel与middleware两种取值其余类型返回-32602Invalid params见 reflection-v2.ts 与 reflection_v2.go。Go 注册表目前不按类型细分type参数被接受但忽略仅用于保持与 JS 侧一致的错误形状。5.4 Run Action执行 Action方向Manager - Runtime类型Request参数字段类型描述keystringAction key例如 /flow/myFlowinputany输入载荷contextany上下文数据可选telemetryLabelsRecordstring, string遥测标签可选streamboolean是否流式返回结果streamInputboolean是否流式输入用于 bidi Action结果非流式字段类型描述resultany返回值telemetryobject遥测元数据例如{ traceId: string }Manager 侧构造请求时会自动推导这两个布尔标志stream: !!streamingCallback、streamInput: !!inputStreammanager-v2.ts。运行时侧用ReflectionRunActionParamsSchemareflection.ts即RunActionRequestSchema.extend({ stream, streamInput })校验入参。流式流程Streaming FlowRuntime 可选地发送runActionState通知Runtime 发送streamChunk通知Runtime 发送携带result的最终响应结构与非流式一致。JS 运行时在流式分支执行完毕后会先await flushTracing()再发送最终响应确保追踪数据已落盘reflection-v2.ts。双向流式流程Bidirectional Streaming FlowstreamInput: trueManager 发送sendInputStreamChunk通知Manager 发送endInputStream通知Runtime 按上述流式流程继续。这两个输入方向的 Notification 参数定义为{ requestId, chunk }与{ requestId }reflection.ts。Go 运行时的实现尤为细致reflection_v2.goreadLoop会在分发runAction之前预注册bidi session探测到streamInput: true即注册使得先于 action 初始化完成的输入块被缓冲而非丢弃bidiSession内部使用sync.Cond 事件队列按到达顺序把块投递给api.BidiJSONConnection队列无界但从不阻塞 WebSocket 读循环以保证cancelAction始终可被及时处理。5.5 Cancel Action取消 Action方向Manager - Runtime类型Request参数字段类型描述traceIdstring要取消的 Action 的 trace ID结果字段类型描述messagestring确认信息源码佐证JS 运行时维护activeActions: MaptraceId, { abortController, startTime }reflection-v2.tshandleCancelAction依据 traceId 找到对应条目后调用abortController.abort()并返回{ message: Action cancelled }找不到则返回-32602错误reflection-v2.ts。Go 运行时等价实现见handleCancelActionreflection_v2.go取消通过action.cancel()即 runAction 的context.CancelFunc触发。六、健康检查与连接保活检查类型描述连接状态WebSocket 连接状态本身即可作为基本的健康检查心跳应使用标准 WebSocket Ping/Pong 帧维持连接并检测超时连接生命周期管理在实现中体现得比文档描述更完整断线清理Manager 侧handleDisconnectmanager-v2.ts在连接关闭时移除对应 Runtime 并触发RuntimeEvent.REMOVEGo 运行时drainPendingreflection_v2.go会让所有未决请求以「connection closed」错误立即失败避免调用方无限阻塞。指数退避重连JS 客户端以 500ms 为基数、5s 为上限做指数退避重连baseDelayMs 500、maxDelayMs 5000见 reflection-v2.tsGo 客户端使用完全一致的重连参数并通过reconnectBaseDelay attempt计算退避间隔reflection_v2.go。中断的输入流兜底连接意外断开时JS 运行时closeInputStreams/failInputStreams会关闭/报错所有进行中的输入 Channel防止 action 体永久挂起reflection-v2.tsGo 运行时closeBidiSessions也会为每个在途 bidi session 入队结束标记让 action 优雅收尾reflection_v2.go。请求超时Manager 侧每个 pending 请求默认 30 秒超时超时后从pendingRequests移除并 rejectmanager-v2.ts。七、如何启用 V2以当前仓库为准V2 仍处于实验阶段CLI 通过--experimental-reflection-v2开关启用start.tsgenkit start --experimental-reflection-v2 -- your-app-command启用后的关键行为见 manager-utils.tsCLI 通过getPort({ port: makeRange(3200, 3400) })在 3200~3400 区间挑选一个空闲端口启动 WebSocket 服务器以环境变量GENKIT_REFLECTION_V2_SERVERws://localhost:port注入被启动的 Runtime 进程RuntimeManagerV2.startWebSocketServer会在启动时打印Starting reflection server: ws://localhost:port见 manager-v2.tsRuntime 进程启动时读取该环境变量并作为 WebSocket 客户端连入JS 侧见 reflection-v2.ts连接建立后立即发起register若未指定端口RuntimeManagerV2 同样使用 3200~3400 区间自动选择端口manager-v2.ts。此外 CLI 还提供--write-env-file file选项把上述环境变量以.env格式写入指定文件便于在外部启动的 Runtime 进程中手动注入start.ts。八、双端实现速览与源码地图V2 协议在仓库中的实现横跨「工具链Manager」与「运行时Runtime」两侧相关源码路径如下ManagerCLI 侧RuntimeManagerV2 核心实现WebSocket 服务器、register/streamChunk/runActionState处理、pending 请求与流式回调路由、bidi 输入转发协议参数与响应 Schema全部方法入参/出参的 Zod 定义启动命令与端口分配、环境变量注入Manager 单测 与 start 命令测试。JS Runtimereflection-v2.tsWebSocket 客户端、注册、方法分发、流式与 bidi 输入 Channel配套测试 reflection-v2_test.ts。Go Runtimereflection_v2.go连接生命周期、readLoop分发、bidi session 事件队列、错误归一化配套测试 reflection_v2_test.go。九、兼容性与迁移注意事项V1 与 V2 的关键差异可归结为一点谁是 Server、谁是 Client。V1 中 Runtime 启动 HTTP Server 供 CLI 轮询V2 中 CLI 启动 WebSocket ServerRuntime 建立持久连接。官方文档明确指出CLI 将根据配置决定使用哪种模式例如--experimental-reflection-v2开关。这意味着在 V2 正式化之前V1 仍作为默认/兜底通道存在两端需要保持对reflectionApiSpecVersion的协商能力当前协议版本为1。迁移到 V2 的实现者需要注意Runtime 需要实现主动外连 自动重连逻辑而非被动监听端口流式输出不再是 HTTP 分块响应而是与 Request ID 绑定的streamChunk/runActionState通知双向流式bidi依赖sendInputStreamChunk/endInputStream通知通道并需要考虑连接中断时输入流的兜底收尾错误上报必须携带Status形状的datacode/message/details以便 Dev UI 统一展示规范状态码与堆栈。十、结语Reflection V2 通过「连接方向反转 WebSocket 持久连接 JSON-RPC 2.0 流式扩展」三项设计把 Genkit 开发者工具的反射通道从「Runtime 被动暴露 HTTP 接口」升级为「CLI 主动聚合多 Runtime 的会话式通道」为多服务项目编排、流式生成预览、双向 Agent 会话等场景提供了统一且低开销的传输基础。无论是实现新的 Runtime 语言绑定还是理解genkit start与 Dev UI 背后的通信机制本文梳理的协议规范与源码映射都将是可靠的起点。【免费下载链接】genkitOpen-source framework for building agentic apps in JavaScript, Go, Dart, and Python, built and used in production by Google项目地址: https://gitcode.com/GitHub_Trending/ge/genkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考