基于Cloudflare Workers与TiDB Cloud构建AI智能体安全共享记忆服务
1. 项目概述为AI智能体构建一个安全、隔离的共享记忆服务最近在折腾AI智能体Agent的协作发现一个挺有意思的痛点不同的智能体实例比如OpenClaw、KimiClaw它们之间如何安全、高效地共享“记忆”想象一下一个智能体学会了用户喜欢用深色模式另一个智能体在处理UI配置时如果能直接读取这个偏好体验就无缝衔接了。但直接把记忆数据存在某个公共数据库安全和隔离就成了大问题。最近看到siddontang开源的claw-memory项目它用Cloudflare Workers和TiDB Cloud搭建了一个专门的服务完美解决了这个需求。它不是简单地提供一个数据库端点而是设计了一套包含自动资源分配、多层加密和完整生命周期的解决方案特别适合我们这些搞AI应用开发的。今天我就结合自己的部署和测试经验把这个项目的里里外外拆解清楚包括架构设计、安全考量、实操步骤以及我踩过的那些坑。2. 架构深度解析为什么选择Worker TiDB Cloud Zero这个项目的核心架构非常清晰目标明确为每一个独立的智能体小组由同一个Token标识提供一个完全隔离、即开即用、且安全的数据存储空间。整个系统可以看作一个智能的“记忆空间”分发与管理平台。2.1 核心组件与数据流整个系统围绕两个核心后端和一个前端接入层构建Cloudflare Worker (claw-memory)这是整个服务的大脑和网关。所有来自OpenClaw、KimiClaw等智能体的API请求都首先到达这里。它不直接存储业务数据而是负责三件关键事身份认证与路由验证Token并转发到正确的数据库、安全处理执行加密解密逻辑、资源调度按需创建新的TiDB Cloud Zero实例。注册表数据库 (Registry DB)这是一个中心化的TiDB Serverless集群用来保存整个系统的“户口本”。它存储所有已签发的Token与其对应的TiDB Cloud Zero实例连接信息之间的映射关系。这里的设计关键是存储的连接信息主机、用户、密码是经过AES-256-GCM加密的即使有人直接访问这个数据库也无法直接获取到下游业务数据库的凭据。TiDB Cloud Zero实例 (业务数据库)这是真正存储每个智能体小组“记忆”数据的地方。核心设计在于“一个Token一个独立数据库实例”。当服务接收到创建新Token的请求时它会通过TiDB Cloud API实时约2秒创建一个全新的Zero实例。这个实例与其他Token的实例在物理和逻辑上都是隔离的从根本上杜绝了数据跨组泄露的可能性。数据流转的路径是这样的智能体带着Token访问WorkerWorker解密Token从注册表查出对应的加密连接串再用密钥解密获得真实的数据库连接信息最后Worker作为代理将智能体的CRUD操作转发到那个完全属于该Token组的TiDB Zero实例中执行。整个过程对智能体来说是透明的它只需要认准一个Token即可。2.2 关键设计决策背后的逻辑为什么这么设计我们逐条分析其优势完全的数据隔离这是最核心的安全边界。传统的多租户方案可能在同一个数据库里用不同表或Schema来区分用户但这存在误操作或漏洞导致越权的风险。claw-memory直接为每个租户分配一个独立的数据库实例实现了物理隔离安全性提升了一个数量级。对于AI智能体这种可能处理不同用户、不同项目敏感上下文的应用这种隔离是必需的。加密的注册表注册表成了“钥匙保管员”。即使最坏的情况发生——注册表数据库被攻破攻击者拿到的也是一堆密文。加密密钥ENCRYPTION_KEY独立存储在Cloudflare Worker的Secret中与数据库分离符合安全实践中的“密钥与数据分离存储”原则。可选的客户端加密这是一个为高安全场景设计的“杀手级”特性。智能体在创建Token时可以提供一个自己的X-Encryption-Key。这个密钥会与服务器密钥一起对数据库连接信息进行二次加密。结果是连服务器都无法单独解密出连接信息。每次请求智能体都必须携带这个客户端密钥Worker用它完成部分解密后才能访问数据库。这适用于对云服务提供商本身也不完全信任的场景实现了“端到端”加密的存储层。零摩擦资源供给TiDB Cloud Zero的“零配置、秒级创建”特性是这个项目能成立的基础。它让按需分配独立数据库实例从成本和技术上变得可行。开发者无需预先购买、配置数据库系统在用户无感的情况下自动完成体验非常流畅。30天生命周期与认领机制TiDB Cloud Zero实例免费提供30天。这实际上是一个很巧妙的“试用转正”漏斗。项目提供了claim_url引导用户在30天内将临时Zero实例认领为永久的TiDB Cloud Starter实例目前也是免费套餐。这既降低了用户初次使用的门槛又为TiDB Cloud提供了潜在的转化路径。认领后原有Token和连接完全不变对智能体无影响设计得很贴心。注意虽然TiDB Cloud Starter目前免费但其资源规格如存储空间、吞吐量是有限的。如果你的智能体记忆数据量增长非常快需要关注用量并考虑升级到付费计划。3. 从零开始部署一步步搭建你的记忆服务理论讲完了我们动手把它跑起来。部署过程主要分三步准备注册表数据库、配置Worker、部署。我会补充一些官方文档里没细说的细节。3.1 环境准备与依赖安装首先确保你的开发环境已经就绪# 1. 克隆项目代码 git clone https://github.com/siddontang/claw-memory.git cd claw-memory # 2. 安装项目依赖 (Node.js环境) npm install # 3. 安装并登录Wrangler (Cloudflare Workers命令行工具) npm install -g wrangler wrangler login执行wrangler login会打开浏览器让你授权CLI工具访问你的Cloudflare账户。确保你拥有一个Cloudflare账户并且有权限在某个账户下创建Worker。3.2 设置注册表数据库TiDB Serverless这是整个服务的“总控中心”需要一个长期稳定的TiDB集群。我们使用TiDB Cloud Serverless因为它免费且易于管理。创建Serverless集群登录 TiDB Cloud控制台 进入项目后点击“Create Cluster”选择“Serverless”套餐。填写集群名称如claw-memory-registry选择提供商和区域建议选一个离你的用户或Cloudflare Worker较近的区域如ap-northeast-1点击创建。几分钟后集群就绪。获取连接信息在集群详情页点击“Connect”按钮选择“General”方式你会看到Host网关地址、Port、User和Password。记录下这些信息。Database名字可以自己定比如claw_memory_registry。初始化注册表结构项目提供了数据库初始化脚本。通过环境变量传入连接信息来运行它REGISTRY_HOSTgateway01.ap-northeast-1.prod.aws.tidbcloud.com \ REGISTRY_USERyour_username \ REGISTRY_PASSWORDyour_password \ REGISTRY_DATABASEclaw_memory_registry \ npm run db:init实操心得这里有个小坑如果密码包含特殊字符如!,,#在Bash中最好用单引号包裹整个密码防止被Shell解析。执行成功后脚本会在指定的数据库中创建token_registry等必要的表。3.3 配置Cloudflare Worker密钥Worker需要访问注册表数据库和进行加密这些敏感信息不能写死在代码里必须通过Cloudflare的Secret管理。生成加密密钥首先为服务器端加密生成一个强密钥openssl rand -hex 32这会输出一个64位的十六进制字符串如a1b2c3...复制下来这就是你的ENCRYPTION_KEY。设置Secret在项目根目录下使用Wrangler命令将敏感信息设置为Secret。这些值会被加密存储仅在Worker运行时注入。# 设置注册表数据库连接信息 npx wrangler secret put REGISTRY_HOST # 在弹出的交互窗口中粘贴你的TiDB Serverless主机地址 npx wrangler secret put REGISTRY_USER # 粘贴数据库用户名 npx wrangler secret put REGISTRY_PASSWORD # 粘贴数据库密码 npx wrangler secret put REGISTRY_DATABASE # 粘贴数据库名如claw_memory_registry # 设置服务器加密密钥 npx wrangler secret put ENCRYPTION_KEY # 粘贴刚才用openssl生成的64位密钥注意事项wrangler secret put命令是交互式的你也可以通过管道传递值如echo “your_value” | npx wrangler secret put SECRET_NAME。确保所有Secret一次性正确设置否则部署后Worker会因缺少配置而启动失败。3.4 部署与验证配置完成后部署就很简单了npm run deploy部署脚本会构建项目并将Worker发布到Cloudflare。成功后你会看到Worker的访问地址格式类似https://claw-memory.你的子域.workers.dev。记下这个地址它就是你的记忆服务的API入口。验证部署是否成功# 使用curl测试创建Token的端点 curl -X POST https://claw-memory.你的子域.workers.dev/api/tokens如果返回类似{ok:true,data:{token:clawmem_..., ...}}的JSON恭喜你服务已经正常运转了如果报错如500 Internal Error需要检查Cloudflare Worker的日志在Cloudflare仪表板的Workers部分查看。所有Secret是否都已正确设置。注册表数据库的网络连通性TiDB Cloud Serverless默认允许所有IP访问但最好在控制台确认一下。4. API使用详解与智能体集成实战服务跑起来了我们来看看怎么用它。API设计得很RESTful主要围绕/api/tokens和/api/memories两个核心资源。4.1 创建与管理记忆空间记忆空间由Token唯一标识。创建Token的同时系统就在后台为你分配了一个全新的TiDB Cloud Zero数据库。基础创建curl -X POST https://你的worker地址/api/tokens这是最简单的用法适用于大多数场景。服务器会用它自己的密钥加密存储数据库连接信息。高安全模式创建客户端加密curl -X POST https://你的worker地址/api/tokens \ -H X-Encryption-Key: your-super-secret-client-key-here请务必将your-super-secret-client-key-here替换为一个你自己生成并妥善保管的强密码。重要一旦使用此模式你必须记住这个客户端密钥因为后续所有使用此Token的请求都必须携带相同的X-Encryption-Key头否则服务器无法解密连接信息请求会失败。这个密钥不会存储在服务器端。创建成功后响应中claim_url字段至关重要。务必在30天内打开这个链接登录TiDB Cloud并完成认领将临时数据库转为永久免费的Starter实例否则数据会丢失。查询Token信息curl -H Authorization: Bearer clawmem_你的token \ https://你的worker地址/api/tokens/clawmem_你的token/info这个端点可以查看该记忆空间的基本信息、统计如记忆条数以及再次获取认领链接。4.2 记忆的存储、检索与管理这才是智能体交互的核心。假设我们有一个Tokenclawmem_a1b2c3d4。存储一条记忆curl -X POST https://你的worker地址/api/memories \ -H Authorization: Bearer clawmem_a1b2c3d4 \ -H Content-Type: application/json \ -d { content: 用户在当前对话中透露他计划下周去上海出差需要预订浦东机场附近的酒店。, source: openclaw, tags: [travel, schedule, user-preference], key: upcoming_business_trip_shanghai, metadata: { priority: high, extracted_date: 2023-10-27 } }content: 记忆的主要内容支持长文本。source: 标识是哪个智能体写入的便于后续过滤和溯源。tags: 标签数组是高效的过滤维度。设计良好的标签体系能让检索事半功倍。key: 可选为一个记忆设定一个唯一键名。如果你需要存储和更新类似“用户偏好”这种单例信息用key就非常方便可以通过key直接定位无需搜索。metadata: 可选一个JSON对象可以存放任何结构化的附加信息如置信度分数、原始消息ID等非常灵活。搜索记忆 这是智能体“回忆”的关键。API支持多条件组合搜索。# 1. 关键词全文搜索 (在content字段中搜索) curl https://你的worker地址/api/memories?q上海酒店 \ -H Authorization: Bearer clawmem_a1b2c3d4 # 2. 按标签过滤 curl https://你的worker地址/api/memories?tagstraveltagsschedule \ -H Authorization: Bearer clawmem_a1b2c3d4 # 3. 按来源过滤 curl https://你的worker地址/api/memories?sourceopenclaw \ -H Authorization: Bearer clawmem_a1b2c3d4 # 4. 按key精确查找 curl https://你的worker地址/api/memories?keyupcoming_business_trip_shanghai \ -H Authorization: Bearer clawmem_a1b2c3d4 # 5. 组合查询 分页 curl https://你的worker地址/api/memories?q出差tagstravelsourceopenclawlimit10offset0 \ -H Authorization: Bearer clawmem_a1b2c3d4搜索结果是按相关性或时间排序的列表非常直观。更新与删除# 更新一条记忆 (需要知道记忆的ID) curl -X PUT https://你的worker地址/api/memories/记忆ID \ -H Authorization: Bearer clawmem_a1b2c3d4 \ -H Content-Type: application/json \ -d {content: 更新后的内容..., tags: [updated]} # 删除一条记忆 curl -X DELETE https://你的worker地址/api/memories/记忆ID \ -H Authorization: Bearer clawmem_a1b2c3d4批量导入 如果你有历史数据需要迁移或者智能体一次性产生大量记忆可以使用批量接口最高支持200条一次。curl -X POST https://你的worker地址/api/memories/bulk \ -H Authorization: Bearer clawmem_a1b2c3d4 \ -H Content-Type: application/json \ -d { memories: [ {content: 记忆1, source: claw1, tags: [tag1]}, {content: 记忆2, source: claw2, tags: [tag2]} // ... 最多200条 ] }4.3 在智能体项目中集成以OpenClaw为例集成claw-memory主要是在智能体需要持久化或查询记忆时调用对应的REST API。你可以在智能体的工具Tools或技能Skills中增加一个MemoryManager类。一个简化的Python示例import requests from typing import List, Optional, Dict, Any class ClawMemoryClient: def __init__(self, base_url: str, token: str, client_encryption_key: Optional[str] None): self.base_url base_url.rstrip(/) self.token token self.headers { Authorization: fBearer {token}, Content-Type: application/json } if client_encryption_key: self.headers[X-Encryption-Key] client_encryption_key def store(self, content: str, source: str, tags: List[str] None, key: Optional[str] None, metadata: Optional[Dict] None) - bool: 存储一条记忆 data { content: content, source: source, tags: tags or [], } if key: data[key] key if metadata: data[metadata] metadata resp requests.post(f{self.base_url}/api/memories, jsondata, headersself.headers) return resp.status_code 200 def search(self, query: Optional[str] None, tags: List[str] None, source: Optional[str] None, key: Optional[str] None, limit: int 10) - List[Dict[str, Any]]: 搜索记忆 params {} if query: params[q] query if tags: params[tags] tags if source: params[source] source if key: params[key] key params[limit] limit resp requests.get(f{self.base_url}/api/memories, paramsparams, headersself.headers) if resp.status_code 200: return resp.json().get(data, []) return [] # 在OpenClaw的配置或初始化阶段 memory_client ClawMemoryClient( base_urlhttps://你的worker地址, tokenclawmem_a1b2c3d4 # client_encryption_key你的密钥 # 如果创建时用了客户端加密 ) # 当智能体需要记住某事时 memory_client.store( content用户说他不喜欢弹出式广告。, sourceopenclaw_dialogue, tags[user-preference, ui, advertisement] ) # 当智能体需要回忆时 related_memories memory_client.search(query广告, tags[user-preference]) for memory in related_memories: print(fRecall: {memory[content]} (from {memory[source]}))这样智能体就具备了跨会话、跨实例的长期记忆能力。5. 安全、性能与生产环境考量将这样一个服务用于生产环境除了功能我们更需要关注安全、可靠性和性能。5.1 安全加固建议客户端加密的密钥管理如果启用了客户端加密X-Encryption-Key的管理是重中之重。绝对不要硬编码在智能体代码或配置文件中。应该通过环境变量注入或者使用专门的密钥管理服务如云厂商的KMS。密钥丢失意味着对应的记忆空间将永久无法访问。Token的保密与轮转Token相当于数据库的访问凭证。应在智能体间安全地共享例如通过安全的配置下发渠道。考虑定期轮转Token的可行性目前API不支持直接轮转但可以创建一个新Token让智能体迁移到新空间再废弃旧的。Worker访问限制可以在Cloudflare Worker的触发器中设置路由规则或使用Cloudflare的防火墙WAF规则限制只有你的智能体后端IP或特定域名可以调用该Worker减少公开暴露的风险。注册表数据库访问控制确保TiDB Serverless注册表数据库的访问密码足够复杂并且仅允许从Cloudflare Worker的IP范围如果需要或你的管理IP访问。定期审计数据库操作日志。5.2 性能优化与监控数据库连接池Worker是无状态的每次请求都可能创建新的数据库连接。TiDB Cloud Serverless和Zero实例对连接数有限制。虽然项目本身可能做了基础连接管理但在高并发下需要注意。可以考虑在Worker内使用更高效的连接池库并设置合理的空闲超时。记忆内容的长度与索引content字段被定义为TEXT类型适合存储长文本。TiDB Cloud的全文搜索功能可以加速q参数的搜索。但对于tags和source这类等值查询确保数据库表上有合适的索引项目初始化脚本可能已创建部署后最好确认一下。响应缓存对于频繁读取且不常变化的记忆例如通过key查询的用户配置可以在Worker层添加简单的内存缓存如使用Cloudflare的Cache API但要注意缓存失效和内存使用。监控与告警Cloudflare Worker Metrics在Cloudflare仪表板监控Worker的请求量、错误率、CPU时间。TiDB Cloud Metrics在TiDB Cloud控制台监控注册表数据库和各个Zero/Starter实例的查询延迟、连接数、存储空间使用情况。设置存储空间接近上限的告警。业务日志在Worker代码中增加关键操作如创建Token、认领实例的日志输出方便问题追踪。5.3 扩展性与成本从Zero升级到Starter及更高版本认领后的Starter实例是免费的但有资源限制。如果智能体数量或数据量极大需要监控TiDB Cloud的控制台关注存储用量和请求单元RCU消耗。超出免费额度后需要升级到付费计划TiDB Cloud支持弹性扩缩容。多区域部署如果智能体用户遍布全球可以考虑在多个地理区域如北美、欧洲、亚洲分别部署一套claw-memoryWorker和对应的注册表数据库让智能体连接最近的端点降低延迟。这需要管理多套配置和Token体系。自定义扩展当前API是通用的。你可以根据智能体的特定需求在Worker上扩展新的API端点。例如增加一个/api/summarize端点自动对某个Tag下的记忆进行摘要总结或者增加一个/api/cleanup端点按规则清理过期记忆。6. 常见问题与故障排查实录在实际部署和测试中我遇到了一些典型问题这里汇总一下排查思路。6.1 部署阶段问题问题现象可能原因排查步骤与解决方案npm run db:init失败提示连接被拒绝或超时。1. TiDB Serverless集群未创建或状态不是“Available”。2. 连接信息主机、端口、用户名、密码错误。3. 本地网络或防火墙阻止访问TiDB Cloud的公共端点。1. 登录TiDB Cloud控制台确认集群状态。2. 仔细核对Connect对话框中的信息注意密码中的特殊字符。3. 尝试用mysql客户端或数据库管理工具如DBeaver直接连接验证网络和凭据。npm run deploy失败或部署后Worker返回5xx错误。1. Cloudflare Wrangler未登录或没有项目写入权限。2. 未设置或错误设置了必需的Secret (REGISTRY_*,ENCRYPTION_KEY)。3. Worker代码运行时无法连接到注册表数据库。1. 运行wrangler whoami确认登录状态。2. 运行npx wrangler secret list查看已设置的Secret确保没有遗漏。3. 查看Cloudflare Worker的实时日志通常会有更详细的数据库连接错误信息。创建Token时返回500错误日志显示“Failed to provision Zero instance”。1. TiDB Cloud API调用失败配额不足、区域资源售罄、临时故障。2. 用于调用TiDB Cloud API的凭据问题但此项目似乎未直接集成此API需确认架构。1. 稍后重试。2. 检查项目代码中关于TiDB Cloud Zero实例创建的部分确认其实现方式。可能需要检查相关的环境变量或配置。6.2 运行时API问题问题现象可能原因排查步骤与解决方案使用Token调用/api/memories时返回401 Unauthorized或403 Forbidden。1. Token拼写错误或已失效如对应的Zero实例已过期且未认领。2. 使用了客户端加密模式创建Token但后续请求未提供或提供了错误的X-Encryption-Key头。1. 确认Token字符串完全正确。调用/api/tokens/:token/info查看Token状态。2.务必确保如果创建Token时提供了X-Encryption-Key那么之后所有使用此Token的请求都必须携带完全相同的Key。搜索记忆时结果不符合预期或速度慢。1. 搜索条件过于宽泛或模糊。2. 数据库表缺少有效索引。3. 记忆数据量非常大。1. 尽量使用tags和source等精确字段进行过滤结合q关键词搜索。2. 连接到你的业务数据库通过认领后的TiDB Cloud控制台检查memories表上是否有idx_tags,idx_source,idx_key等索引。如果没有可以考虑在低峰期添加。3. 对结果进行分页limitoffset。存储记忆时返回“Payload too large”或类似错误。单条记忆的content字段超出了数据库列或API设置的大小限制。项目文档说明content字段支持最多约50KB。检查你写入的内容长度。如果确实需要存储更长的内容可以考虑压缩后再存储或者将大内容拆分成多条关联的记忆。认领链接(claim_url)点击后无效或提示“Already claimed”。1. 认领链接已过期可能有时效性。2. 该Zero实例已被其他TiDB Cloud账户认领。3. 你已经认领过该实例。1. 重新调用POST /api/tokens/:token/claim获取新的认领链接。2. 确保你用于点击链接的浏览器已登录正确的TiDB Cloud账户。3. 在TiDB Cloud控制台查看你的集群列表确认是否已存在该实例。6.3 数据迁移与备份虽然TiDB Cloud提供了高可用性但主动备份重要数据是好习惯。备份单个记忆空间的数据由于每个Token对应一个独立的TiDB实例你可以直接通过TiDB Cloud控制台对你认领后的Starter实例进行数据导出Dumpling或使用其备份功能。迁移记忆空间如果需要将记忆从一个Token迁移到另一个例如切换到客户端加密模式目前没有内置工具。你需要写一个脚本用旧Token读出所有记忆可能需要分页然后用新Token的API逐条或批量写入。注册表数据库备份这个数据库存储了所有Token的映射关系至关重要。务必定期为这个TiDB Serverless集群启用自动备份或手动导出表结构及数据。这个项目为AI智能体的记忆共享提供了一个非常优雅且安全的解决方案。它巧妙地将无服务器函数、云原生数据库和精心的安全设计结合在一起把复杂的多租户、资源隔离问题简化成了一个简单的API调用。在实际集成到智能体项目中时最需要花心思的是设计记忆的结构如何设置tags、key和metadata以及制定记忆的更新与淘汰策略避免存储空间无限增长。对于中小规模的智能体应用来说这套方案几乎是开箱即用、成本可控的优选。