DeepSeek super-agent:把「别打扰人」写成一张准入表

它不靠提示词说"别打扰人",靠三个格子:谁在哪个范围里说了什么话,才够格开一个新的活。默认模式只记录"它本会做什么",一条都不执行。

分享
DeepSeek super-agent:把「别打扰人」写成一张准入表

一个 agent 在群里多回一句,一个团队就少干一件事。 所以我们平时解决"agent 太吵"的办法,几乎都是提示词:别插话、别重复、只在必要时说。而这些办法的共同问题是——提示词不是权限,模型可以不听。

DeepSeek 的 Harness 团队 2026-11-01 开源了一个研究原型 dsh-superagent(MIT,v0.1.0),配套一篇设计文《Exploring Super-agent Design》。媒体全在写它的 Router + Worker 双层的性能(p95 15.7 分钟 vs 29.5 分钟),但它真正稀缺的东西在仓库的 docs/ 里:一整套把"尽量少占人注意力"写成代码的授权协议——两条进入路径、强度三档、一张按接收范围分行的准入表、三档执行模式、不可变的凭证与恢复前重校验、策略版本化,以及一节"我们刻意否掉了哪些概念"。

英文世界目前还没有文章拆这一层(二手报道停在"三种模式")。这篇按文档顺序把它拆开,并在最后给出与 Claude Code / Codex / Copilot cloud agent 的对照,以及能直接抄进自建平台的五条。

先说边界:这是研究原型不是产品。README 自己写了两句话必须记住——"文章里有些设计是未来方向,本原型并没有实现"、"代码是 agent 写的,风格与工程实践可能不一致"。性能数字全部自报,且只测合成消息与模拟工具。我们读的是文档,没有部署、没有实测(数据截至 2026-11-02)。


一、一句原则,四条推论

文档开篇只有一句:"take as little human attention as possible, and give as much value as possible"。接下来所有设计都被这句话判过一遍——一条消息、一个通知、一个提问、一个设置项、面板上的一个格子、文档的一段话,都在花别人的注意力。

落到 agent 行为上,是四条可检查的规则:

规则 原文口径
只在被要求、或被写好的规则允许时才行动 "请求"只算一种:直接点名 agent、且来自团队许可的人;没人要求的工作必须有团队写下的规则,而且先跑在"只记录它本来会做什么"的模式里
只在有人必须行动、或结果能派上用场时开口 确认一次并说明要做什么 → 干活时保持安静 → 有结果、有需要决策、或做不完时才再说
一次只问一个具体问题,并且用结构化表单 让它落到人眼前,而不是埋在长报告里
按影响停,不按投入停 局部改动做到可评审为止;需要设计决策的改动就停下并问

还有一个容易漏掉的:它把"责任"写在设计文档里,而不是写在条款里——agent 用你团队天天看得见的账号发言、开 PR,所以你欠同事的注意力,也由你负责。具体到操作上有一句非常反直觉的话:

当 agent 太吵时,把它的提示词改短改严,或者直接暂停;不要为了解释噪音而再发一条消息。

二、先把概念砍到五个

这套设计最"工程师"的地方是它拒绝造词。001-domain 只保留五个核心概念,其余全部是附属:

概念 一句话 它守的规则(关键几条)
Source 一个事件流(GitHub / 飞书各是一个实例) 自己记读位、自己有 bot 身份;重启不能重放事件;在进入系统前就丢掉自己的消息与不在监听范围内的事件
Trigger 一个不可变事件(带 actor 等元数据) 同一个 Trigger 被接受两次,只产生一个 Ticket——它是审计单位和幂等单位
Thread 按时间排好的 Trigger 序列 同一 Thread 同时只跑一个 Eval;一个 Thread 可以有多个 Ticket;持有 Subscription 与 Decision 历史
Eval 对一批 Trigger 的判断,分闸门与评估两层 自己不持有状态;输入是这批 Trigger + Thread 快照 + 该 Thread 上所有 Ticket(含已结束)+ 当前 Policy;输出是一个 Decision
Ticket 一个"被授权的工作" 只有 Eval 能创建;有自己的状态机(open → ended → 被人的消息唤回 open);状态不跟随执行会话
Mandate accept 授予的东西:策略版本、范围、强度、命中的规则、发送者身份、消息是怎么被收进来的 不可变;要扩大范围只能开新 Ticket;Ticket 结束不等于 Mandate 结束

