v3 是当前唯一可执行的 Workflow 引擎:LLM 驱动的有界 DAG,跑完即散。packages/workflow-core/ 是从 src/workflows/v3/ 生成的发布包(index.ts/schema.ts/engine.ts 均为一行 re-export),保证外部运行时与 botmux 内部不会分叉出两套 DAG 语义。v2(src/workflows/definition.ts)已冻结,只留给 migration/ 做离线迁移;仓库根 workflows/*.workflow.json 是 v2 时代示例。
DAG 定义格式(dag.ts)
V3Dag = { runId, nodes[] },runId 与 nodeId 都是路径安全段([A-Za-z0-9._-]),因为它们直接做 runDir 的路径段。三种节点(V3NodeType):
- goal — LLM 节点,由 botmux-goal skill 驱动,一个临时 worker 跑一个目标;
goal字段是单句目标。 - host — 确定性副作用节点,不经 LLM,调注册在
hostExecutors/registry.ts的执行器:feishu-send/feishu-reply/botmux-schedule。 - loop — 有界子流水线(结构化返工,如 code→test 直到 test 通过);外层 DAG 保持无环,返工只存在于显式 loop 体内。
节点字段要点(V3Node):
depends:入边,可写字符串或{from, when?};when是对源节点 resultSchema 结构化结果的谓词(equals/notEquals/gt… 单算子),校验时即与源 schema 的 enum 交叉检查,运行时只读一次result.json并记edgeResolved。triggerRule:入边汇合语义,all_success(默认)/one_success/{quorum: n},所有入边 settle 后一次性求值。inputs:{from, select?}把上游节点的 manifest 产物喂进本节点inputs.json,from必须 ⊆ depends。timeoutSec:默认 1800s,上限 14400s(防架构节点幻觉出失控预算)。humanGate:创作期冻结的人工审批门(prompt/options/approvers),运行时不允许增删。resultSchema:刻意极小的 JSON-Schema 子集(平铺对象、原始类型、≤32 属性 / ≤4KB),节点须写result.json,违反会 block(非 fail)。revisitTo:跨节点回溯白名单,只允许回溯祖先;预算 per-pair 默认 1、per-run 默认 8,耗尽后 block 等人工 +1。bot/override:每节点可指定 bot 与能力覆盖(仅 model、systemPromptAppend,权限不可覆盖)——混合后端 DAG 是非破坏性扩展。- loop 专属:
maxIterations(硬上限 20)、body(仅 goal 节点、不可嵌套)、exit.when、feedback(上轮产物穿线)、output.from(对外产物投影)。
validateDag 是纯函数,一次抛出全部问题(DagValidationError.problems[]);环检测委托 topologicalOrder(含条件边)。
决策与执行分层
orchestrator.ts是纯决策层:decideNext(runState, dag)→ 动作描述列表。节点状态机:pending / gateWaiting / running / done / skipped / cancelled / blocked / superseded / failed。runtime.ts拥有全部副作用:journal/STATE 写入、worker 派发、humanGate 卡片投递、并发上限。ephemeral-pool.ts:一次runNodefork 一个用完即弃的 worker,以 goal-mode 初始化(GOAL_COMMAND = '/goal'),不解析不信任模型最终文本——节点成败由校验BOTMUX_GOAL_MANIFEST_PATH指向的 manifest 决定;worker-fence.ts做 attempt 围栏。- host 节点走
host-execution.ts:冻结输入 → 人工门批准 → 执行器调用,带幂等键与对账(reconciler)。
状态真相:journal + STATE 两层
journal.ts:journal.ndjsonappend-only 审计真相(带跨进程锁与断尾修复);state.ts:materialize(events)把 journal 折叠成V3RunSnapshot(runStatus: running / cancelling / cancelled / succeeded / failed / blocked),STATE文件只是可随时重放的检查点——daemon 重启后靠重放 journal 恢复。
与飞书话题 / 多 bot 的结合
RunChatBinding(grill-state.ts)在 run 出生时从 grill worker 注入的环境捕获larkAppId / chatId / rootMessageId / sessionId并持久化:daemon 重启后 cold-attach 凭它知道把 humanGate 审批卡片重新发到哪个话题(见 cards)。chatBinding同时钉进不可变的 run.json,是 dashboard 路由取消等变更到 owner daemon 的依据(见 dashboard)。- host 执行器 feishu-send / feishu-reply 把结果发回飞书会话,botmux-schedule 建定时任务(见 schedule);host 节点强制携带 humanGate。
- 每节点
bot字段由bot-resolve.ts解析成BotSnapshot,支持一个 DAG 混合多个机器人/CLI(见 multi-bot)。
run 生命周期
- grill 前置阶段(
grill.state.json):grilling → spec_ready → spec_approved → architect_running → dag_ready → dag_approved;两个人工门(gate-1 确认需求、gate-2 确认 DAG)。 spec.ts从 spec.md 唯一的 ```json 块抽出 canonical Spec;architect.ts起一个自主 goal-worker 把 spec 编译成dag.json。run-envelope.ts:run.json是不可变的授权/身份边界,create-once;所有产物(dag.json、spec.json、bots.snapshot.json 等)按 SHA-256 钉死,防止”批一个 DAG、跑另一个”。来源四种:ad_hoc / saved_definition / manual_cli / legacy_v3。daemon-run.ts的driveV3Run驱动执行;requestV3RunCancel / requestV3Retry / requestRevisitGrant / requestV3LoopGrant / resolveV3GateClick是 CLI 与卡片回调共用的变更入口。- CLI 面:
botmux workflow new/spec-finalize/approve-spec/architect/approve-dag/start(即兴流程)、save/run/list/show(Saved Workflow)、cancel/retry/grant(受阻处理);botmux goal run(goal-cli.ts)是不经 daemon 的单 goal 本地入口,复用同一套 envelope/journal/manifest 校验。
存储位置
- run 目录:
~/.botmux/v3-runs/<runId>/(cli-run.tsdefaultBaseDir),内含 run.json、dag.json、spec.json、grill.state.json、journal.ndjson、STATE、各节点 manifest 与 pty-log。 - Saved Workflow 库:
<dataDir>/workflow-library/<workflowId>/(library-store.ts,dataDir 默认~/.botmux,可经 SESSION_DATA_DIR 覆盖,见 env):metadata.json— 可变小索引:displayName/aliases/owner(openId+larkAppId)/scope(chat|global)/status(draft|active|archived)/latestRevision/publishedRevision;写更新加锁+原子。revisions/rev_*.json— 不可变、内容寻址(sha256),payload 含 inputs 参数定义、contextRefs、specTemplate、dagTemplate、safety(gateDigest 防审批门被静默削弱 + sideEffects 清单)。- id 形如
wf_<32hex>/rev_<64hex>(library-schema.ts);store 从不回退 HOME/cwd 旧搜索路径,与 v2 的~/.botmux/workflows/*.workflow.json彻底隔离。
相关页面:workflow、architecture-overview、daemon-worker、skills(botmux-goal skill 注入)。