TencentDB Agent Memory 的网关路由全景:v1 / v2 / v3 各管什么

2026-08-16

MemoryCore/ 这个模块的时候,最先让人卡住的不是某个算法,而是一个很土的问题:同一个网关上为什么同时挂着 /recall/v2/conversation/add/v3/meta/team/create 三种长相完全不同的路径?它们是三代接口的地层叠加,还是三类职责的横向切分?

这篇就沿着路由表把这件事摊开。先把前提说在前面。

这份路由图的取证边界

我们读的是 TencentCloud/TencentDB-Agent-Memory 仓库,快照 97f9465,核对日 2026-08-16。要特别注意:这个仓库的默认分支是 feat/server_team,不是 main 也不是 master,下面所有文件路径都是在这条分支上说的。MemoryCore/package.jsonversion2.0.0-beta.1,而仓库根 CHANGELOG.md 最新条目写的是 [2.0.1-beta.1] —— 两处不一致,我们只陈述这个差异,以实读的仓库状态为准。既然主模块还在 beta 阶段,下面这些路径、字段、默认值随版本变动是完全可能的,请以仓库最新内容为准。

还有一条更硬的:我们没有部署过这个项目、没有启动过 Gateway、没有发过一个 HTTP 请求。下文出现的端点、端口、超时,全部是从路由表定义和配置文件里读出来的字面值,不是运行结果。

对外只有一个 HTTP 口,没有 MCP

先排除一种常见猜测。我们在 MemoryCore/ 全目录内对 \bmcp\b 做大小写不敏感检索(.ts.json.md.yaml 全覆盖),命中 0 条 —— 在这个模块范围内找不到任何 MCP server 或 MCP 工具注册的实现与文档。对外的主要形态就是一个 HTTP Gateway。

README.md:29 的架构图里写的是 MemoryCore Gateway :8420README.md:44Listens on 127.0.0.1:8420 by default。实现侧,src/gateway/server.ts:13 的注释原文是「Built with Node.js native http module — no Express/Fastify dependency.」—— 没有 Web 框架,路由靠手写 switch,这也是为什么路由表读起来这么直白。

v1:七条扁平端点,一个 switch 就写完了

v1 的全部路由在 src/gateway/server.ts 里:GET /healthserver.ts:1046,另外六条集中在 1055-1069switch 里 —— POST /recallPOST /capturePOST /search/memoriesPOST /search/conversationsPOST /session/endPOST /seed,其余落到 1069 的 404。

有两处值得单独记:

一是 /health 放在鉴权门之前,源码注释写它无条件可达 —— 这一点和 Dockerfile:156-157HEALTHCHECK 对得上,那条健康检查打的正是 http://127.0.0.1:${TDAI_GATEWAY_PORT:-8420}/health

二是 v1 的鉴权函数 verifyAuthserver.ts:1116-1129)里有一句需要留神:server.apiKey 未配置时它直接 return "ok",注释写的是 auth disabled — default behaviour。这和 tdai-gateway.yaml:29 那行被注释掉的 server.apiKey 是一套口径,注文写「不填则所有 v2 接口默认开放(仅本机)」。

v1 这一组接口的形状是「一次会话交互对应一个动词」:捞回忆、抓取、搜、结束会话。hermes-plugin 对接的正是其中三条 —— 它的 README 里那张生命周期映射表(hermes-plugin/memory/memory_tencentdb/README.md:33-38)写得很清楚:prefetch(query)POST /recallsync_turn(user, assistant)POST /captureshutdown() / on_session_endPOST /session/end

v2 与 v3 的数据面:同一批十八条子路径,挂载规则差一点

到了 src/gateway/v2-router.ts,路由不再是一条条写死,而是一张表。V2_PREFIX = "/v2"v2-router.ts:99V3_PREFIX = "/v3":116。真正的数据面在 DATAPLANE_HANDLERSv2-router.ts:414-431),一共 18 个子路径,按四组分:

子路径
/conversation/add query search delete count
/atomic/update query search delete count
/scenario/ls read write rm count
/core/read write count

挂载规则在 v2-router.ts:436-441/count 结尾的只挂 /v3,其余同时挂 /v2/v3V3_ALLOWED_SUBPATHSv2-router.ts:153-172)列的是同一批 18 条。

也就是说,v2 与 v3 在数据面上不是「两代不同接口」,而是同一张处理表的两个入口,v3 多带了四个计数接口。真正的差别不在路径,在下一节的请求头。

