背景
Memoh 是一个多用户 AI Agent 平台——用户创建 Bot,Bot 通过进程内 Agent Runtime + workspace/container 能力处理来自 Telegram、Slack 等聊天平台的请求。每个 Bot 拥有持久化的文件系统、记忆、技能和身份。
当前架构更准确地说是 一个进程内 Agent Runtime + 多个 Session 上下文 + 一个 Bot Workspace 容器 。Bot 可以通过 spawn 并行创建 subagent session,但这些 subagent 复用同一个 Agent Runtime,默认也复用同一个 Bot 的 workspace container。它们是 session 级并行,不是独立的 worker runtime。
这在处理简单请求时足够。但有一类任务正在变得越来越重要:
Deep Research :需要多轮搜索 → 阅读 → 综合 → 验证,单次 LLM 循环放不下
复杂代码生成 :需要规划 → 编码 → 测试 → 修复的迭代,且不同步骤需要不同工具环境
设备操控(Autofish) :需要长时间运行、观察-行动-验证的循环,中间可能需要人类介入
多步骤自动化 :跨系统操作(查数据 → 生成报告 → 发邮件),每步有外部副作用
这类任务的共同特征是:需要任务级分解、隔离执行环境、结构化协作、持续验证和可恢复的控制流。 当前的 spawn 模型无法满足——它没有任务图、没有独立 worker 生命周期、没有共享状态层、没有验证环节。现有实现已具备 watchdog、超时和重试等单子任务保护,但还没有任务级的错误恢复、重规划和编排控制。
Memoh 已有 Agent Runtime、Tool Loop 和 workspace/container 基础设施。缺的是面向复杂任务的编排层:任务模型、worker 模型、调度器、共享状态和事件流。
目标
核心目标
在 Memoh 现有 User Bot 架构之外,引入一个 task-oriented orchestration subsystem,将复杂任务动态分解为 DAG,调度多个 task-scoped worker 在隔离环境中执行,并在执行过程中持续验证和自适应调整。
具体而言:
动态编排 :Orchestrator 接收 prompt,通过迭代式规划(Plan → Execute → Observe → Re-plan)将任务分解为 DAG,根据任务特征标签选择编排模式,根据执行反馈动态调整计划。
独立 Worker Runtime :每个 Worker 是 task-scoped 的运行单元,拥有自己的 task context、生命周期和事件流;执行环境可绑定独立容器、sandbox 或设备能力。
结构化协作 :通过 NATS 消息总线 + 分层 Blackboard(NATS KV Store)实现通信和状态共享,Worker 只读前驱和全局上下文、只写自己的结果。
约束
作为 tool 暴露 :编排能力以异步 tool 调用的形式提供给 User Bot,不改变现有 Bot 的交互模型
Worker 与 User Bot 分离 :被编排的 Worker 是面向任务的运行单元,不承载面向用户的功能(身份、聊天平台接入、用户侧记忆与社交动作);User Bot 不参与调度
Human-in-the-Loop :编排任务可在关键决策点暂停等待用户输入,支持超时默认策略和状态快照
可恢复的错误处理 :Worker 自分类错误(retryable / env_mismatch / fatal),指数退避重试,不可恢复的失败可控传播到上层
非目标
通用的 multi-agent framework
跨用户的 agent 协作
agent 自主发现和自注册
方案
总体架构
graph TB
subgraph 用户侧
U[用户] -->|聊天/命令| UB[User Bot]
end
subgraph Server 侧
UB -->|消息流| AR[Agent Runtime]
AR -->|orchestrate tool 调用| OE[Orchestrator Engine]
OE -->|管理| NATS[NATS 消息总线]
OE -->|读写| BB[Blackboard]
OE -->|创建/销毁| DK[Worker Runtime Manager]
NATS --- BB
end
subgraph Worker Runtime / 执行环境
DK -->|分配任务 + 绑定 env| W1[Worker: Researcher]
DK -->|分配任务 + 绑定 env| W2[Worker: Coder]
DK -->|分配任务 + 绑定 env| W3[Worker: Verifier]
DK -->|分配任务 + 绑定 env| W4[Worker: Phone Operator]
end
W1 -->|pub/sub| NATS
W2 -->|pub/sub| NATS
W3 -->|pub/sub| NATS
W4 -->|pub/sub| NATS
OE -->|结果回传| UB
Loading
编排以 异步 tool 暴露给 User Bot。User Bot 所在的 Agent Runtime 调用 orchestrate(prompt | status | cancel) 后异步返回 task_id,Orchestrator 在后台完成分解、调度、执行、验证,最终将结果回传。
任务图模型
任务图在任一时刻为 DAG。 逻辑上的迭代(Maker-Checker 循环、Debate 等)通过 Orchestrator Re-plan 动态追加节点实现,图内不存在环。这保证调度只需拓扑排序,无死锁风险。
A ───→ C ───→ E
↗ ↘
Root → F (join: 依赖 C + D)
↘ ↗
B ───→ D
调度规则:入度为 0 的节点并行执行,完成后减少后继入度,新的入度为 0 的节点继续执行。
分层 Blackboard
每个任务节点拥有独立的 Blackboard(NATS KV bucket bb_{task_id}):
bb_root: goal, constraints, budget, deadline, global_context
bb_a: sub_goal, status, result, artifacts
bb_b: sub_goal, status, result, artifacts
bb_c: sub_goal, status, result (读取 bb_a + bb_b)
访问规则:
角色
可读
可写
Worker X
自己的 bb + 所有前驱 bb + Root bb
只写自己的 bb
Orchestrator
所有 bb
所有 bb
Verifier
被验证节点 bb + 其前驱 bb
验证结果写到被验证节点 bb
任务生命周期
Orchestrator 采用迭代式规划(Plan → Execute → Observe → Re-plan),拆为四个独立模块:
模块 1 — 规划(Planner)
flowchart LR
A[接收 prompt / 任务节点] --> B[LLM 标注任务特征]
B --> C{需要分解?}
C -->|是| D[生成子节点 + 依赖关系 → 构建子 DAG]
C -->|否| E[标记为叶子节点 → 进入调度]
D --> E
Loading
输入:一个任务节点。输出:叶子节点(可直接执行)或子 DAG。任何层级的节点都可能触发规划,包括 Worker 运行中 request_decompose。
模块 2 — 调度(Scheduler)
flowchart LR
A[接收 DAG] --> B[计算各节点入度]
B --> C[入度=0 的节点 → 并行分发]
C --> D[匹配 Worker 类型 → 分配 Runtime / Env]
D --> E[Worker 开始执行]
E --> F[节点完成 → 后继入度 -1]
F --> G{新的入度=0 节点?}
G -->|是| C
G -->|否 + 仍有运行中| H[等待]
G -->|否 + 全部完成| I[DAG 完成]
Loading
核心是拓扑排序驱动的事件循环。每个节点完成是一个事件,触发后继的入度更新和可能的新调度。
模块 3 — 执行(Worker)
flowchart LR
A[Worker 接收任务] --> B[读取 Blackboard: 自己 + 前驱 + Root]
B --> C[执行]
C --> D{结果}
D -->|完成| E[写结果到自己的 Blackboard]
D -->|需要再分解| F[request_decompose → 回到 Planner]
D -->|env 不匹配| G[上报 → Orchestrator 换 Worker]
Loading
Worker 是 task-scoped runtime。运行时上下文从任务定义和 Blackboard 读取,所有产出写回 Blackboard,并通过事件流上报状态。
模块 4 — 验证与错误处理(Verifier)
flowchart LR
A[节点执行完成] --> B{验证方式}
B -->|叶子节点| C[Verifier Worker 验证]
B -->|中间节点| D[Orchestrator 聚合子结果验证]
C & D --> E{通过?}
E -->|是| F[标记完成 → 通知 Scheduler]
E -->|否 + 可重试| G[指数退避重试 → 回到 Worker]
E -->|否 + 需重写| H[Re-plan → 回到 Planner]
E -->|否 + 不可恢复| I[标记失败 → 所有可达后继标记 blocked]
Loading
失败处理三级:当前节点重试 → 当前节点 Re-plan → 失败传播(标记后继 blocked,由上层决定是否整体 Re-plan)。
模块间关系:
Planner ──生成 DAG──→ Scheduler ──分发──→ Worker
↑ │
│ 完成/失败事件 │ 结果
│ ▼
Scheduler ←──验证── Verifier
│
↓ (Re-plan)
Planner
任务标签系统
Orchestrator 分解任务后为每个子任务标注特征标签,用于 Worker 匹配和调度策略:
标签
取值
影响
idempotent
true/false
是否可安全重试
has_side_effect
true/false
是否有外部状态变更
complexity
low/medium/high
是否需要进一步分解
latency
realtime/async
是否走 warm pool
env
web/code/device/...
匹配 Worker capabilities
depends_on
[task_ids]
调度依赖
interruptible
true/false
是否可暂停等待 HITL
通信:NATS + Blackboard
flowchart LR
subgraph Orchestrator
OE[编排引擎]
end
subgraph NATS Topics
T1[task.assign.*]
T2[task.result.*]
T3[task.status.*]
T4[bb.update.*]
T5[hitl.request/response]
T6[worker.error.*]
end
subgraph Workers
W1[Worker A]
W2[Worker B]
W3[Verifier]
end
subgraph Blackboard
BB[(共享状态)]
end
OE -->|分配| T1 --> W1 & W2
W1 & W2 -->|结果| T2 --> OE
W1 & W2 -->|状态| T3 --> OE
W1 & W2 -->|写| T4 --> BB
BB -->|变更通知| T4 --> W1 & W2
W1 & W2 -->|错误| T6 --> OE
OE -->|验证请求| T1 --> W3
W3 -->|验证结果| T2 --> OE
Loading
Human-in-the-Loop
sequenceDiagram
participant W as Worker
participant O as Orchestrator
participant UB as User Bot
participant U as 用户
W->>O: hitl.request (需要人类决策)
O->>O: 保存轻量快照
O->>UB: 推送通知
UB->>U: "任务 X 需要你确认: ..."
alt 用户在超时前回复
U->>UB: 回复
UB->>O: hitl.response
O->>W: 恢复执行
else 超时
O->>O: 执行 on_timeout 策略
Note over O: conservative: 最安全选项<br/>skip: 跳过子任务<br/>fail: 标记失败
end
Loading
背景
Memoh 是一个多用户 AI Agent 平台——用户创建 Bot,Bot 通过进程内 Agent Runtime + workspace/container 能力处理来自 Telegram、Slack 等聊天平台的请求。每个 Bot 拥有持久化的文件系统、记忆、技能和身份。
当前架构更准确地说是 一个进程内 Agent Runtime + 多个 Session 上下文 + 一个 Bot Workspace 容器。Bot 可以通过
spawn并行创建 subagent session,但这些 subagent 复用同一个 Agent Runtime,默认也复用同一个 Bot 的 workspace container。它们是 session 级并行,不是独立的 worker runtime。这在处理简单请求时足够。但有一类任务正在变得越来越重要:
这类任务的共同特征是:需要任务级分解、隔离执行环境、结构化协作、持续验证和可恢复的控制流。 当前的
spawn模型无法满足——它没有任务图、没有独立 worker 生命周期、没有共享状态层、没有验证环节。现有实现已具备 watchdog、超时和重试等单子任务保护,但还没有任务级的错误恢复、重规划和编排控制。Memoh 已有 Agent Runtime、Tool Loop 和 workspace/container 基础设施。缺的是面向复杂任务的编排层:任务模型、worker 模型、调度器、共享状态和事件流。
目标
核心目标
在 Memoh 现有 User Bot 架构之外,引入一个 task-oriented orchestration subsystem,将复杂任务动态分解为 DAG,调度多个 task-scoped worker 在隔离环境中执行,并在执行过程中持续验证和自适应调整。
具体而言:
约束
非目标
方案
总体架构
graph TB subgraph 用户侧 U[用户] -->|聊天/命令| UB[User Bot] end subgraph Server 侧 UB -->|消息流| AR[Agent Runtime] AR -->|orchestrate tool 调用| OE[Orchestrator Engine] OE -->|管理| NATS[NATS 消息总线] OE -->|读写| BB[Blackboard] OE -->|创建/销毁| DK[Worker Runtime Manager] NATS --- BB end subgraph Worker Runtime / 执行环境 DK -->|分配任务 + 绑定 env| W1[Worker: Researcher] DK -->|分配任务 + 绑定 env| W2[Worker: Coder] DK -->|分配任务 + 绑定 env| W3[Worker: Verifier] DK -->|分配任务 + 绑定 env| W4[Worker: Phone Operator] end W1 -->|pub/sub| NATS W2 -->|pub/sub| NATS W3 -->|pub/sub| NATS W4 -->|pub/sub| NATS OE -->|结果回传| UB编排以 异步 tool 暴露给 User Bot。User Bot 所在的 Agent Runtime 调用
orchestrate(prompt | status | cancel)后异步返回 task_id,Orchestrator 在后台完成分解、调度、执行、验证,最终将结果回传。任务图模型
任务图在任一时刻为 DAG。 逻辑上的迭代(Maker-Checker 循环、Debate 等)通过 Orchestrator Re-plan 动态追加节点实现,图内不存在环。这保证调度只需拓扑排序,无死锁风险。
调度规则:入度为 0 的节点并行执行,完成后减少后继入度,新的入度为 0 的节点继续执行。
分层 Blackboard
每个任务节点拥有独立的 Blackboard(NATS KV bucket
bb_{task_id}):访问规则:
任务生命周期
Orchestrator 采用迭代式规划(Plan → Execute → Observe → Re-plan),拆为四个独立模块:
模块 1 — 规划(Planner)
flowchart LR A[接收 prompt / 任务节点] --> B[LLM 标注任务特征] B --> C{需要分解?} C -->|是| D[生成子节点 + 依赖关系 → 构建子 DAG] C -->|否| E[标记为叶子节点 → 进入调度] D --> E输入:一个任务节点。输出:叶子节点(可直接执行)或子 DAG。任何层级的节点都可能触发规划,包括 Worker 运行中 request_decompose。
模块 2 — 调度(Scheduler)
flowchart LR A[接收 DAG] --> B[计算各节点入度] B --> C[入度=0 的节点 → 并行分发] C --> D[匹配 Worker 类型 → 分配 Runtime / Env] D --> E[Worker 开始执行] E --> F[节点完成 → 后继入度 -1] F --> G{新的入度=0 节点?} G -->|是| C G -->|否 + 仍有运行中| H[等待] G -->|否 + 全部完成| I[DAG 完成]核心是拓扑排序驱动的事件循环。每个节点完成是一个事件,触发后继的入度更新和可能的新调度。
模块 3 — 执行(Worker)
flowchart LR A[Worker 接收任务] --> B[读取 Blackboard: 自己 + 前驱 + Root] B --> C[执行] C --> D{结果} D -->|完成| E[写结果到自己的 Blackboard] D -->|需要再分解| F[request_decompose → 回到 Planner] D -->|env 不匹配| G[上报 → Orchestrator 换 Worker]Worker 是 task-scoped runtime。运行时上下文从任务定义和 Blackboard 读取,所有产出写回 Blackboard,并通过事件流上报状态。
模块 4 — 验证与错误处理(Verifier)
flowchart LR A[节点执行完成] --> B{验证方式} B -->|叶子节点| C[Verifier Worker 验证] B -->|中间节点| D[Orchestrator 聚合子结果验证] C & D --> E{通过?} E -->|是| F[标记完成 → 通知 Scheduler] E -->|否 + 可重试| G[指数退避重试 → 回到 Worker] E -->|否 + 需重写| H[Re-plan → 回到 Planner] E -->|否 + 不可恢复| I[标记失败 → 所有可达后继标记 blocked]失败处理三级:当前节点重试 → 当前节点 Re-plan → 失败传播(标记后继 blocked,由上层决定是否整体 Re-plan)。
模块间关系:
任务标签系统
Orchestrator 分解任务后为每个子任务标注特征标签,用于 Worker 匹配和调度策略:
通信:NATS + Blackboard
flowchart LR subgraph Orchestrator OE[编排引擎] end subgraph NATS Topics T1[task.assign.*] T2[task.result.*] T3[task.status.*] T4[bb.update.*] T5[hitl.request/response] T6[worker.error.*] end subgraph Workers W1[Worker A] W2[Worker B] W3[Verifier] end subgraph Blackboard BB[(共享状态)] end OE -->|分配| T1 --> W1 & W2 W1 & W2 -->|结果| T2 --> OE W1 & W2 -->|状态| T3 --> OE W1 & W2 -->|写| T4 --> BB BB -->|变更通知| T4 --> W1 & W2 W1 & W2 -->|错误| T6 --> OE OE -->|验证请求| T1 --> W3 W3 -->|验证结果| T2 --> OEHuman-in-the-Loop
sequenceDiagram participant W as Worker participant O as Orchestrator participant UB as User Bot participant U as 用户 W->>O: hitl.request (需要人类决策) O->>O: 保存轻量快照 O->>UB: 推送通知 UB->>U: "任务 X 需要你确认: ..." alt 用户在超时前回复 U->>UB: 回复 UB->>O: hitl.response O->>W: 恢复执行 else 超时 O->>O: 执行 on_timeout 策略 Note over O: conservative: 最安全选项<br/>skip: 跳过子任务<br/>fail: 标记失败 end