dsh-superagent 源码分析
dsh-superagent 源码分析:Trigger、Ticket、Policy 与 Subscription
- 作者
- DeepSeekAgent.io 编辑部
- 发布
- 更新
dsh-superagent-prototype 最值得研究的部分,不是又封装了一层 Sub-agent,而是它为长期运行的 Agent 建立了清楚的领域模型。消息、权限、任务、执行和恢复都对应持久化概念,模型只在需要语义判断的环节参与。
本文沿着一条事件从进入系统到完成工作的路径,解释 Source、Trigger、Thread、Eval、Policy、Mandate、Ticket、Assignment 与 Subscription 如何配合。
Source:事件从哪里进入
Source 是事件流的实现与配置实例。公开原型包含 GitHub Source,并支持可选飞书 Source。Source 负责:
- 记录读取位置,避免重启后重放旧事件;
- 把外部消息转换成不可变 Trigger;
- 判断哪些 Trigger 属于同一个 Thread;
- 保存回复所需的 Channel 地址;
- 丢弃 Agent 自己产生的消息和不在监听范围的事件。
因此,Source 不只是一个 Webhook。它负责外部系统和内部领域模型之间的边界。
Trigger 与 Thread:事件和上下文分开
Trigger 是一条不可变事件,包含 Source 提供的 actor 和元数据。Thread 是按时间排序的 Trigger 集合,例如一个 GitHub Issue、一条 Pull Request 评审线程或一个飞书话题。
一个 Trigger 可以关联多个 Thread,但关联关系只增加上下文,不直接授予权限。这个区分很重要:看到相关消息,不等于 Agent 获得了执行新任务的授权。
Eval:是否应该创建工作
没有被现有 Ticket 拥有的 Trigger 会进入 Eval。Eval 分成两层:
- Gate 使用确定性规则检查发送者、@ 状态、allowed list、Source 范围和 admission table;
- Assessment 使用模型判断推断型候选是否符合启用的主动规则。
Eval 输出 Decision,例如 accept、stop、ignore 或 unavailable。显式请求可以直接路由;主动发现的候选必须经过规则判断。默认 observe 模式会记录“本来会接受”,但不会真正创建任务。
Policy 与 Mandate:谁授权了什么
Policy 包含 Source 的 allowed list、admission table、机器人列表、主动规则和 accept mode。每次变化形成新的 Policy version。
当 Decision 接受工作时,系统创建 Mandate,记录:
- 使用的 Policy version;
- 请求来源与发送者;
- explicit 或 inferred 强度;
- 允许完成的 scope;
- 命中的主动规则。
Mandate 是 Ticket 的授权依据。Worker 收到后可以在 scope 内继续处理后续消息,但不能因为某条评论提到另一个任务,就自动扩大权限。
Ticket:持久任务,而不是一次模型调用
Ticket 是一项获得授权的工作。它可以经历多次 Assignment,保持自己的 Channel、Input、Subscription 和 Decision 引用。Executor 失败、重启或被替换时,Ticket 不会跟着消失。
Ticket 状态和 Session 状态也被刻意分开。一个 Ticket 可以等待人工回复、等待评审、结束后被后续人类消息恢复,或在新的 Assignment 中继续执行。这样,任务生命周期不会被某一次模型请求绑死。
Assignment 与 Executor:谁在这一轮执行
Assignment 把 Ticket 绑定到一个 Executor 实例。每个 Ticket 有独立 Worker Session 和目录。一次重试会结束当前 Assignment,并在同一 Ticket、目录、分支和 Pull Request 上创建新的 Assignment。
Worker 报告 progress、waiting、ready、blocked、failed 或 dropped。Pull Request 是否仍开放、是否收到人工后续消息、是否有未读 Input,都会影响 Ticket 是否真正结束。
Subscription:让后续事件回到正确任务
Subscription 是 Ticket 与 Thread 的多对多关系。一个 Ticket 订阅 Issue 和自己创建的 Pull Request 后,后续评论、CI 结果和评审就会作为上下文送回 Worker。
Subscription 不会产生新授权。消息可以提供上下文,但 Worker 仍受原 Mandate 限制。超出 scope 的人类请求会被“交还”给 Router,重新进入 Eval,而不是被当前 Worker 顺手执行。
结束的 Ticket 可以保留 Subscription。相关 Thread 中的人类追问能够恢复任务;机器人消息和 CI 不会自动唤醒已经结束的 Ticket。这让系统既能持续跟进,又不会被自动事件无限复活。
为什么这个模型适合长期 Agent
传统 Agent 常把所有状态放进对话历史:模型记得就继续,压缩或重启后就可能丢失。dsh-superagent 把关键状态放进结构化记录:
- Source 保存外部读取位置;
- Trigger 保存原始事件;
- Decision 保存为什么接受或忽略;
- Mandate 保存授权边界;
- Ticket 保存工作生命周期;
- Assignment 保存每次执行;
- Subscription 保存后续路由关系。
模型负责语义判断和工作执行,Host 负责幂等、权限和恢复。Super-agent 的“持续性”来自这层结构,而不是依赖无限长上下文。
一条 GitHub Issue 的完整路径
GitHub comment
→ Source records Trigger
→ Thread groups Issue context
→ Gate checks sender and mention
→ Eval produces accept Decision
→ Mandate records scope and Policy version
→ Ticket is created
→ Assignment starts an Executor Session
→ Worker prepares directory and opens PR
→ Ticket subscribes to PR Thread
→ review and CI Triggers return to the same Ticket
→ PR closes and Ticket ends
→ later human follow-up may resume it
这条路径也是源码阅读的最佳顺序:先读 001-domain.md,再看 002-authorization.md 和 003-execution.md,最后进入具体 Source、存储和面板代码。
相关阅读
- DeepSeek Super-agent 架构:Router、Worker 与持续在线 Agent
- dsh-superagent 部署教程:GitHub、飞书与独立 Worker
- dsh-superagent 安全边界:账号、权限与执行隔离