元数据面在另一个文件里:/v3/meta 五十五条

数据面之外还有一整套实体管理接口,它们不在 v2-router.ts,而在 src/metadata/router/v3-meta-router.ts —— 前缀 V3_PREFIX = "/v3/meta"v3-meta-router.ts:47),routeTable 定义在 84-315 行,V3_ROUTES316 行导出。我们用脚本数出 55 条,按前缀分组是这样:

user/* 5 条(含 create-with-key)、user-key/* 5、team/* 5、team-member/* 4、agent/* 5(含 archive)、task/* 6(含 archive)、task-agent/* 3、participation-log/* 2、asset/* 7(含 list-accessibletouch-usage)、agent-fixed-asset/* 4(含 list-with-detailsummary-by-agents)、acl/* 4(grant revoke list check)、auth/verify 1、instance-quota/get 1、config/user/{get,set} 2。

这就是「数据面 / 元数据面」的分界线:记忆内容的读写走 v2-router.ts,人、团队、Agent、任务、资产、权限这些实体走 v3-meta-router.ts 落到磁盘上也是两套东西 —— 元数据库有自己的初始化脚本 scripts/db/sqlite-init.sql(222 行),文件头写的是「记忆内核 metadata 模块 — SQLite 初始化脚本(v3.2 · 按实例分库)/每个实例独立库文件;表内无 instance_id」,里面建 meta_usersmeta_teamsmeta_agentsmeta_tasksmeta_assetsmeta_asset_acl 等一共 12 个 CREATE TABLE。而记忆内容那套表在 src/core/store/sqlite.ts 里,17 个建表点,其中 l1_vecl0_vec 是 vec0 虚表,l1_ftsl0_fts 是 FTS5 虚表。

顺带一提,v2 里也曾经有过实体接口:v2-router.ts:451-466 有 16 条 /v2/{team,user,agent,task}/{create,get,update,delete},整体标了 @deprecated,注释(v2-router.ts:444-449)原文写「仅为兼容现网保留、行为不变」「计划在确认无外部调用方后整体删除」。它们还在,但按注释的说法不再演进。

v3 独占的几个功能面

除了数据面和元数据面,/v3 下还挂了几组按功能切的路由,各自在自己的 handler 文件里:

  • Skill 17 条src/gateway/skill-handlers.ts:1138-1157makeSkillRouteTable()/v3/skill/ 下的 create update patch delete get get-by-name list search versions files/write files/remove files/read export listing extract conversation/add conversation/force-archive
  • Knowledge 5 条src/gateway/knowledge-handlers.ts:149-153create get update delete list。注意 knowledge-handlers.ts:14 的注释原文写着 No binding endpoints — binding is TODO,绑定这块是标了 TODO 的。
  • Memory Prompt 7 条memory-prompt-handlers.ts:290-296)、Memory Generation Log 2 条memory-generation-log-handlers.ts:72-73)、Chat Memory 1 条 /v3/chat-memory/clearchat-memory-handlers.ts:472)。

另外两处不在上述任何一组里:/v2/pipeline/statusv2-router.ts:468),以及实例销毁 /v2/instance/destroyserver.ts:848)与 /v3/instance/destroyserver.ts:859)。offload 那三条也走 v2 前缀但在完全另一个文件 —— src/offload_server/router.ts 里判断前缀 /v2/offload/:35),三个 case 在 57/66/77 行:ingestquery-mmdcompact

方法约束是统一的(v2-router.ts:498-505):默认只接受 POST,只有 5 个 memory-prompt / memory-generation-log 的读接口允许 GET。看到一堆 POST /xxx/query 别觉得反常,这里就是这么定的。

v2 到 v3 真正的差别:请求头多了隔离三元组

前面说数据面 v2 与 v3 共用同一张表,那 v3 的意义在哪?在 collectV3Missingv2-router.ts:130-150)。

  • v2 侧的要求(parseV2Authv2-router.ts:350-360):Authorization: Bearer <key>x-tdai-service-id 两样。缺前者返 401「Missing or invalid Authorization header. Expected: Bearer {api_key}」,缺后者返 401「Missing x-tdai-service-id header」。
  • v3 侧在此之上强制隔离三元组 team_id / agent_id / user_id,可以从 body 里给,也可以走 x-tdai-team-id / x-tdai-agent-id / x-tdai-user-id 三个头;session_id 不强制(v2-router.ts:148 注释)。

把这两处并排放着看:/v3 数据面要填 team / agent / user 三元组,而这三类实体的创建、查询、归档接口正好落在 /v3/meta 那 55 条里。至于 /count 那四条为什么只挂 /v3,源码与注释里没有给出说明,我们不做推断。

CORS 那边是另一套:applyCorsHeadersserver.ts:1176-1180)在 allow.length === 0 时不发任何 CORS 头,注释称之为 strict default

三处对不上的地方,只记录不评价

按住这份路由图对文档,有几处口径不一致,照实记下来,不推断原因、也不据此评价什么:

其一v2-router.ts:520 的注释写「/v3 暴露 L0–L3 数据面 14 条(V3_ALLOWED_SUBPATHS)」,而 V3_ALLOWED_SUBPATHSv2-router.ts:153-172)实际列了 18 条(conversation 5 + atomic 5 + scenario 5 + core 3,我们逐行数过)。同一个文件 :444 注释里说的「16 条」废弃实体路由,与 :451-466 的 16 行是对得上的。

其二,两份 README 的 API 表都没有列出这些端点:POST /session/endPOST /seedserver.ts:1064:1066)、/v2/offload/{ingest,query-mmd,compact}/v2/pipeline/status/v2/v3instance/destroy/v3/chat-memory/clear。另外中英文 README 本身也不一致:README_CN.md:186-187 的表里有 /v3/memory-prompt/*/v3/memory-generation-log/list、/get 两行,README.md:174-184 的同一张表没有这两行(英文 259 行,中文 330 行)。要照着路由做对接,比起 README,直接读上面那几个 handler 文件的路由表更贴合仓库实况。