外加两个支撑概念:Assignment(Ticket 与某个 Executor 实例的绑定,一个 Ticket 先后可以有多个)与 Subscription(Thread 与 Ticket 的多对多关系,由 Thread 持有)。

文档还专门有一段"人不是域概念":人的身份只是 Trigger 上由 Source 给出的标识;"许可名单"是某个 Source 的 Policy 的一部分;同一个人在不同 Source 上有不同账号,这件事只是提示词里的文本,不进数据模型。

三、两条进入路径:新工作 vs 续作

这是整套授权的地基。一条消息要变成"活",只有两条路:

路径 谁决定 授予什么
Eval(闸门 + 评估) 主会话判断"这是不是一个新请求" 通过后创建 Ticket 与 Mandate
Subscription(订阅扇出) Thread 把消息投给已订阅的 Ticket 什么都不授予——只作为上下文到达;仍受该 Ticket 的 Mandate 约束

关键在第二行的后半句:"投递绕过闸门,但不授予任何新权限"。也就是说,一旦某个 PR 上的 Ticket 还活着,别人在这个 PR 里说十句话,都会送到那个 Worker 面前,但它并不能因此扩大自己可以做的事;越界就要"交还"(hand back),由主会话重新判断。

文档还写了交还的三种情形,很细:超出 Ticket 范围、属于另一个 Ticket、或者"我跟着的这个 Thread 其实是无关的"。同一条消息只会被交还一次;交还之后如果没有任何 Ticket 还持有它,它才进入 Eval,且候选里会带上各 Executor 给出的理由。

四、强度三档,和那张三格子的准入表

一条消息"有多强",被固定成三档:

强度 什么时候成立
explicit(显式请求) 名单内的人点名 agent;或名单内的人在已经有 Ticket 的 Thread 里追问;或准入表里把某一格设成"显式请求"
inferred(推断候选) 名单外的人在已有 Ticket 的 Thread 里追问(除非那一格是显式);准入表里设成"推断候选"的格子;bot 名单里的 bot 点名或出现在"收全部消息"的范围
not admitted 其他 bot 的一切;准入表里"忽略"的一切;以及 off 模式下所有 inferred 的情形

然后是那张表。它按 Source 的"接收范围"分行,每行最多三个格子:

  • 飞书:每个配置过的群、"其他 @ 它的群"、私聊;
  • GitHub:新 Issue、新 PR、评论、主干 CI。
格子 可选项 默认
名单内的人、没点名 inferred / ignore inferred
名单外的人、点名了 explicit / inferred / ignore ignore
名单外的人、没点名 inferred / ignore ignore

这张表有三处设计值得单独记:

  1. 默认值全是"最保守"的那一档。 陌生人点名 = 忽略;陌生人随口说 = 忽略;名单内的人不点名 = 只能是推断候选(还要看执行模式)。
  2. "没点名"的两个格子只在"能收到全部消息"的范围里才存在(飞书设成"全部消息"的群、GitHub 开了全收开关的范围)。
  3. CI 结果没有发送者,所以它那一行只有第三个格子;bot 走另一套"bot 名单",而且文档写死了:bot 不能产生显式请求,也不能停掉 Ticket。

有一个容易被忽略的反向开关:把"名单外的人、点名了"这一格设成 explicit,就等于"这个群里任何人 @ 它都能派活"——文档举的用例是专门的客服群。这是唯一一个"故意放宽"的旋钮,而且它在任何执行模式下都生效。

五、三档执行模式:默认只记录,不执行

模式 效果
off 推断类一律不进候选(没点名的消息、bot 的消息、名单外的人的追问)
observe(默认) 推断类照常评估,评估为"该接"的记成 ignore,并标注 "would accept";一条都不接
auto 推断类评估为"该接"就接

