
同一个 Agent,换个人指挥,权限也会跟着换吗?
一个数字员工先替甲处理代码,随后接受了乙的新指令。聊天没有断,任务没有换,执行它的仍是同一个 Agent。
接下来要向代码仓库提交内容时,它应该使用谁的权限?
这是一个说明问题的情境,不是我们发现的真实账号事故。它看起来像“换一个登录用户”,实际上却牵涉另一条时间线:甲的动作可能已经开始,乙的指令刚被接受,队列里还可能留着甲先前提交的工作。
如果一律跟随最后说话的人,排队中的旧指令可能被错误换主;如果始终沿用 Agent 启动时的凭据,新指令又可能继续借用前一个人的访问权。
会话可以连续,动作的责任与权限却不能因此含糊地连续下去。
1. Paperclip 改的不是聊天身份,而是动作开始时的身份
Paperclip 是一个用来组织和管理 AI Agent 工作的开源应用。它面对的具体问题是:多人可以向同一个 Agent、同一项任务发出指令,任务负责人不一定就是当前动作的指令责任人。
2026 年 9 月 7 日合并的变更,把任务归属与执行身份分开保存,并在受管理的 GitHub 操作开始时选择相应凭据。已经开始的动作保留当时确定的身份;没有新指令的重试,也不能仅因后来有人说话就自动换人。作者报告了两个用户、两个 GitHub 账号的切换验证;我们没有复跑这套账号实验。Paperclip #13005
这项变更有明确边界:它处理受管理操作的凭据选择,不承诺隔离同一执行主体内蓄意复制凭据的任意代码。变更中的风险说明
对我们而言,值得吸收的首先不是它用了多少组件,而是它把一个容易混在一起的问题拆开了:
| 要回答的问题 | 所需的身份或证据 |
|---|---|
| 谁在执行这项工作? | Agent 的执行身份 |
| 这次动作来自哪条指令? | 已接受指令的来源引用 |
| 这条指令由谁负责? | 经过认证及规则确认的责任人 |
| 这次动作实际能用什么访问权? | 在动作边界核验的凭据与授权 |
四项可以有关联,但不能仅凭名字相近就互相代替。比如,“开发角色”说明职责,不说明是哪位同事发出了指令;“这条消息来自甲”也不自动证明甲有权要求执行其中的动作。
2. 回到自己的系统:我们真的有同一个问题吗?
CodeFlowMu 是我们正在开发的一个本地运行、多 Agent 协作系统。它以 FCoP 的任务、报告与审核记录组织工作,运行时负责会话和技术执行,不替管理角色作业务裁决。
看到外部项目解决共享身份问题,最省事的反应是宣布:“我们也需要同样的功能。”但这跳过了关键前提——我们自己的数据究竟证明了什么?
我们先检查了选定的本地记录。采集发生在 9 月 8 日,记录本身来自 9 月 5 日;它们不是当天新发生的事故。
| 选定数据 | 实际粒度 | 它能告诉我们什么 |
|---|---|---|
| 操作审批 | 1 条审批记录 | 决定角色为 ADMIN;不能据此计算真人身份覆盖率 |
| 任务命令回执 | 10 行,对应 5 个命令幂等键 | 每个键有处理中、已完成两类事件;不是 10 次独立任务 |
| 技能调用 | 25 条、25 个调用编号 | 9 条具有非空会话编号;其余需区分合法无会话操作,不能直接判错 |
这批选定记录没有解析坏行。检查的几个显式真人身份、指令责任人与凭据授权字段也没有出现,但这只说明该批记录的字段情况,不能证明其他模块没有等价信息。
因此,历史数据不足以支持“发生过多人凭据串用”。它给出的真正提醒是:现有记录主要描述操作、命令、角色和调用,我们还不能把它们直接读成真人责任链。
下一步要查的不是“多加一个人名字段”,而是当前请求究竟绑定了谁。
3. 已有保护必须先承认:换 Agent,不等于旧批准继续有效
我们直接调用了当前源码中的操作审批服务,保存真实格式的批准记录。执行前核验通过后,服务会调用负责执行的函数,也就是“执行回调”。实验把这个函数替换为只计数、不做真实操作的模拟函数,没有连接代码仓库。
“请求摘要”可以理解为一份操作身份校验值:如果受保护的请求内容改变,旧批准不应再被当作同一份请求使用。
| 对照 | 观察 | 正确解释 |
|---|---|---|
| 原请求再次核验并执行 | 回调发生 1 次 | 基本允许路径成立 |
| 只把请求主体从一个 Agent 改为另一个 | 摘要改变,返回 APPROVAL_STALE,回调 0 次 | 旧批准不能直接给另一个请求主体使用 |
| 只改变会话编号 | 摘要不变,回调发生 1 次 | 该摘要没有把会话编号作为身份差异;不代表完整接管流程已经获准 |
| 任务命令用同一幂等键,但改变提交主体 | 返回 idempotency_key_conflict,不再调用 | 命令层也没有忽略主体差异 |
第二轮又调用了真实的操作策略构造器,而不是由研究脚本自己拼请求。构造出来的 subject.actor,即请求主体字段,来自 agentId;修改 Agent 后,实际构造出的请求摘要也改变了。
保护确实存在,只是它回答的是“哪个 Agent 提交了这个操作”,不是“哪个经过认证的真人,应当为该操作负责”。这两个问题需要相连,却不是同一个字段天然就能回答的。
4. 真正复现的差异,比“身份系统不完善”具体得多
要判断这次动作该使用谁的权限,至少要先知道它来自哪条指令。因此,我们先检查一个更基础的问题:原始指令的引用,能不能一路跟到执行会话? 这是责任追溯链的一部分,还不是真人授权的验证。
我们沿聊天续办路径检查,发现消息编号已经进入命令,却在传给会话时出现了位置差异:放在外层能够保存,放进续办信息里,却没有进入对应会话字段。
具体来说,续办命令保留了聊天消息引用,并把触发本次工作的消息编号 trigger_chat_id 放进续办上下文。
调度器把这份信息作为嵌套的“续办上下文”传给会话管理器;会话管理器保存触发消息字段时,却只读取上下文的顶层。
下面是经过简化的字段位置示意,不是另一份实验记录:
顶层传入:context.trigger_chat_id
→ 会话记录保存 runtime_trigger_chat_id
续办传入:context.continuation.trigger_chat_id
→ 对应会话字段没有保存我们把同一来源字段分别放在这两个位置,调用真实会话管理器,用内存模拟的执行适配器代替真实模型。结果如下:
| 传入方式 | 触发消息编号写入会话记录? | 同时传入的逻辑执行编号写入? |
|---|---|---|
| 顶层上下文 | 是 | 是 |
| 嵌套续办上下文 | 否 | 是 |
图 1:J1/J2 字段投影对照。图中的“未保存”仅指对应会话字段,不表示聊天或命令中的来源证据全部丢失。来源:正式观测与证据说明。点击图片可查看原图。
不是整个会话记录都没保存:同一次传入的逻辑执行编号正常落盘,缺的是触发消息编号这一项。源码也与结果一致——逻辑执行编号会同时查找顶层与续办层,触发消息编号则只查找顶层。
另一个经过真实调度器启动的隔离场景,同样没有在会话记录中留下对应触发消息字段。四组身份探针在两轮运行中结果一致。
这就是本轮能明确指出的缺口:来源信息已经进入命令,但没有沿指定的会话字段完整投影下去。
它与 Paperclip 的问题有关,却不是同一个问题。聊天和命令证据仍保留引用,不能说历史全部消失;消息编号也不是真人凭据,不能说修好这个投影就完成了多人授权。
它的实际价值在于:依赖该会话字段的查询者,可能只看见“会话没有触发消息引用”,而不知道信息曾经到达上一层。若以后要把一次操作追溯到原始指令,这一跳值得先解释清楚。
5. 研究应该落到哪里,而不是马上开发什么?
这轮研究并不指向立即重建身份平台。已有的 Agent 主体绑定应当保留;眼前可评审的是来源引用的传递约定,共享凭据则需要另行确认需求与授权边界。
触发消息引用的投影差异可以作为一个窄的工程评审问题:谁负责提供它、哪些入口会使用嵌套上下文、顶层和嵌套同时存在但冲突时如何处理、哪些查询真正依赖这个字段?这些需要形成清楚的读写约定,而不是凭一个缺省值自动增加一套身份系统。
至于共享凭据能力,还要先确认真实产品需求。如果系统要允许不同真人长期指挥同一个数字员工,就需要进一步回答:指令何时被接受,责任身份如何认证,旧动作何时固定身份,新动作如何选择授权,以及底层平台已有能力能否复用。当前实验没有给出这整条链的实现或验收。
对建设 Agent 产品的团队,一个实用的检查方法是:选一次真实动作,逆向查出使用的凭据、当时授权、责任人和原始指令。在哪一跳只能得到“应该是这个人”,就先把那一跳的证据补清楚。
一个 Agent 能记住谁说过什么,不等于它已经知道每个动作该以谁的权限执行。会话连续解决的是工作不失联;责任连续解决的是动作不失主。
研究与证据说明
第一方实验基于 2026 年 9 月 8 日固定源码提交 c008d9db91a2,在 Windows、Node v24.16.0 下运行。审批实验使用模拟执行回调;会话实验使用内存 SDK,未执行真实模型工具。聊天命令构造器的任务查询和治理依赖为合成输入,没有测试两个真人账号的认证或凭据切换。源码核查与探针支持上述局部结论,不构成全平台安全保证或独立 QA。
逐轮脱敏观测、源码摘要、历史聚合与记录校验器已随本文公开:中文证据说明 · 英文说明。公开包核对已保存的结果,不等于重新执行产品实验;原始运行文件、完整夹具及产品复跑仍属于访问受限材料。历史样本没有观测到本文假设的多人凭据事故;本轮没有修改产品,也未授权开发上述能力。
