【免费下载链接】dsh-superagent-prototype
Towards a More Autonomous Agent System
dsh-superagent 是一个面向 GitHub 仓库的主动式自主编码智能体(autonomous agent)系统,其 dsh-superagent 架构的核心由四个部分组成:负责组装与生命周期的 Runtime、负责所有领域决策的 Engine、负责持久化的 Store,以及负责可恢复副作用的 Effects。本文带你用最短的路径读懂这套架构,理解它们如何协同作战,让 Agent "只在被要求时才行动,只在有人需要时才说话"。
一图看懂:dsh-superagent 架构全景
先建立整体印象。dsh-superagent 的运行形态可以概括为:消息进来 → 评估 → 开工 → 回报,四个核心模块各守其位:
图源:改编自 docs/007-architecture.md 中的架构流程图
| 模块 | 一句话定位 | 源码位置 |
|---|---|---|
| Runtime | 组合根:组装所有组件,掌管启动与关闭 | src/app/runtime.ts |
| Engine | 决策中枢:所有领域状态唯一的写入者 | src/core/engine.ts |
| Store | 持久化:独占一个 SQLite 数据库文件 | src/app/store.ts |
| Effects | 副作用队列:可重试、可恢复的异步工作 | src/app/effects.ts |
Runtime:组装一切、掌管生死的组合根
Runtime(src/app/runtime.ts) 是整个应用的"总装车间"。它本身不含任何业务规则,职责非常纯粹:
- 启动阶段:锁定状态目录 → 打开 Store → 逐个构建 Engine、Effects、Outbox、Sessions 等组件;如果构建失败,回滚关闭,不留半成品。
- 运行阶段:注册管理 API 路由、恢复被中断的任务(Assignment)、启动周期性调度器 Passes 和 Effects 队列。
- 关闭阶段:取消进行中的回合、等待所有队列排空、恢复进程环境、关闭数据库、释放目录锁。
一个值得注意的细节:Executor 和 Assessor 会回调 Engine,为避免循环依赖,Runtime 给它们的不是构造器,而是 getter。这种"窄接口注入"贯穿整个 dsh-superagent 架构——每个模块只拿到自己需要的那一小撮接口(如 ExecutorHost、AssessorHost),而不是整个应用。
Engine:唯一拥有"写权限"的决策中枢
Engine(src/core/engine.ts) 是 dsh-superagent 架构的心脏。它有一个铁律:
Triggers、Threads、Decisions、Tickets、Assignments 这五类领域状态,全世界只有 Engine 能写。 其他模块要么读,要么向 Engine 申请。
这带来一个直接好处:无论消息来自 GitHub、Feishu 还是面板,所有状态变更都走同一条规则化路径,不会出现"两处代码改了同一张票"的混乱。
Engine 的五大内部模块
Engine 对外只暴露一个入口,内部拆成五个单向依赖的模块(Intake → Evals → Tickets → Assignments → Replies):
| 模块 | 职责 | 通俗理解 |
|---|---|---|
| Intake | 接收 Source 的 Trigger,去重、扇出给订阅的 Ticket | 前台登记处 |
| Evals | 对一批 Trigger 做评估,产出 Decision | 面试官 |
| Tickets | 工单全生命周期:创建、挂起、重试、停止、结束 | 项目经理 |
| Assignments | 接收执行器回报:开工、交付、报告 | 现场监工 |
| Replies | 通过 Outbox 回写渠道:确认、答复、结果 | 对外发言人 |
两个命名约定让代码意图一目了然:命令用现在时(stopTicket、attach),适配器回报的事实用过去时(assignmentStarted、deliveryFailed)。每个命令都在一个事务中完成聚合变更,调用方还只能拿到自己角色对应的 Pick 接口(如 EngineForSources、EngineForPeople),权限天然隔离。
Store:一个 SQLite 文件承载全部状态
Store(src/app/store.ts) 独占 <stateDir>/orchestrator.sqlite 这一个数据库文件。Runtime 打开它之前会先拿目录锁,确保第二个进程不可能同时迁移或写入同一份状态。
Store 的接口按用途分成五组:
- 领域仓储:
triggers、threads、tickets、decisions,各有get/save与列表查询; - 只读查询:
read服务面板视图、工具与 Source 轮询,永不写入; - Source 元数据:Source 只允许写自己 Thread 上的
meta; - 设置与版本:Settings 和 Prompts 都按带编号的
Versions存快照; - Outbox 回执:每条对外消息的发送状态,只由 Outbox 写入。
持久层有两个精妙设计:
afterCommit钩子:事务提交后才执行的动作,回滚则永不执行。比如 Executor 的停止指令就挂在上面——如果"结束工单"的事务回滚了,worker 就不会被误杀。- 生成列索引:
threads.active、tickets.open等生成列让调度器每轮只读"活跃工作集",而非全表扫描。
Effects:让副作用"落盘可恢复"的队列
Effects(src/app/effects.ts) 是 dsh-superagent 架构中最容易被低估、却最关键的模块。它回答了一个经典难题:模型调用、消息发送这类外部副作用,进程重启后怎么办?
答案是:副作用先"落盘",再执行。命令在自己的事务里调用 enqueue(kind, key, payload),只有事务提交后执行才开始。队列中每个 kind/key 只占一行;相同 key 重复入队时直接替换负载并立即到期,天然合并重复工作。
六类 Effect 构成整个系统的工作流:
| Kind | 执行者 | 干什么 |
|---|---|---|
assessment | MasterAssessor | 把候选卡片递给主 Session 评估 |
launch | DshExecutor | 为待办 Assignment 拉起 worker 会话 |
delivery | DshExecutor | 把 Input 按序交给运行中的 Assignment |
relay | Sessions | 转发 worker 报告与人工追问 |
notice | Sessions | 不唤醒主 Session 地注入通知 |
reply | Outbox | 通过 Source 渠道真正发出消息 |
可靠性由三件小事保证:指数退避重试(如 2 秒翻倍至 60 秒)、Later 延迟机制(无 worker 槽位时让路但不计失败)、每类一个健康度条目(连续失败 3 次才上报错误)。这意味着崩溃、重启、网络抖动都不会丢工作——这正是"自主 Agent"敢放手的底气。
协同作战:一次 Trigger 的完整旅程
把四个模块串起来,看一条 GitHub 评论如何变成一次 PR 回报:
- Source 插件(src/sources/github-trigger.ts)轮询到通知,翻译成 Trigger,交给 Passes;
- Passes(src/app/passes.ts) 每 2 秒一轮,先跑
Effects到期任务,再调Engine.evaluateDue——新 Trigger 存库后立刻请求一轮; - Engine 将 Trigger 入库并扇出,随后 Eval 流程把候选卡片经
assessmentEffect 递给主 Session 评估; - 评估
accept后,Engine 在一个事务内原子创建 Ticket、Mandate、Assignment 和确认消息,并向 Effects 入队launch; - DshExecutor(src/executor/dsh.ts) 消费
launch,在独立目录与 Session 中开工,期间通过delivery接收 Input,结束后调Engine.report回报结果; - 结果经
replyEffect 由 Outbox 发回原会话,回执写入 Store。
整个旅程中,领域规则只在 Engine、状态只在 Store、异步动作只在 Effects——任何一步失败,都有确定的恢复路径。
架构亮点:这套设计做对了什么
- 单一写入者原则:每类状态只有一个 Writer(Trigger/Ticket 归 Engine,回执归 Outbox,Effect 行归 Effects),其余模块只读或申请,从根源消灭竞态;
- 窄接口依赖:
src/core不依赖src/app、不做任何 I/O,可以纯内存测试全部领域规则(见 tests/core-engine.spec.ts); - 命令与事实分离:命令可被拒绝(
UserError),事实必须被记录,命名约定让两者不可混淆; - 事务内入队、提交后执行:一致性边界清晰,副作用永不"半提交"。
延伸阅读:如何继续深入
| 想做什么 | 从这里读起 |
|---|---|
| 理解设计哲学 | docs/000-philosophy.md |
| 掌握领域概念(Trigger/Ticket/Mandate) | docs/001-domain.md |
| 完整架构开发者指南 | docs/007-architecture.md |
| 运行时行为细节 | docs/003-execution.md |
| 核心代码入口 | src/core/ports.ts、src/app/runtime.ts |
| 面板与 API 层 | src/app/api.ts、src/client/app.tsx |
dsh-superagent 架构的本质,是把"自主性"关进了一个可审计、可恢复、可暂停的笼子里:Engine 管"该不该做",Store 管"发生过什么",Effects 管"做完但没做稳的",Runtime 管"这一切何时开始、何时停止"。读懂这四个模块的协作,也就读懂了如何构建一个既主动又不越界的 Agent 系统。
【免费下载链接】dsh-superagent-prototype
Towards a More Autonomous Agent System
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