显式请求在任何模式下都生效,所以 observe 不会让正常协作卡住——它只是把 agent 的"主动性"先关进观察室。文档给的迁移路径也很朴素:先跑 observe,翻一翻记录下来的 Decision,再切 auto。

切到 auto 之后还有一道闸:主动接手必须至少命中一条团队写下的规则。每条规则描述一类"主动工作",命中哪些规则会被写进该 Ticket 的 Mandate,Worker 也会收到这些规则的名字与指示。规则里的流程与沟通要求会覆盖默认值(比如"沉默规则"可以压掉确认消息,"评审规则"可以指定必须由谁批准才能合)。

六、Mandate 的一生:只有三件事能改它

事件 对 Mandate 的影响
Eval accept 创建它
人按下 stop 撤回它(Ticket 保持 ended,之后什么都不会再收到)
恢复前重校验失败 吊销它

除此之外,Ticket 结束不结束 Mandate——这正是"一句话就能让旧活复活"的原因:已结束的 Ticket 保留 Mandate 与 Subscription,人在它自己的 Thread 上说一句,就能就地恢复,不走 Eval、不产生新 Decision;而 bot 与 CI 唤不醒已结束的 Ticket。

但复活不是无条件。恢复前要过一张矩阵(这可能是全文最值得抄的一张表):

Mandate 的来路 恢复前还要求什么
显式追问(explicit) 直接放行
推断而来(inferred) 当前必须是 auto,且命中的规则仍启用
由准入表某格授权 今天的表与发送者名单仍能给到至少原强度——所以把人从名单里删掉,能吊销它当初授权的 Ticket
bot 的 那个 bot 仍在 bot 名单里;且需 auto + 规则启用
其他 发送者仍在许可名单里

还有一个细节:恢复还要求 Source 仍在监听原来那个 Thread,但不要求它仍在"收全部消息"——因为"重新开始听"和"继续把每条消息都推过来"是两件事。

重校验失败之后会发生什么,文档写得很不客气:Ticket 保持 ended,一条等着它的消息都不接;每条消息被当成"没到过任何 Ticket",如果没有别的 Ticket 持有它,就回到 Eval;而且主会话不会被通知"它到过某个 worker"。之后的活要重新走一次 accept。

七、策略版本化:改规则,不砍在跑的活

团队改规则(规则文本、执行模式、各 Source 的 Policy)会产生一个新的策略版本,每张 Mandate 都记着自己被接受时是哪个版本。版本一变:

  • 在跑的 Eval 被丢弃,它的 Trigger 重新排队;
  • 受影响的活 Ticket 会收到一条 policy-changed 输入,说明是命中规则改/不再适用、是请求人不再有资格、还是主动工作不再被接受(比如从 auto 退回 observe);
  • 不受影响的 Ticket 不收到任何通知(少一条消息就少一次打扰);
  • 不立即吊销 Mandate。

文档还专门把"改策略就取消在跑的 Ticket"列为被否掉的方案,理由是"被取消的变更会留下半成品"。这句是一整套设计的气质:它宁可多一次通知,也不愿意制造一个半成品。

还有一根手术级别的分界线,值得单独引用:

在对话里说 "stop" 是普通 Trigger,由 Eval 判断这是不是一个停止;在面板里按 stop 是命令,直接作用于 Ticket,并记为人工停止。而且——Executor 不能宣告"是人让我停的"。

同一逻辑还处理了"等一会儿"这件事:像"没人认领 N 小时"这种等待条件,属于 Source,由它自己等、自己再查;Eval 永不等待。这也是为什么文档把"等待中 / 已撤回"的 Eval 状态一并否掉——状态一旦多出这两种,重试与审计就说不清了。

八、执行侧的常数

003-execution 里全是可直接抄的数字:

