news 2026/9/12 12:07:49

Supermemory 怎么设计 containerTag 实现多租户记忆隔离

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Supermemory 怎么设计 containerTag 实现多租户记忆隔离

Supermemory 怎么设计 containerTag 实现多租户记忆隔离

【免费下载链接】supermemoryMemory and context engine + app that is extremely fast, scalable, and can be run fully locally. The Memory API for the AI era.项目地址: https://gitcode.com/GitHub_Trending/su/supermemory

当你的应用用同一个 Supermemory 组织服务多个用户、客户或租户时,必须保证租户 A 的记忆永远不会出现在租户 B 的检索结果里。Supermemory 用 containerTag 解决这件事:一个由你自己定义的字符串标识符,写记忆时附上它,之后搜索、列表、更新、删除时再传回去,数据就被限制在对应容器内。本文给出一条完整操作路径:设计命名规则、把数据写入正确的容器、验证隔离效果,并用 scoped API key 把边界锁死在数据层。前置条件是一个 Supermemory 账号和 API key(登录 Developer Platform,在 API Keys 页面点Create API Key,选择名称和过期时间后复制),以及supermemorySDK 或 cURL。

containerTag 的隔离机制

containerTag 是一个不透明标识符——Supermemory 不会解析它的含义,user_123project_mobileorg:acme:team:growth都是合法的。你的应用里有什么访问边界,tag 就该怎么取。

隔离的关键在于两点:

  • 自动建容器:第一次带某个 tag 写入时,Supermemory 自动为该 tag 创建 space(限定在你的组织内),无需提前配置;后续写入复用同一容器。
  • 独立的向量命名空间:每个 tag 被哈希进专属的 vector namespace,该 tag 的 embeddings、chunks 和 memory 条目与其他 tag 完全独立存储和检索——不存在一个需要过滤的共享索引,所以隔离是严格的(strict),而不是 best-effort。

同一个 tag 贯穿记忆整个生命周期,官方文档给出的各操作行为如下:

操作行为
Add把记忆写入该 tag 的容器(自动创建 space)
Search检索被限制在该 tag 的 namespace 内
List只返回属于该 tag 的记忆
Update / Delete作用于指定 tag 容器内的记忆

字段注意:当前 API 用单数containerTag字符串。复数containerTags数组字段已弃用,只在旧的/v3端点上为向后兼容保留,/v4API 只接受containerTag。唯一的例外是 documents 列表接口,按文档的字段差异表它使用数组形式:

// 搜索:单数字符串 await client.search({ q: "planning", containerTag: "project_q1" }); // 列表文档:数组形式 await client.documents.list({ containerTags: ["project_q1"] });

选择命名规范并遵守命名规则

先决定"一个隔离空间"在你的应用里对应什么层级,再定 tag 格式。文档给出的四种模式:

模式示例适用场景
按用户user_{userId}消费级应用,每用户独立记忆
按项目project_{projectId}工作区或项目级内容
按 Agentagent_{agentId}每个 AI agent 一份长期记忆
层级式org:{orgId}:user:{userId}多级多租户 SaaS

冒号被刻意允许,就是为了支持层级式 tag。文档同时给出一条重要建议:保持 tag确定性——直接由你已有的 ID(用户 ID、租户 ID)推导,这样查询时总能重建出正确的 tag,而不需要额外查找。另外,边界之内的分类、状态、日期等属性应该用 metadata 表达,不要为每个想过滤的属性新建 tag,那是 metadata 的职责(见 Organizing & Filtering)。

