作用域与命名空间
作用域不是记忆对象上的附属标签,而是整个系统的第一隔离机制。只要 Scope 设计不清楚,后续的读取策略、覆盖优先级和权限边界都会变得含糊。
Scope 层级
羽忆采用由粗到细的层级式 Scope:
global
-> tenant
-> team
-> user
-> project
-> agent
-> session
第一阶段真正主打的是 user、project、agent、session 这几层;tenant 和 team 主要是对象模型上的预留,为后续协作和商业化场景保留扩展空间。
各层级适合存什么
| 层级 | 典型内容 |
|---|---|
user | 个人偏好、长期习惯、通用约束 |
project | 项目约定、技术决策、项目目标 |
agent | 某个宿主下的特定使用偏好 |
session | 当前会话的临时决定或阶段上下文 |
系统之所以强调“优先写入最小且最精确的 Scope”,是为了防止过宽的记忆污染后续召回。例如某个只属于单项目的约定,如果被写成 user 级,就会在其他项目里产生误导。
Namespace 的存储表达
在存储层里,Scope 最终会被展开成命名空间字段组合,例如:
{
"tenant_id": "t_default",
"user_id": "u_001",
"team_id": "team_dev",
"project_id": "p_demo",
"agent_id": "antigravity",
"session_id": "s_456"
}
这里最重要的约束是:Scope 的解析和权限判断必须由服务端负责。Adapter 只负责透传身份和上下文,不负责做最终的作用域仲裁,否则不同接入层很快就会出现行为漂移。
默认读取策略
对任务召回来说,默认范围通常是:
user + current_project + recent_session
这样设计是因为:
user层承载长期个人偏好project层承载当前项目最关键的约定与决策session层承载最近一次工作连续性的材料
如果默认把更宽范围都打开,召回结果很快会被噪声淹没。
写入推断规则
当调用方没有显式给出完整 Scope 时,服务端通常按以下顺序推断:
- 请求里包含
project_id,优先写入project - 内容明显属于长期个人偏好,写入
user - 内容明显是特定 Agent 行为偏好,写入
agent - 无法可靠判断时,先落到
user,并提示调用方确认
这个推断顺序不是为了偷懒,而是为了避免把模糊信息直接放到过宽或过深的层级里。
同一语义跨 Scope 的优先级
当不同 Scope 中出现语义相似或 semantic_key 相同的内容时,默认优先级为:
session > project > agent > user > team > tenant > global
原则非常简单:越贴近当前上下文的 Scope,越优先。
具体仲裁时还要叠加以下规则:
active永远优先于archived和invalid- 同一 Scope 内优先
version更高的内容 version相同时再比较importance- 再相同时才比较最近更新时间
Scope 与权限的关系
Scope 同时也是权限边界。第一阶段至少要保证:
- 用户默认只能读取自己的
user级内容 project级内容要经过项目归属校验- 不允许跨用户、跨租户直接读取
global级内容只读范围可以更广,但写权限必须极少
如果 Scope 只被当成检索过滤条件,而没有真正参与权限判断,系统在安全上就是不完整的。