
CopilotKit Runtime 中 AgentRunner 怎么选InMemory、Sqlite 与 Intelligence【免费下载链接】CopilotKitThe Frontend Stack for Agents Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit搭建 CopilotKit Runtime 时每个 runtime 都把 agent 执行和会话持久化委托给一个AgentRunner。runner 负责把POST /agent/:id/run变成一条 AG-UI 事件流记住 thread 以便POST /agent/:id/connect重新挂接并在需要时停止运行。选择或子类化runner 决定了对话状态存放在哪里进程内存、本地 SQLite 文件还是 CopilotKit Intelligence 平台。这篇文章给出三者的适用条件、配置写法和验证方式覆盖从本地开发到单实例上线再到多实例扩展的选型路径。AgentRunner 是什么、由谁承担AgentRunner是一个抽象类有四个方法与 runtime 的 HTTP 路由一一对应详见 AgentRunner and persistenceimport type { Observable } from rxjs; import type { BaseEvent } from ag-ui/client; abstract class AgentRunner { // 启动一次 run返回 AG-UI 事件流 abstract run(request: AgentRunnerRunRequest): ObservableBaseEvent; // 重新挂接到已有 thread 的流reconnect / 刷新页面 abstract connect(request: AgentRunnerConnectRequest): ObservableBaseEvent; // 该 thread 当前是否有活跃的 run abstract isRunning(request: AgentRunnerIsRunningRequest): Promiseboolean; // 停止该 thread 上正在进行的 run abstract stop(request: AgentRunnerStopRequest): Promiseboolean | undefined; }run接收threadId、克隆后的agent、AG-UIRunAgentInput以及persistedInputMessagesconnect接收threadId外加可选的 headers 和joinCode。thread 背后的存储由 runner 自己持有。不传runner时runtime 默认使用InMemoryAgentRunner。runner在CopilotRuntime上只配置一次对它的每个 agent 生效同一个 runner 处理所有已注册 agent 的run、connect和stop。按部署形态选 runner文档给出的内置 runner 及用途如下Runner导入来源适用场景InMemoryAgentRunnercopilotkit/runtime/v2v2 默认 runner。thread 保存在进程内存中用于本地开发、单实例部署或作为扩展基类SqliteAgentRunnercopilotkit/sqlite-runner第一方文件级持久化 runner。thread 运行记录写入 SQLite 文件单实例重启后历史仍在。需要better-sqlite3peer 依赖和一个真实非:memory:的dbPathIntelligenceAgentRunnercopilotkit/runtime/v2为 CopilotKit Intelligence 提供持久化 thread、跨实例持久化和 threads/history 功能。在 Intelligence runtime 上自动使用TelemetryAgentRunnercopilotkit/runtime旧版包装行为。根 runtime 在开启遥测时会在 runner 外组合遥测层copilotkit/runtime/v2不这样做据此可以按三条主路径决策本地开发或单实例、不要求重启后保留历史保持默认的InMemoryAgentRunner。单实例生产部署要求重启后历史仍在换成第一方SqliteAgentRunner。多实例水平扩展使用 CopilotKit Intelligence 的IntelligenceAgentRunner或者自己提供一个基于共享数据存储的 runner文档建议的子类化路径见后文。InMemoryAgentRunner的历史在重启时丢失、进程运行期间有界见下文边界配置且不在多实例间共享。这三点就是它不能作为多实例方案的依据。配置 InMemoryAgentRunner 并给内存历史上界最小配置以 Next.js App Router 为例import { CopilotRuntime, BuiltInAgent, InMemoryAgentRunner } from copilotkit/runtime/v2; const runtime new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: openai/gpt-4o-mini }) }, // 显式声明省略时也是这个默认值 runner: new InMemoryAgentRunner(), });InMemoryAgentRunner把每个 thread 的运行历史放在一个进程级全局 store 中。该 store默认就有上界长生命周期服务会驱逐旧历史而不是把 Node.js 堆撑爆。当默认值不匹配你的负载时通过构造函数传入限制import { CopilotRuntime, BuiltInAgent, InMemoryAgentRunner } from copilotkit/runtime/v2; const runtime new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: openai/gpt-4o-mini }) }, runner: new InMemoryAgentRunner({ maxThreads: 200, maxRunsPerThread: 50, maxBytes: 128 * 1024 ** 2, // 128 MiB }), });选项默认值约束对象maxThreads1000保留的不同 thread 数量。超限时整个丢弃最近最少使用的 threadmaxRunsPerThread100每个 thread 保留的 run 数按最旧优先驱逐。设为Infinity或0会关闭该上限——这是唯一的按线程边界maxBytes只驱逐其他 thread单个热 thread 会无限增长文档建议改为一个较大的有限值maxBytes536870912512 MiB所有 thread 保留历史的近似总大小是主要防线两个计数是次要的保险上限哪个边界先触发哪个生效。两条规则保证驱逐安全有活跃或仍在收尾的 run 的 thread 永远不会被驱逐即使这意味着暂时超限。maxBytes是跨 thread 的上限它驱逐其他最近最少使用的 thread从不裁剪刚结束 run 的 thread。单个热 thread 只受maxRunsPerThread约束不受maxBytes约束。驱逐有两种形式移除的内容和影响范围不同整 thread 驱逐整体丢弃最近最少使用的 thread——所有 run、事件和该 thread 的消息快照。maxThreads和maxBytes都会触发它。被驱逐的 thread 不再出现在GET /threads中后续connect()也没有任何内容可回放。run 上限裁剪maxRunsPerThread只丢弃单个超上限 thread 的最旧 runthread 本身保留。该 thread 仍出现在GET /threads中、保留原始创建时间最新消息快照和最新 run 都在——只有被裁剪 run 的事件消失了后续connect()回放剩余部分。任一形式触发时都会打一条单行警告然后保持安静。该警告每个 store 只锁存一次不是每次驱逐一次所以频繁的驱逐不会刷爆日志锁存只在 store 被清空clearThreads()/POST /threads/clear后复位之后最多再触发一次警告。把它当作正在发生驱逐的信号而不是逐条丢弃的审计记录。驱逐还会削弱该 thread 上的消息去重。run()通过扫描仍持有的 run 来剥离输入中已见过的消息一旦 thread 超过maxRunsPerThread且最旧 run 被丢弃只存在于被驱逐 run 中的消息就不再被识别为已见过后续connect()或run()可能再次呈现它客户端可能短暂显示一条已见过的历史消息。这是显示层面的现象不是数据损坏。如果某个 thread 绝不允许旧消息重新出现应迁移到持久化 runner或把maxRunsPerThread调大为有限值——不要设为Infinity或0那会移除唯一的按线程边界让单个长生命周期 thread 增长到堆耗尽。一个必须注意的坑这些限制是进程全局的。所有InMemoryAgentRunner共享同一个进程内存 store限制也一样——最后一个传入限制的 runner 生效于所有内存 thread会静默覆盖之前 runner 设置的边界。文档明确提示不要指望日志来发现这个问题覆盖警告只在传入限制的 runner 之后又出现另一个传入不同限制的runner 时才触发一个用默认值、第二个传自定义限制的常见场景属于首次显式覆盖不产生日志。一个进程里只配置一套一致的限制。设置上界防止的是崩溃不等于持久化。如果不能接受历史丢失就切换到下面的持久化后端。配置 SqliteAgentRunner 让历史在重启后保留SqliteAgentRunner来自copilotkit/sqlite-runner把 thread 运行记录持久化到 SQLite 文件单实例重启后历史仍在。使用前提有两个安装better-sqlite3peer 依赖包声明的版本约束是^12.2.0并提供一个真实的、非:memory:的dbPathimport { CopilotRuntime, BuiltInAgent } from copilotkit/runtime/v2; import { SqliteAgentRunner } from copilotkit/sqlite-runner; const runtime new CopilotRuntime({ agents: { default: new BuiltInAgent({ model: openai/gpt-4o-mini }) }, runner: new SqliteAgentRunner({ dbPath: ./data/threads.db }), });dbPath: ./data/threads.db是文档给出的示例路径指向一个可写目录下的真实文件。copilotkit/sqlite-runner要求 Node18。接入 CopilotKit Intelligence需要跨水平扩展实例共享历史时文档给的路径是 Intelligence 的IntelligenceAgentRunner在 Intelligence runtime 上自动使用或者自建共享数据存储 runner。接入托管平台的接线步骤见 Connect your runtime to Intelligence准备项目 API key。用 CLInpx copilotkit login npx copilotkit project selectproject select会把项目级 key 写入.env的CPK_INTELLIGENCE_API_KEY。该 key 是服务端机密不要加NEXT_PUBLIC_或VITE_前缀。构造CopilotKitIntelligence客户端并作为intelligence传给 runtime。runtime 从你传入的客户端读取 key不是从环境读import { CopilotRuntime, CopilotKitIntelligence, createCopilotRuntimeHandler, } from copilotkit/runtime/v2; const intelligence new CopilotKitIntelligence({ // apiUrl 和 wsUrl 默认指向托管平台不要设置 apiKey: process.env.CPK_INTELLIGENCE_API_KEY!, }); const runtime new CopilotRuntime({ agents, intelligence, // Threads 按用户隔离否则所有访客共享同一份历史 identifyUser: (request) ({ id: request.headers.get(x-user-id) ?? anonymous, name: request.headers.get(x-user-name) ?? Anonymous, }), }); export const { GET, POST } createCopilotRuntimeHandler({ runtime });apiKey是唯一必填字段key 本身限定项目范围不需要另传组织或 project id。agents是你的 agent 注册对象需自行替换为实际应用中的注册内容。如果是自托管部署apiUrl和wsUrl必须一起覆盖或都不覆盖——API 面和实时面部署在不同主机上websocket URL 无法从 API URL 推导只设一个会让另一面仍指向托管主机。传裸 websocket 基址即可客户端自己追加/runner和/client并给每个 REST 调用加/api前缀传apiUrl: .../api会产生/api/api/threads这样的双前缀。验证 runner 是否按预期工作文档给出的检查方式按 runner 分别对应InMemory / Sqlite用GET /threads查看当前保留的 thread。被整 thread 驱逐的 thread 会从这里消失被maxRunsPerThread裁剪的 thread 仍在列表中且保留原始创建时间。刷新或断线后用POST /agent/:id/connect重新挂接能回放的内容就是 runner 实际保留的历史——这正是验证持久化与否最直接的行为差异重启后 InMemory 为空Sqlite 仍能回放。Intelligence编译通过和聊天能回复都证明不了 Intelligence 在工作——runtime 在 SSE 模式下不读 key 也能做到这些。文档要求的验证方式是从产品侧确认打开云托管 dashboard在应用里发一条消息应该出现一个 thread没有出现就说明 runtime 根本没有连到平台实际仍跑在 SSE 模式。对应的排查表现象原因聊天正常dashboard 里没有 threadintelligence没有传给CopilotRuntimeruntime 处于 SSE 模式首个请求出现不透明的鉴权错误CPK_INTELLIGENCE_API_KEY为空或属于别的项目socket 停在connecting随后报 did not settle in time只覆盖了wsUrl或把它指向了 API 主机请求日志里出现/api/api/...apiUrl带了/api后缀并发 run 与自定义 runner 的边界当你的 UX 允许用户快速发送追问、或卡住的 run 需要被顶替时可以对并发的run()选择 supersede 语义默认行为是对同一 thread 的并发run()抛Thread already runningimport { InMemoryAgentRunner } from copilotkit/runtime/v2; const runner new InMemoryAgentRunner({ onConcurrentRun: supersede });取值行为throw默认同一 thread 上的并发run()抛出Thread already runningsupersede进行中的 run 被中止走stop()同一条路径新 run 开始被顶替 run 的部分输出被丢弃不写入历史与内存限制不同onConcurrentRun是按 runner的只作用于你传入它的那个 runner。需要共享数据存储或外部记忆层时最常见的定制方式是子类化InMemoryAgentRunner只覆盖需要的方法、其余调用superimport { InMemoryAgentRunner } from copilotkit/runtime/v2; export class MyRunner extends InMemoryAgentRunner { override run(request: ParametersInMemoryAgentRunner[run][0]) { // 在此持久化 request.threadId / input然后委托 return super.run(request); } override connect(request: ParametersInMemoryAgentRunner[connect][0]) { // 重新挂接前先从自己的存储恢复 thread return super.connect(request); } }这里有一个文档明确要求的边界情况如果connect()可能被调用在 runner 从未见过的 thread 上例如首次页面加载时的新 thread id必须显式处理否则POST /agent/:id/connect会在用户发消息之前返回 404 或报错。完整的生产级示例可参考仓库中的 AWS AgentCore 集成AWS AgentCore 文档 指向的/deploy/agentcore页面。限制小结InMemoryAgentRunner的历史重启即失、进程内不跨实例共享上界配置防止内存耗尽但不提供持久化。内存限制是进程全局的多个传限 runner 时最后一个生效且该场景通常无日志。SqliteAgentRunner解决单实例重启问题依赖better-sqlite3和真实dbPath跨实例仍需 Intelligence 或自建共享存储 runner。TelemetryAgentRunner属于copilotkit/runtime根入口的旧版组合行为copilotkit/runtime/v2不做这件事——新项目按 v2 方式配置 runner 和遥测。下一步若需了解每个 runner 方法对应的路由细节见 Runtime HTTP endpoints运行时整体配置见 Copilot Runtime。【免费下载链接】CopilotKitThe Frontend Stack for Agents Generative UI. React, Angular, Mobile, Slack, and more. Makers of the AG-UI Protocol项目地址: https://gitcode.com/GitHub_Trending/co/CopilotKit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考