tag 在每次请求时都会校验,规则是:

  • 长度100 个字符以内
  • 只允许字母、数字、连字符(-)、下划线(_)、冒号(:
  • 匹配正则:^[a-zA-Z0-9_:-]+$
// ✅ Valid "user_123" "project-mobile-app" "org:acme:user:john" "tenant_42_workspace_7" // ❌ Invalid — 空格、斜杠和其他符号会被拒绝 "user 123" "project/mobile" "team@acme"

把记忆写入指定租户容器

选定规范后,写入时同时带上containerTag(隔离用)和可选的metadata(容器内细分查询用)。以多租户支持平台为例,每个客户一个 tag,工单状态、优先级走 metadata:

await client.add({ content: "Customer reports checkout button unresponsive on Safari", containerTag: "org_customer_442", metadata: { status: "open", priority: "high", channel: "chat" }, });

不用 SDK 时可以直接调 API($SUPERMEMORY_API_KEY替换为你的组织 key 或 scoped key):

curl -X POST "https://api.supermemory.ai/v3/documents" \ -H "Authorization: Bearer $SUPERMEMORY_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "Customer reports checkout button unresponsive on Safari", "containerTag": "org_customer_442", "metadata": {"status": "open", "priority": "high", "channel": "chat"} }'

请求成功后的响应(文档示例):

{ "id": "abc123", "status": "queued" }

处理是异步的,用返回的id跟踪状态:

const doc = await client.documents.get("abc123"); console.log(doc.status); // "queued" | "processing" | "done"

状态变为done即表示该文档已分块、嵌入并索引进该容器。注意文档中的一个警告:如果发生不可恢复的处理错误,文档会在 2 分钟后被自动删除。

验证隔离:检索只返回本租户数据

隔离的验证方式是文档明确给出的行为:一次搜索只限定在一个 container tag 内,containerTag: "user_123"会把结果限制在该容器的记忆中;一个 tag 里的记忆永远不会被限定在另一个 tag 的搜索返回。检索时可以叠加 metadata filters 缩小范围,filter 结构必须包在AND/OR数组里:

const results = await client.search({ q: "checkout issue", containerTag: "org_customer_442", searchMode: "documents", filters: { AND: [ { key: "status", value: "open" }, { key: "priority", value: "high" }, ], }, });

判断标准:对租户 A 的 tag 检索,只应返回写入 A 容器的记忆;用租户 B 的 tag 做同样的查询,拿不到 A 的任何内容。metadata filter 永远不跨越 containerTag 边界——你无法用 filter 去"看"另一个租户的容器。

用 scoped API key 在数据层锁定边界

组织层面还有两种机制把 containerTag 变成授权边界而不只是组织手段:API key 可以被限制到特定的 tag 集合(每个 tag 分别授予读/写权限),组织成员也可以被授权只访问某些 tag。受限请求的校验行为:

  • 请求超出允许集合的 tag → 返回403 Forbidden(而不是静默过滤)
  • 对只读 tag 执行写操作(add/update/delete)→403 Forbidden
  • 受限调用方未提供 tag 时 → 请求自动限定在其允许的 tag 内

这意味着你可以签发一把在数据层就物理上无法读写其他租户数据的 key,不依赖你的应用代码。创建 scoped key:

curl https://api.supermemory.ai/v3/auth/scoped-key \ --request POST \ --header 'Content-Type: application/json' \ --header 'Authorization: Bearer $SUPERMEMORY_API_KEY' \ -d '{ "containerTag": "my-project", "name": "my-key-name", "expiresInDays": 30 }'

参数说明:

参数必填默认值说明
containerTag限定该 key 可访问的容器
namescoped_{containerTag}key 的显示名
expiresInDays有效期,1–365 天
rateLimitMax500每窗口最大请求数(1–10,000)
rateLimitTimeWindow60000窗口毫秒数(1–3,600,000)

创建响应(文档示例):

{ "key": "sm_orgId_...", "id": "key-id", "name": "scoped_my-project", "containerTag": "my-project", "expiresAt": "2026-03-08T00:00:00.000Z", "allowedEndpoints": ["/v3/documents", "/v3/memories", "/v4/memories", "/v3/search", "/v4/search", "/v4/profile"] }

返回的 key 用法与普通 key 完全相同,只是出了它的容器范围就不生效。两个边界要知道:scoped key 只能访问上面列出的文档/记忆/搜索/profile 端点,不能读账单、管理组织设置或再签发 key;回收时用创建响应里的idDELETE https://api.supermemory.ai/v3/auth/scoped-key/KEY_ID,之后该 key 的请求返回401,但记忆和 container tag 本身不会被删除。

容器级配置与生命周期管理

每个 tag 可以带独立于其他 tag 的配置:

  • name:容器的显示名
  • entityContext:处理该容器内文档时应用的自定义上下文提示,用于按租户/项目引导抽取与摘要(按 add API 文档,最长 1500 字符)
await client.containerTags.update("project_research", { entityContext: "This project contains research papers about machine learning.", });

容器还有完整的管理端点({containerTag}替换为实际 tag):

端点用途
GET /v3/container-tags/{containerTag}读取 tag 配置
PATCH /v3/container-tags/{containerTag}更新 tag 配置
DELETE /v3/container-tags/{containerTag}删除容器及其数据
POST /v3/container-tags/merge把一个 tag 合并进另一个
GET /v3/container-tags/merge/{mergeId}轮询合并状态

两个破坏性操作必须在执行前明确其影响:DELETE /v3/container-tags/{containerTag}删除该容器及其全部数据client.documents.deleteBulk({ containerTags: ["user_123"] })按 tag 批量删除内容,删除是永久性的、不可恢复。只在确认要清退某个租户数据时使用。

常见约束与错误判断

  • 一次搜索只能限定一个 container tag。需要跨容器检索时(例如公司级共享容器 + 员工个人容器),由你的应用在每次请求中分别查询、再在客户端合并结果——containerTag 边界是 per-request 而不是 per-user 的。
  • 错误码(来自 add API 文档的错误处理表):400缺字段或参数非法;401key 无效或缺失;403权限不足(包括上面两类 tag 越权);429触发限流或配额超限;500处理失败。
  • 一处文档差异:authentication.mdx 中 scoped key 的containerTag参数说明允许"字母数字、连字符、下划线、冒号、",比 Container Tags 概念页的校验规则(^[a-zA-Z0-9_:-]+$,不含点)更宽。保守做法是按概念页的严格规则命名 tag。

完成上述步骤后,你的验证路径是:同一查询分别打到两个租户的 tag,各自只返回自己的数据;换一把 scoped key 去请求其范围外的 tag,收到403 Forbidden。隔离与授权边界都由数据层强制执行。深入阅读可参考 Multi-tenancy Overview、Multi-tenancy Examples(个人 agent、公司 agent、邮件助手、支持平台四种形态)和 Container Tags API。

【免费下载链接】supermemoryMemory and context engine + app that is extremely fast, scalable, and can be run fully locally. The Memory API for the AI era.项目地址: https://gitcode.com/GitHub_Trending/su/supermemory

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 12:07:47

C#视觉缺陷检测框架在新能源电池制造中的应用

1. 项目背景与核心需求在新能源电池制造领域,视觉缺陷检测系统已成为质量控制的关键环节。传统检测方法面临三大痛点:检测精度不足导致漏检、多工位协同效率低下、产线调试影响正常生产。我们开发的这套C#视觉缺陷检测框架,正是为了解决这些行…

作者头像 李华
网站建设 2026/9/12 12:06:55

Consolidated Review: PR {number}

Consolidated Review: PR #{number} 【免费下载链接】Archon The first open-source harness builder for AI coding. Make AI coding deterministic and repeatable. 项目地址: https://gitcode.com/GitHub_Trending/archon3/Archon Date: {ISO timestamp} Agents: cod…

作者头像 李华
网站建设 2026/9/12 12:06:37

AI写作助手如何提升创作效率与质量

1. 项目概述:当创意遇上AI写作助手"好写作AI"是一款面向文字工作者的智能创作辅助工具,专门解决写作过程中的创意枯竭问题。它通过自然语言处理技术模拟头脑风暴过程,能在作者卡壳时提供情节发展建议、修辞优化方案甚至完整段落生成…

作者头像 李华
网站建设 2026/9/12 12:06:11

PostgreSQL时间函数全解析:从类型、计算到性能优化实战

做后端开发这几年,我发现自己跟 PostgreSQL 打交道最多的,除了增删改查,就是跟时间相关的各种函数。不管是出报表、做统计分析、算用户活跃度,还是处理日志表、判断订阅到期时间,几乎每个业务场景都绕不开时间处理。Po…

作者头像 李华
网站建设 2026/9/12 12:05:31

论文降重工具评测与学术规范实践指南

1. 论文降重工具的核心需求解析对于硕博研究生而言,论文降重不仅是技术问题,更是学术规范问题。查重率过高往往源于三个典型场景:文献综述部分的表述雷同、研究方法章节的公式化描述,以及讨论部分与已有研究的相似性。真正有效的降…

作者头像 李华
网站建设 2026/9/12 12:03:26

基于单目视觉深度推理的敌方阵地三维全息态势瞬时重构 技术方案

1 方案概述1.1 建设背景现代攻防对抗作战呈现阵地动态伪装、工事快速构设、目标隐蔽机动、战场态势秒级迭代的典型特征,敌方阵地依托地形遮蔽、伪装网覆盖、假目标布设、地下工事嵌套等手段,大幅提升战场隐蔽性,导致传统侦察手段存在看不清、…

作者头像 李华