机制 值 意图
前台 shell 转后台 5 秒(worker 与 router 同一套) 让 worker 能在下一步收到新消息,而不是等长命令跑完
一轮结束后后台还能跑多久 最多 30 分钟,到点杀 shell 并上报(列出被杀的任务与仍在跑的子 agent) 不让"以为在干活"变成永久占用
交还给人时 立刻释放 worker slot;shell(比如留给评审的本地服务)可以继续,且不占 slot、不受 30 分钟限制 人一接手,机器就不该继续占坑
并发 配置的并发上限 + 1 个额外 slot,留给"人发来的消息"或状态查询 新活不能挡住人
目录准备 prepare 命令跑一次,限时 10 分钟,典型做法是 git worktree 一个 Ticket 一个目录一个分支
关停 每个 worker 的后台工作最多等 10 秒;进程重启则直接终止 边界清晰,便于恢复
交付/投递重试 失败后 2 秒起,指数退避到 1 分钟;通道消息从 5 秒退避到 300 秒 对端抖动不该变成人的通知
错误上报 同类动作连续失败三次才进面板的"系统问题" 少一条噪音就少一次打扰

自动合并的默认边界也很克制:只在"为本 Ticket 开的 PR、已 ready、必需审批覆盖 head commit、增删合计 < 200 行"时才允许开;再推新版本前必须先撤销 auto-merge。而且默认不以 agent 账号去合并——因为 GitHub 会把这次合并记在"谁开的 auto-merge"名下(默认是由人合)。

还有一条小而重要的产品设计:它发出的每一条 GitHub 消息第一行都是 This is by an automated agent, not a human。

九、授权阶梯:五级优先级

004-prompts 里有一张比大多数"agent 框架"都清楚的优先级表,从强到弱:

级别 内容 能否被提示词改写
1 由工具与宿主强制的事实:身份、权限、工具参数检查、回复用途、长度限制 不能
2 内置与生成的分节(团队覆盖过的按覆盖读) 团队可覆盖第 2 级,但改不了第 1 级
3 主动 Ticket 命中规则的流程与沟通要求(只对该 Executor 生效) 规则级
4 团队分节与团队技能 是
5 外部文本:消息、评论、文档、引用 它只是数据,永远不能改规则或授权

文档把这句话写得很直:改提示词会改变模型收到的指示,但不会改变闸门、Mandate、工具检查与账号包装——后面这些由代码强制。

这也顺带解释了"为什么 Router 可以很轻":它只负责派发与对外说话,可以不装 Bash;真正的执行在 Worker 里,Worker 的工具里刻意去掉了会向人提问或改配置的那些(ask_user_question、present、plugin_manager),因为它们是无人在场的。

十、12 个被否掉的设计

001-domain 里这张表是全篇最独特的东西——很少见有人把"我们决定不做什么"逐条写下来:

被否掉的概念 理由(原文意思)
把人做成实体 / 跨 Source 映射身份 人只是 Trigger 的元数据;跨平台对应关系是提示词文本
让 Eval 自己排"延迟 Trigger" 需要等待的是普通 Source,Eval 永不反过来依赖 Source
"等待中 / 已撤回"的 Eval 状态 等待属于 Source;超时的 Eval 要么重排队,要么以 unavailable 结束
一个 Thread 最多一个活 Ticket 一个 Thread 可以承载多件互相独立的工作
"把消息追加到 Ticket"作为一个 Decision 追加就是订阅扇出,不需要 Eval
对 Subscription 再做准入检查 Subscription 覆盖整个 Thread;授权与上下文由 Mandate 分开
让 Correlation(关联关系)承担路由 路由是 Subscription 的事,Correlation 只补充上下文
让 Ticket 状态跟随会话 Ticket 可能被移交、恢复、由多个 Executor 跑
让 Executor 宣告"人让我停" 终止的强度只能由 Eval 判
改策略就取消在跑的 Ticket 被取消的变更会留半成品;改为记录并投递
Executor 失败/阻塞时锁死它全部工具 那会挡住人直接在会话里接手,也会挡掉恢复后的报告;暂停自动输入就够
从报告的自由文本里推断"在等人" 分类需要结构化事实,所以要求用结构化字段提问

最后两条尤其值得抄:"锁死工具"和"从自由文本推断状态"都是很自然的第一反应,而它们分别破坏了人的接手与机器的可判定性。

