OpenClaw 多用户模式与 USER.md 用户模型:共用一个 agent 时谁能看到谁的会话
两个人共用一个 OpenClaw agent,最先撞上的往往不是技术问题,而是”这条会话是谁开的""他现在是不是也在看这个会话""我这半截活能不能先别出现在同事的侧边栏里”。再往后一点,是另一类问题:我告诉过它一次”实现过程中别写长篇解释”,下次开新会话它又忘了,这种稳定偏好该往哪儿放。
OpenClaw 把这两件事分成了两份文档:多用户模式(multi-user)管的是会话归属与在场感知,用户模型(USER.md)管的是跨会话的稳定偏好。它们看起来都像”多人协作”,但解决的问题完全不同,混着理解会踩坑——尤其是多用户模式,官方文档在开篇第二段就写了一句劝退式的警告。
先把那句警告摆在最前面,因为它决定了后面所有功能该怎么用。
多用户模式不是隔离机制,官方把这一条写在最前面
官方原文的意思很直白:任何能操作某个 agent 的人,都能让这个 agent 做它能做的任何事。会话归属、侧边栏里的可见性、在场指示器,这些是易用性功能,不是安全边界。
所以文档给出的判断标准也很硬:如果这些人之间不允许互相访问对方的会话、工具、凭据和文件,那就给他们各自独立的 agent,或者干脆用独立的网关 / 宿主机作为信任边界。不要指望靠”归属头像”和”人物筛选器”来做隔离。
这一条值得展开一下,因为它经常被误读。共享网关意味着共享一个信任域——会话、工具、凭据、文件都在这个域里。多用户模式让你看得清是谁在干活,但没有让你拦得住谁去碰什么。真正约束”能做什么动作”的是操作者作用域(operator scopes),那属于另一套机制,和沙箱、工具策略、提权的边界一起理解会更清楚,可以参考沙箱、工具策略与提权的边界。而如果你的诉求本来就是”几个人各干各的、互不可见”,那正确答案是拆 agent,见多 Agent 与专家分线。
会话归属:createdActor 写一次就不再改
新会话在创建时会记录一个 createdActor 字段,写一次就不再变更(write-once),前提是创建路径能够证明是谁触发的:
- 已认证的人使用其持久的 Gateway 档案 id;
- 发起请求的 agent 和系统路径,也写入同一个 actor 字段;
- 无法证明触发者的创建路径,会话就保持”无归属”状态。
有一个设计细节值得留意:OpenClaw 不会把显示名字存进会话条目。人的显示名是在返回会话列表时,从当前的 Gateway 档案里现查的。这意味着某人改了档案名之后,归属 UI 会直接跟着变,而不需要回头去重写历史会话记录。
对运维来说,这条的实际含义是:会话历史里存的是稳定 id,不是可能过期的名字快照;改名不会造成”同一个人在不同时期显示成两个人”。想进一步了解会话本身的生命周期,可以看会话模型:主会话、附着与状态。
界面上区分”归属”和”在场”的三个信号
Web 应用把”这个会话是谁的”和”现在谁在看”做成了视觉上互不混淆的两类元素。文档写明的语义如下:
| 元素 | 表示什么 | 时效 |
|---|---|---|
| 实心(solid)归属头像 | 这个会话的创建者 | 会话的整个生命周期内固定不变 |
| 带圆环或半透明的在场头像 | 当前已连接 / 正在观看的人 | 随连接状态实时变化 |
| 侧边栏的人物筛选器 | 只看某个身份创建的会话 | 与既有自定义分组并存,不冲突 |
还有一条容易被忽略的行为:当已加载的会话列表里出现的不同创建者少于两个时,OpenClaw 会把所有归属和人物筛选相关的界面元素整体隐藏。也就是说,单人使用的网关看上去和没有多用户模式时完全一样,不会平白多出一堆用不上的头像和筛选入口。
这个设计对判断故障很有用:如果你确信有两个人在用,却看不到归属 UI,那说明系统识别到的不同创建者仍然只有一个——很可能是有人的会话走的是无法证明触发者的创建路径,落成了”无归属”,或者两个人其实共用了同一个 Gateway 档案。
按身份走的便利状态:偏好和最近使用
当一条连接具备持久的 Gateway 档案时,两类”便利状态”会跟着人走,而不是跟着浏览器走:
- 新建会话的偏好设置:跟随这个人跨浏览器保持,但偏好本身仍然是按 agent 分别保存的;
- 选择器的最近使用(recents):只从这个人自己创建过的会话里推导。
反过来,如果一条连接没有持久身份,那么偏好就退回浏览器本地存储,最近使用则从当前加载的会话列表整体推导——也就是说,它会掺进别人的会话。
文档紧接着又强调了一遍同样的话:这套状态是为了连续性,不是授权或隔离边界。操作者作用域仍然管着动作,共享的 Gateway 仍然是一个信任域。同一句警告在一页文档里出现两次,通常说明官方在真实场景里被误用过。
草稿:把半成品挡在同事的侧边栏之外
如果一段工作还没成形,可以以草稿(draft)方式开会话,在你主动发布之前,它不会出现在队友的侧边栏里。
两个限制要记清楚:
- 管理员始终能看到草稿,包括别人的草稿,只是会带一个淡化的”幽灵”标记;
- 官方明确写了,这仍然是协作功能,不是安全边界。
所以草稿的正确用法是”减少噪音”——避免半截思路刷屏、避免同事误以为某个任务已经在推进;而不是”藏东西”。
轮次归属是尽力而为,不保证逐人可分
多人同时对着一个会话说话时,一个自然的期待是:转录里能看出哪句话是谁说的。官方对此的表述是尽力而为(best-effort)。
原因写得很具体:插话(steering)会把输入合并进正在进行的轮次,因此转录并不总能把每个人的贡献表示成独立的一轮。
这条要提前跟团队讲清楚。如果你打算把会话转录当成”谁提出了什么”的责任记录,那它在多人插话的场景下会失真——这不是 bug,是机制使然。
USER.md:把稳定偏好写成指令,而不是观察记录
换到另一半话题。USER.md 是 agent 工作区里可选的用户模型文件,存放稳定偏好、沟通风格、人际关系、以及当前项目背景,形式是能指导后续会话的指令。
加载机制上有三点事实:
- OpenClaw 在会话启动时把
USER.md与MEMORY.md并列加载; - 它有独立的、较小的 bootstrap 预算;
- 在长会话里,对该文件的编辑会在后续轮次被读取到;文件不存在时,启动流程继续,不报错。
写法上,每条目是一行元数据加一条祈使式指令:
<!-- observed: 2026-07-27 | status: active -->
- Prefer concise progress updates during implementation work.
官方给出的规则是固定的五条:
| 规则 | 具体要求 |
|---|---|
| 用祈使句开头 | Always / Never / Prefer 这类词开头 |
| 记录观察日期 | 即 observed: 后面那个日期 |
| 状态只有两个取值 | 只用 active 或 superseded |
| 一条指令一个行为 | 不要把多个行为塞进一条 |
| 只存能改善协助质量的内容 | 别把它写成个人档案 |
文档为”为什么要写成指令”给了一个依据:PrefEval 的研究发现,对话越长,模型遵循偏好的能力下降越明显,即便配了检索和提示也一样(官方引用的编号是 arXiv:2502.09597)。把稳定偏好复述成一条指令,等于在 agent 真正用到它的位置上,把期望行为写明白。
偏好变了要”就地取代”,不要追加
这是 USER.md 最容易写错的地方。官方要求:偏好发生变化时,更新它原有的那一节,不要在文件别处再追加一条新的 active 指令。
修改前:
<!-- observed: 2026-05-10 | status: active -->
- Prefer detailed explanations for every code change.
修改后:
<!-- observed: 2026-05-10 | status: superseded -->
- Prefer detailed explanations for every code change.
<!-- observed: 2026-07-27 | status: active -->
- Prefer concise implementation summaries unless more detail is requested.
注意旧条目没有被删掉,而是标成 superseded 并紧挨着新条目放。这样”当前生效的是哪一条”没有歧义。
文档同样给了依据:HorizonBench 的报告指出,系统经常在用户已经改变偏好之后,仍然选中最初表述的那一条(官方引用的编号是 arXiv:2604.17283)。只追加、不标记取代的写法,等于亲手重建这个失败模式。
一件事该写进哪个文件
USER.md 和 MEMORY.md 的分工是新手最常混淆的。官方文档直接给了一张对照表,照抄如下:
| 信息类型 | 存到哪里 |
|---|---|
| 稳定的偏好或沟通风格 | USER.md |
| 会改变”该如何协助此人”的人际关系或当前项目事实 | USER.md |
| 持久的非个人事实、决策或经验教训 | MEMORY.md |
| 详细观察或运行中的上下文 | memory/YYYY-MM-DD.md(日期文件) |
| 由事件触发的未来动作 | 常驻意图(standing intents) |
| 精确时点或周期性动作 | 定时任务(scheduled task) |
一个可操作的判断办法:先问”这条信息是关于这个人的,还是关于这件事的”。关于人的(偏好、风格、关系、在做什么项目)进 USER.md;关于事的(结论、教训、决策)进 MEMORY.md;只是过程记录的进日期文件。至于整套记忆分层是怎么组织的,见记忆架构:内置、搜索与外接。
为什么必须让 USER.md 保持紧凑
前面提到 USER.md 有”刻意更小”的 bootstrap 预算——这不是随口一提的实现细节,而是直接影响你能往里写多少东西。
文档给的清理办法有两条:
- 删掉过时的 superseded 条目。取代记录的作用是让”当前生效哪条”不含糊,一旦新指令稳定下来、不再有歧义,旧的就该清掉,而不是无限累积;
- 把不影响行为的项目细节挪走,移到日常记忆或
MEMORY.md里。
判断标准就是”是否改变 agent 的行为”。“这个项目用 TypeScript”如果不改变它该怎么回你,那它属于 MEMORY.md,不属于 USER.md。
什么时候不适用,以及哪些问题官方没解决
把上面的事实合起来,可以划出这套机制的适用边界:
不适用的场景:
- 需要真正隔离的团队。只要必须做到”A 不能读 B 的会话、工具、凭据、文件”,多用户模式就是错误的工具,官方给的答案是拆成独立 agent 或独立网关 / 宿主机。
- 需要精确责任追溯的场景。轮次归属是尽力而为,插话会把多人输入合并进同一轮,转录不能当作逐人可分的记录来用。
- 需要”对管理员也保密”的草稿。管理员始终能看到别人的草稿,只是带淡化标记。
官方文档没有说明的部分:
- 支持多少人同时在场、会话列表加载多少条才触发归属 UI 的显示阈值(只写了”少于两个不同创建者时隐藏”,没给列表规模),官方文档未说明;
USER.md的 bootstrap 预算具体是多少 token 或多少字节,只写了”比一般工作区文件更小”,没给数值;- 无归属会话事后能否补上归属,文档只说”创建时无法证明触发者的会话保持未归属”,没有提供补录路径。
如果你现在正要给团队上共享网关,最实际的动作顺序是:先判断有没有硬隔离需求——有就直接拆 agent,别在共享网关上做文章;没有,再把多用户模式当成”看得清谁在干什么”的协作层来用,同时给每个人的 agent 工作区建一份克制的 USER.md,从三五条指令起步,变了就就地取代。
延伸阅读
- 从头读起:OpenClaw 架构总览:网关、Agent、渠道、节点、插件五层各管什么,出问题该往哪查
- 本专题共 40 篇,完整分组目录见专题页
- OpenClaw 模型供应商怎么接、挂了怎么自动转移:从 provider/model 到 fallback 链
- OpenClaw 的队列、插话(steering)与重试:消息挤在一起时它到底怎么排
本文依据 OpenClaw 官方仓库(github.com/openclaw/openclaw)docs/ 下的官方文档整理,核对日 2026-08-17。
我们没有安装或运行过 OpenClaw,因此不涉及界面外观、操作手感与实测耗时的任何描述;
文中的默认值、命令与配置项均为文档口径,不构成对实际运行结果的保证。
该项目迭代很快,请以仓库最新内容为准。接入即时通讯平台前,请自行确认所在平台的规则与合规要求。