其三,和绑定地址有关。README.md:204 的表格原文是 TDAI_GATEWAY_API_KEY | Unset | HTTP Bearer authentication; required for non-loopback binding。代码侧我们找到的是:server.ts:739-746 在「非回环且未开鉴权」时打一条 logger.warn,文案是「Bind to 127.0.0.1, or set TDAI_GATEWAY_API_KEY, before continuing.」;而 verifyAuthserver.ts:1116-1118)在 apiKey 未设时直接 return "ok"我们没有在仓库里找到「未设 API Key 且绑非回环则拒绝启动」的实现。 同时 Dockerfile:146 默认把 TDAI_GATEWAY_HOST 设为 0.0.0.0。这三处并列摆着,各自的位置都在上面,怎么处置请自行判断。

这里必须说明一件事实层面的东西:这个网关承载的是团队的对话、文档与代码 —— SKILL-DIAGNOSTIC-EXPORT.md:57-63 的导出包隐私风险表里,memory-tdai/ 那一栏标的是「高」,说明原文是「包含用户对话原文」。所以监听地址和鉴权不是纯粹的工程细节。至于防火墙、密钥托管一类做法,那属于通用运维范畴,不是这个项目的官方文档内容,本文不给方案。

这份图怎么用

如果你要接这个网关,按上面的分层去找入口大致是这个顺序:会话级的抓取与召回看 v1 那七条;记忆内容的增删查看数据面那 18 条子路径,并确认自己走 v2 还是 v3;要建团队、Agent、任务、资产权限,去 /v3/meta 那 55 条;Skill、Knowledge、Memory Prompt 各有独立 handler 文件。请求头按 v2 / v3 分别准备,方法默认 POST

而所有条数、路径、默认值都请回到 feat/server_team 分支上那几个文件里再核一遍 —— 我们数出的是 2026-08-16 快照里的状态,这个模块还在 beta。

延伸阅读


本文依据 TencentDB Agent Memory 官方仓库(github.com/TencentCloud/TencentDB-Agent-Memoryfeat/server_team 分支上的 README、INSTALL、CHANGELOG、ROADMAP 与四个模块的源码整理, 核对日 2026-08-16,对应仓库快照 97f9465。该仓库的默认分支即为 feat/server_team。 本文内容为仓库源码与文档口径,我们没有部署、也没有运行过该项目的任何一个模块, 因此不涉及运行效果、检索质量与性能的任何描述。 该项目主模块处于 beta 阶段、其余模块版本号仍为 0.1.0,参数与接口随版本变动,请以仓库最新内容为准。 该项目会采集并存储团队的对话、文档与代码,属于敏感数据,是否使用请结合自身合规要求评估。 安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。

想系统学会用 AI?报名体系课或加入会员,照着学、照着用。