TencentDB Agent Memory 的网关路由全景:v1 / v2 / v3 各管什么
翻 MemoryCore/ 这个模块的时候,最先让人卡住的不是某个算法,而是一个很土的问题:同一个网关上为什么同时挂着 /recall、/v2/conversation/add、/v3/meta/team/create 三种长相完全不同的路径?它们是三代接口的地层叠加,还是三类职责的横向切分?
这篇就沿着路由表把这件事摊开。先把前提说在前面。
这份路由图的取证边界
我们读的是 TencentCloud/TencentDB-Agent-Memory 仓库,快照 97f9465,核对日 2026-08-16。要特别注意:这个仓库的默认分支是 feat/server_team,不是 main 也不是 master,下面所有文件路径都是在这条分支上说的。MemoryCore/package.json 里 version 是 2.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 :8420,README.md:44 写 Listens 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 /health 在 server.ts:1046,另外六条集中在 1055-1069 的 switch 里 —— POST /recall、POST /capture、POST /search/memories、POST /search/conversations、POST /session/end、POST /seed,其余落到 1069 的 404。
有两处值得单独记:
一是 /health 放在鉴权门之前,源码注释写它无条件可达 —— 这一点和 Dockerfile:156-157 的 HEALTHCHECK 对得上,那条健康检查打的正是 http://127.0.0.1:${TDAI_GATEWAY_PORT:-8420}/health。
二是 v1 的鉴权函数 verifyAuth(server.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 /recall,sync_turn(user, assistant) → POST /capture,shutdown() / on_session_end → POST /session/end。
v2 与 v3 的数据面:同一批十八条子路径,挂载规则差一点
到了 src/gateway/v2-router.ts,路由不再是一条条写死,而是一张表。V2_PREFIX = "/v2" 在 v2-router.ts:99,V3_PREFIX = "/v3" 在 :116。真正的数据面在 DATAPLANE_HANDLERS(v2-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 与 /v3。V3_ALLOWED_SUBPATHS(v2-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_ROUTES 在 316 行导出。我们用脚本数出 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-accessible、touch-usage)、agent-fixed-asset/* 4(含 list-with-detail、summary-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_users、meta_teams、meta_agents、meta_tasks、meta_assets、meta_asset_acl 等一共 12 个 CREATE TABLE。而记忆内容那套表在 src/core/store/sqlite.ts 里,17 个建表点,其中 l1_vec、l0_vec 是 vec0 虚表,l1_fts、l0_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-1157的makeSkillRouteTable():/v3/skill/下的createupdatepatchdeletegetget-by-namelistsearchversionsfiles/writefiles/removefiles/readexportlistingextractconversation/addconversation/force-archive。 - Knowledge 5 条,
src/gateway/knowledge-handlers.ts:149-153:creategetupdatedeletelist。注意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/clear(chat-memory-handlers.ts:472)。
另外两处不在上述任何一组里:/v2/pipeline/status(v2-router.ts:468),以及实例销毁 /v2/instance/destroy(server.ts:848)与 /v3/instance/destroy(server.ts:859)。offload 那三条也走 v2 前缀但在完全另一个文件 —— src/offload_server/router.ts 里判断前缀 /v2/offload/(:35),三个 case 在 57/66/77 行:ingest、query-mmd、compact。
方法约束是统一的(v2-router.ts:498-505):默认只接受 POST,只有 5 个 memory-prompt / memory-generation-log 的读接口允许 GET。看到一堆 POST /xxx/query 别觉得反常,这里就是这么定的。
v2 到 v3 真正的差别:请求头多了隔离三元组
前面说数据面 v2 与 v3 共用同一张表,那 v3 的意义在哪?在 collectV3Missing(v2-router.ts:130-150)。
- v2 侧的要求(
parseV2Auth,v2-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 那边是另一套:applyCorsHeaders(server.ts:1176-1180)在 allow.length === 0 时不发任何 CORS 头,注释称之为 strict default。
三处对不上的地方,只记录不评价
按住这份路由图对文档,有几处口径不一致,照实记下来,不推断原因、也不据此评价什么:
其一,v2-router.ts:520 的注释写「/v3 暴露 L0–L3 数据面 14 条(V3_ALLOWED_SUBPATHS)」,而 V3_ALLOWED_SUBPATHS(v2-router.ts:153-172)实际列了 18 条(conversation 5 + atomic 5 + scenario 5 + core 3,我们逐行数过)。同一个文件 :444 注释里说的「16 条」废弃实体路由,与 :451-466 的 16 行是对得上的。
其二,两份 README 的 API 表都没有列出这些端点:POST /session/end 与 POST /seed(server.ts:1064、:1066)、/v2/offload/{ingest,query-mmd,compact}、/v2/pipeline/status、/v2 与 /v3 的 instance/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.」;而 verifyAuth(server.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 是什么:团队级 Agent 记忆中枢怎么读
- 本专题共 40 篇,完整分组目录见专题页
- TencentDB Agent Memory 怎么接入:没有 MCP,只有 HTTP 网关与 CLI
- TencentDB Agent Memory 的两份 gateway 配置逐字段对照
本文依据 TencentDB Agent Memory 官方仓库(github.com/TencentCloud/TencentDB-Agent-Memory)
feat/server_team 分支上的 README、INSTALL、CHANGELOG、ROADMAP 与四个模块的源码整理,
核对日 2026-08-16,对应仓库快照 97f9465。该仓库的默认分支即为 feat/server_team。
本文内容为仓库源码与文档口径,我们没有部署、也没有运行过该项目的任何一个模块,
因此不涉及运行效果、检索质量与性能的任何描述。
该项目主模块处于 beta 阶段、其余模块版本号仍为 0.1.0,参数与接口随版本变动,请以仓库最新内容为准。
该项目会采集并存储团队的对话、文档与代码,属于敏感数据,是否使用请结合自身合规要求评估。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。