十一、我们的整理:它和现有产品差在哪

维度 DeepSeek super-agent(原型) Claude Code(本地会话) Codex(云端任务) Copilot cloud agent
工作单位 Ticket(带不可变 Mandate) 会话 云任务 Issue / 分配 / 自动化
授权来源 显式 / 推断 / 准入表三档 + 执行模式 权限规则(allow/deny/ask)+ 审批 账号与仓库范围 计划与组织级设置
未点名时会不会干活 默认不干,只记录"本会干" 不会(除非 hook/自动化) 取决于任务创建 可以(automations)
权限能否被提示词改写 不能(闸门与 Mandate 由代码强制) 部分(规则在配置里) 账号侧 组织侧
改规则对在跑的活 通知 + 不吊销 下次会话生效 — 取决于平台
人的消息优先级 独立额外 slot 交互式 — —

我们不认为这构成"谁更强"的结论——它测的是合成消息,真实代码质量没测。但它给出了四个可以直接借的结构:

  1. 默认 observe:任何"主动"能力上线第一步,先只记录"它本来会做什么",让人翻记录再开闸。这个开关比任何"我们很安全"的声明都便宜。
  2. 权限靠不可变凭证,不靠提示词:Mandate 记下"为什么可以做、能走多远",改提示词改不动它;范围要扩大就开新的。
  3. 授权要能级联吊销:把人从名单移除,应当让"当初靠这个人授权的活"在下次恢复时失效——否则一次权限回收只是心理安慰。
  4. 改规则不要砍在跑的活:通知 + 记版本 + 让下一次恢复时重校验,比"立刻取消"更少半成品。
  5. 人的消息要单独一条通道:并发满了也要留一个额外 slot 给人。这条和"少打扰人"是同一枚硬币的两面——不打扰 ≠ 让人插不进来。

如果你想接着读"多 agent 怎么组织",可以看 循环在节点之内,图在节点之间;想看"权限被绕过"的真实案例,看 Claude Code 的 shell 变量绕过 与 九起 agent 事故与六项控制。

十二、边界

  • 原型,不是产品:README 明写"仅供研究参考、非正式产品",并说明设计文里部分方向在原型中未实现;代码由 agent 参与编写,风格与实践可能不一致。
  • 数字是自报且口径有限:p95 15.7 分钟 vs 29.5 分钟来自约 300 条消息(其中约 20 条真需求)、每方案 5 次、合成消息 + 模拟工具;基线在 5 次里调用子 agent 0 次;token 约 23.2M(cache-read)vs 6.1–10.8M。真实代码质量未测。
  • 安全姿势要自己加:Worker 以操作者的 OS 用户身份免审批执行命令,文档也要求"先隔离再上";默认 observe 与准入表是减噪与减权限,不是沙箱。
  • 本文为文档整理(主源为仓库 docs/000–005 英文设计文档,参考团队设计文与二手报道),我们没有部署、没有实测;术语尽量保留原文英文,便于对照。

Sources

  • 仓库与文档:deepseek-ai/dsh-superagent-prototype(MIT,v0.1.0)https://github.com/deepseek-ai/dsh-superagent-prototype
  • docs/000-philosophy.md、001-domain.md(含 Rejected concepts)、002-authorization.md、003-execution.md、004-prompts.md、005-panel.md
  • README.md("研究原型"声明与"部分设计未实现")
  • 设计文:DeepSeek Harness 团队《Exploring Super-agent Design: Towards a More Autonomous Agent System》,2026-11-01(英文为中文原文的机器翻译)
  • 性能数字的二手来源:MarkTechPost《DeepSeek Open-Sources dsh-superagent》(2026-11-01)、CloudNavi《Why DeepSeek's AI dropped the session》(2026-11-01)——两者均标注为"自报/转述"

同主题阅读

本文由 Software 2.0 整理编译,转载请注明出处。文中所有机制描述以仓库文档原文为准;性能数字为发布方自报,我们未复测。

这是「Agent / MCP」专题的一部分。完整地图见:Agent / MCP / 自动化完全指南