跳转到内容

AgentRunner 状态管理:内存、SQLite 与 Intelligence 三种实现

AgentRunner 状态管理:内存、SQLite 与 Intelligence 三种实现

学习目标

理解 CopilotKit 的 AgentRunner 架构:

  • AgentRunner 抽象类的四个核心方法
  • InMemoryAgentRunner 的无状态特性
  • SQLiteAgentRunner 的持久化方案
  • IntelligenceAgentRunner 的 WebSocket + Redis 锁

前置知识

本章涉及记忆系统设计的通用原理,建议先阅读:

项目实践

AgentRunner 抽象类

抽象接口(源码验证):
abstract class AgentRunner {
abstract run(request: AgentRunnerRunRequest): Observable<BaseEvent>
abstract connect(request: AgentRunnerConnectRequest): Observable<BaseEvent>
abstract isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean>
abstract stop(request: AgentRunnerStopRequest): Promise<boolean | undefined>
}

Request 结构

AgentRunnerRunRequest:
{
threadId: string,
agent: AbstractAgent,
input: RunAgentInput,
persistedInputMessages?: Message[] // 从持久化恢复的历史消息
}
AgentRunnerConnectRequest:
{
threadId: string,
headers?: Record<string, string>,
joinCode?: string // Intelligence 模式的 WebSocket 加入码
}

InMemoryAgentRunner(默认)

最简单的实现,状态存于内存:

特性说明
存储Map<threadId, ThreadState>
持久化无,进程重启丢失
并发单实例内线程安全
适用开发环境、单实例部署

关键实现(467 行源码):

  • run():克隆 Agent → 设置 threadId/messages/state → 执行 → 发射事件
  • connect():恢复已有线程的状态 → 订阅事件
  • stop():标记线程为停止 → 清理资源
  • isRunning():检查线程的 isRunning 标志

SQLiteAgentRunner

持久化到 SQLite 数据库:

特性说明
存储SQLite 文件数据库
持久化进程重启不丢失
并发单写入者(SQLite 写锁)
适用单机生产部署、轻量场景

数据模型

  • threads 表:threadId、创建时间、最后活跃时间
  • messages 表:threadId、消息内容、角色、时间戳
  • states 表:threadId、状态 JSON

IntelligenceAgentRunner

Intelligence 模式:WebSocket + Redis 锁 + 云端持久化:

特性说明
传输WebSocket 实时连接
Redis 分布式锁(TTL + 心跳续约)
持久化云端存储(线程历史永久保留)
并发多实例部署支持
适用生产部署、多实例、持久化线程

线程锁机制(498 行源码):

锁生命周期:
1. run 开始时获取锁(Redis SETNX with TTL)
2. 运行期间定期续约(lockHeartbeatIntervalSeconds,默认 15s)
3. run 结束时释放锁
4. TTL 过期自动释放(兜底机制,最大 3600s)

关键约束

  • lockTtlSeconds:最大 3600s(1 小时),防止无限期锁定
  • lockHeartbeatIntervalSeconds:最大 3000s(50 分钟),必须小于 TTL
  • 如果续约间隔 >= TTL,锁可能在下次续约前过期

WebSocket 连接管理

  • 前端通过 WebSocket 连接到 Intelligence 平台
  • joinCode 用于多用户协作场景(共享线程)
  • 断线自动重连(指数退避,最大 maxReconnectMs

Runner 选择策略

问题与规避

问题规避策略
InMemory Runner 多实例状态不一致生产环境使用 Intelligence 模式 + Redis 锁
SQLite 写锁竞争高并发场景切换到 Intelligence 模式
Redis 锁泄漏(进程崩溃未释放)TTL 兜底;lockTtlSeconds 设置合理值
心跳续约间隔 >= TTL确保 lockHeartbeatIntervalSeconds < lockTtlSeconds
WebSocket 断线后消息丢失Intelligence 模式的云端持久化确保消息不丢失;断线重连后从游标恢复

设计取舍

三种 Runner 的权衡

维度InMemorySQLiteIntelligence
部署复杂度最低高(需要 Redis)
持久化文件级云端
并发性单实例单写入者多实例
成本中(Redis + 云服务)
适用规模开发/测试小型生产中大型生产

抽象类 vs 策略模式

抽象类(CopilotKit 的选择)

  • 优势:统一的接口和类型约束
  • 代价:新增 Runner 需要继承并实现所有抽象方法

策略模式(运行时注入不同实现)

  • 优势:更灵活,可以动态切换
  • 代价:类型安全较弱

参考来源

  • packages/runtime/src/v2/runtime/runner/agent-runner.ts
  • packages/runtime/src/v2/runtime/runner/in-memory.ts
  • packages/runtime/src/v2/runtime/runner/intelligence.ts
  • packages/sqlite-runner/