Files
maka/docs/architecture/agent-graph-stream-scheduling-draft.zh-CN.md
T
agent-radar 7be535059e
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 19:05:14 +08:00

36 KiB
Raw Blame History

doc_id, title, language, source_language, counterpart, implementation_status, document_status, translation_status, last_verified, owners
doc_id title language source_language counterpart implementation_status document_status translation_status last_verified owners
architecture.agent-graph-stream-scheduling 第七章:Graph 是调度,不是第二套 Runtime——主 Agent 监督下的流式 Agent Work zh-CN zh-CN ./agent-graph-stream-scheduling-draft.md current draft synced 2026-08-23
maka-backend

第七章:Graph 是调度,不是第二套 Runtime——主 Agent 监督下的流式 Agent Work

本章回答一个问题:Maka 如何把相互依赖、运行中动态展开的 Agent work 组织成图,同时不再发明一套 Agent runtime?Maka 把每个 child Session 视为 operator 容器,把每次 Session-inline AgentRun 视为 activation,把每个已提交 RuntimeEvent 视为 reference-only stream record。SQLite control plane 保存 topology、schedule intent、admission 和 supervisor wake;已有的 Session 与 Runtime ledger 继续拥有运行事实。主 Agent 始终在图旁担任 supervisor:它观察和修改 schedule,但正常 record delivery 不等待它批准。Graph 是建立在 Runtime 事实之上的持久调度,不是第二个运行宇宙。

本章直接建立在第一章之上。Runtime Event Log 仍然是“Agent 实际做了什么”的语义 authority。Graph 只是增加了一组 identity 和 projection,用来回答另外几类问题:哪个 child Session 是一个 operator、哪些已提交 record 会流向另一个 operator、supervisor 请求了哪些 work、哪个 intent 被精确 admission 一次,以及何时应该唤醒 root Agent 检查一个稳定 checkpoint。

本文面向修改 Graph contract、child Session、调度、恢复或 Desktop 接线的工程师,描述截至 2026-08-23 已验证的实现。它不描述任意有环 workflow、分布式执行、图级资源优化,也不把当前实现说成可视化 workflow authoring system。

从运行中才逐渐显形的工作开始

假设用户让 Maka review 一个跨层改动:

  1. 一个 specialist 检查 Runtime invariant;
  2. 另一个 specialist 检查 storage 与 recovery;
  3. 两者提交的 findings 暴露出还需要一次 Desktop 检查;
  4. 主 Agent 再让一个 synthesis specialist 对比选中的 findings;
  5. 主 Agent 读取权威 child output,并选择最终 result records。

这不只是一个 batch。后续 work 依赖前面产生的事实,而且有用的 topology 在一开始并不完全已知。但这也不是替换 Agent loop 的理由:每个 specialist 仍然需要普通的 model/tool loop、permission、history、context compaction、usage accounting、stop、recovery 和 inspection。

因此真正有用的抽象是:

child Session              → operator 容器
Session-inline AgentRun    → operator activation
已提交 RuntimeEvent        → immutable stream record
record 沿 edge 可见         → route
确定性的 input state       → readiness intent
持久 admission row         → exactly-once execution identity
supervisor schedule update → control-plane decision

Graph layer 只协调这些既有对象,不复制它们。

先说结论

当前设计建立在六条边界上:

  1. Runtime 继续拥有执行 authority。 Graph 不引入 GraphRun event ledger,也不复制 model/tool loop。
  2. 持久 child Session 是 operator 边界。 后续 activation 复用它的 runtime snapshot、history、lifecycle、usage 和产品 identity。
  3. 只有已提交 RuntimeEvent 才能成为 Graph record。 partial chunk 和进程内 callback 永远不是持久 dataflow fact。
  4. Readiness 是确定性 projection,admission 是 SQLite decision。 重算 runnable intent 不会把同一工作执行两次。
  5. 主 Agent 在 data path 旁监督。 observation callback、Desktop invalidation 和 supervisor turn 可以失败或重试,但不能阻塞 record projection。
  6. Schedule closure 与 runtime quiescence 是两回事。 “此刻没有 runnable work”不等于“supervisor 已完成 Graph”。

这些边界让 Graph 直接复用 Maka 已经解决的困难部分:Session 创建与生命周期、AgentRun identity、RuntimeEvent 持久化、permission、context compaction、child-output inspection、usage 和 tool activity、Desktop conversation component,以及重启恢复。

Identity 模型

Graph 有意保留多种 identity,而不把它们压扁成一个泛化的“node status”。

Identity 含义 持久 authority
Root Session 用户面对的会话,其主 Agent 监督 Graph Session store
Graph 由一个 root Session 派生的调度 namespace SQLite Graph control plane
Work 一条 supervisor instruction 与 input frontier Schedule update log
Operator 到一个 child Session 的稳定 Graph binding Operator provision
Child Session 一个 operator 可复用的执行与产品容器 Session store 与 metadata control plane
Activation 该 operator 的一次 Session-inline execution AgentRun
Turn / Run Child Session 内精确的输入与执行 identity Session 与 AgentRun ledger
RuntimeEvent canonical semantic execution fact Runtime Event Log
Record 引用一个已提交 RuntimeEvent 的有界 Graph projection 可重建 projection
Route Record 沿一条 direct edge 对下游可见 可重建 trace projection
Readiness intent 由 route 和 policy 确定性派生的候选 可重建 readiness projection
Claim 把一个 intent 持久 admission 到精确 Session、Turn、Run SQLite Graph control plane
Supervisor wake 请求运行一次 root-Agent checkpoint turn SQLite Graph control plane

最重要的层级是:

root Session
└── graph
    ├── schedule revisions
    ├── operator
    │   └── child Session
    │       ├── activation / AgentRun
    │       │   └── committed RuntimeEvents → graph records
    │       └── later activation / AgentRun
    ├── operator
    │   └── child Session
    └── admission claims and supervisor wakes

Operator 不是 AgentRun。稳定的 operator-to-Session binding 才让 follow-up 自然成立:Session 保持不变,每次 activation 获得新的 Turn 与 Run identity。

同一套 Runtime 上的两个 plane

最容易理解当前实现的方法,是把它看成 data plane 旁边的一层 control plane。

flowchart LR
    U["User"] --> M["Root Session<br/>Main Agent supervisor"]

    subgraph CP["SQLite Graph control plane"]
        S["Schedule revisions<br/>add / stop / replace / finish"]
        T["Monotonic topology<br/>operator provisions"]
        C["Intent claims<br/>admission state"]
        W["Supervisor wakes<br/>delivery attempts"]
        RM["Bounded client projection"]
    end

    subgraph DP["Existing Session / Runtime data plane"]
        O1["Operator A<br/>Child Session"]
        O2["Operator B<br/>Child Session"]
        A1["AgentRun activation"]
        A2["AgentRun activation"]
        L1["Runtime Event Log"]
        L2["Runtime Event Log"]
    end

    M -->|"view / update tools"| S
    S --> T
    T --> O1
    T --> O2
    C --> A1
    C --> A2
    O1 --> A1 --> L1
    O2 --> A2 --> L2
    L1 -. "reference-only records and routes" .-> RM
    L2 -. "reference-only records and routes" .-> RM
    RM --> W
    W -->|"new root turn"| M

Control plane 与 data plane 之间的箭头都是 typed boundary:

  • provision 把 child Session relation 与 operator metadata 原子创建;
  • claim 在执行前,把确定性 intent 绑定到预分配的 Turn 与 Run identity;
  • Runtime 通过普通的 Session-inline child path 执行;
  • observation 把 immutable RuntimeEvent fold 回 Graph record 与 client projection;
  • durable wake 在有价值的 checkpoint 后启动一次普通 root Session turn。

任何 Graph callback 都不会成为 model output、tool result 或 terminal state 的 owner。

为什么 child Session 是 operator 容器

较早的 child-agent 设计可以把执行直接放在 parent Session 下,只用一个 child AgentRun 区分它。这足够支撑短暂的 foreground call,却不是长寿命 Graph work 的良好 operator 边界。

Linked child Session 可以自然复用:

  • Session 创建、停止、归档与恢复;
  • 冻结的 subagent runtime snapshot,包括 profile、system prompt、tool surface 和 permission ceiling;
  • 后续 follow-up 所需的多次 Session-inline AgentRun;
  • RuntimeEvent 与 message 持久化;
  • context 构造与 compaction;
  • usage、tool activity 与 artifact accounting;
  • Desktop 与 TUI 的会话检查组件;
  • 基于精确 child Session 和 current Run 的 agent_output;
  • 未来通过同一 Runtime host 实现的多 client 观察。

Child 会持久保存回到 root 的 lineage:

parentSessionId
spawnedBy.parentRunId
spawnedBy.parentTurnId
spawnedBy.toolCallId
graph.graphId
graph.workId
graph.operatorId

Parent 不需要维护可变 child ID 数组。反向查询与 Graph topology 是 read-model concern。Cross-Session provenance 也不会塞进 AgentRun.parentRunId,所以 child Session 内的 Runs 仍然保留普通 Session-inline history semantics。

从 RuntimeEvent 到 stream record

Projection,而不是复制

readCommittedAgentGraphProjection() 读取每个 operator binding 的 immutable RuntimeEvents,产生有界的 AgentGraphRecord。Record 携带 identity、order、facet、supervisor signal,以及到 source Session、Run、RuntimeEvent 的引用;它不复制完整 message、tool arguments 或 tool result payload。

这层分离带来几个结果:

  • Graph 可以用小而稳定的值做 route 与 schedule;
  • 权威 child output 仍留在 Runtime ledger;
  • access control 与 archive 继续附着在原始 resource 上;
  • read model 不会悄悄变成竞争性的 event store。

主 Agent 需要读取某个 candidate record 背后的真实答案时,使用 operator 的 childSessionId、currentRunId 和 view=result 调用 agent_output。这个投影只返回 最终已提交的模型文本、对应的 Graph result/terminal record ID,以及有界的 artifact 引用。原始 Runtime events 仍可用于显式诊断,但不再属于 supervisor 的正常数据路径。

Commit 是 stream boundary

只有 non-partial、immutable RuntimeEvent 才进入 Graph projection。Provider chunk 与已 yield 的 SessionEvent 可以更新 best-effort client view,但不是 Graph fact。Terminal history 只由 authoritative RuntimeEvent fold 写入,因为 stop race 仍可能在 Runtime durability barrier 把已 yield 的 completion 改写为 aborted terminal fact。

规则是:

只有当 Runtime 已提交 Graph 所引用的 semantic event,该事实才能进入 Graph。

Record facet 与 signal

Record 暴露有界 facet,例如 message、thinking、error、tool call、tool dispatch、tool result、artifact update、permission request、permission decision、user-question request、transfer、usage、completed、failed、aborted、cancelled 和 generic runtime fact。

同一 record 还可以带 attention 或 terminal 等 supervisor-facing signal。它们是同一 record identity 上的 meta-stream,不是第二份事实。Supervisor signal 不能改变下游 operator 收到什么。

稳定 replay 顺序

Record 使用确定性的 total order:

  1. event time;
  2. Run creation time;
  3. operator identity;
  4. Run identity;
  5. committed event ordinal;
  6. RuntimeEvent identity;
  7. record identity。

每个 activation 还链接前一个 record。Replay 验证每个 activation 只有一次 terminal transition,并拒绝终止后的 record。因此重启后可以从 Runtime ledger 重建 projection,而不把 callback arrival order 当成 authority。

Topology 与 routing

Existing operator binding 组成的 DAG

Trace topology 包含 operator 与 directed edge。校验会拒绝缺失 operator、self-loop、重复 endpoint 和 cycle,再派生确定性 topological order。

对每个已提交 source record,trace projection 都会在每条 direct outgoing edge 上创建 reference-only route。Edge 只拥有 visibility,不拥有 readiness policy。下游 adapter 决定一条 visible route、一个 settled activation frontier,还是 supervisor 显式选择,足以启动 work。

动态 topology 只做 monotonic add

当前产品路径支持单调增加:

  • agent_id work provision 一个新 child Session 与新 operator;
  • operator_id work 在已有 operator 上创建后续 activation;
  • input record 的 producer 决定新 operator 的入边;
  • provision、child Session、initial Turn 和 initial Run identity 都被确定性预分配;
  • retry 要么观察到已有 provision,要么只创建一次。

首版不支持任意删边、删点、rewire 或 cycle。Supervisor 可以 stop 或 supersede work,但历史 topology 与事实保持可解释。

Readiness 不是 admission

可复用 Runtime primitive 定义了两种 policy projection。

map

map 对 operator 可见的每条 routed record 产生一个确定性 intent。没有 input route 时,operator 报告 input_route wait。

all_settled

all_settled 为每个 direct upstream operator 指定一个 immutable activation。它等待 activation 出现并结束,然后在 sealed inputs 上产生一个 intent。

显式 activation frontier 很关键。如果同一个 child Session 后来执行 follow-up activation,新 Run 不能悄悄改变已声明 join 的含义。

两种 policy 都只产生确定性 intent ID 与 readiness-context fingerprint,不启动 Runtime work。Supervisor 可以观察相同的 waiting/runnable projection,但 readiness 派生过程不需要它批准。

当前 Desktop host profile 默认不安装自动 map 或 all_settled policy。主 Agent 通过 add_work 与已提交 input_ids 显式推进动态图。Policy primitives 可以被其它 host adapter 使用,而不需要修改 execution runtime。

Supervisor schedule

Graph Mode 只给 root Agent 一组紧凑 control surface:

  • view_agent_graph 读取持久 schedule state、runtime state、readiness、wait 与有界 recent activity;
  • update_agent_graph 追加一条 idempotent schedule decision,包含 add_work、stop、finish 或允许的组合;
  • agent_output 读取选定 child Session Run 的权威输出。

Child Session 永远不会获得 Graph supervisor tools。

Revision-linearized intent

每条 schedule update 记录:

  • source root Session、Run、Turn 和 tool call;
  • stable update identity 与 fingerprint;
  • 零到多个 work addition;
  • 零到多个 stop decision;
  • 可选 finish decision;
  • 严格递增的 Graph revision 与 commit time。

SQLite 拥有 revision order。同 source 与内容的 tool retry 是幂等的;冲突 identity reuse 会失败,而不是产生含糊 control history。

Work 与 input frontier

一个 work item 只会指向 catalog agent_id 或已有 operator_id 之一,并携带 instruction、已提交 input record IDs,以及可选的被替换 work 或 activation。

Input IDs 不是复制出来的 prompt,而是 durable frontier。默认 scheduled prompt 只携带有界 record reference——record、operator、activation、facet 与 RuntimeEvent source——不会复制 upstream payload。Host 可以提供其它 prompt renderer。真正需要 semantic source content 的 work,必须把内容写入 instruction,或使用显式授权的 Runtime retrieval path;edge 本身不授予 cross-Session payload access。

Stop、replace 与 finish

Stop 可以指向 work 或 activation。尚未 admission 的 work 变成 cancelled;正在执行的 child Session 通过普通 Runtime stop path 停止;已终止执行继续作为历史事实存在。

replaces 显式表达 supersession,而不是修改旧 work row。

finish 选择已提交 Graph record IDs,并关闭 fresh admission。它不能与新 work 同时提交。已经 claim 的 work 仍然可恢复,因为 closure decision 不能把一个已经持久 admission、拥有精确 Run identity 的执行遗弃。

先 claim,再执行

Readiness 与 schedule reconciliation 可以重复计算很多次。Exactly-once execution identity 来自 claim protocol:

  1. 计算确定性 intent 与 readiness-context fingerprint;
  2. render 并 fingerprint execution prompt;
  3. 预分配 target operator、child Session、Turn 与 Run identity;
  4. 在 expected schedule revision 上 conditional claim;
  5. conditional 把 admission 从 claimed 推进到 executing;
  6. 调用已有 Session-inline child execution primitive;
  7. 一旦 Run 存在,就以 AgentRun 与 RuntimeEvent ledger 为 authority。

如果 Run 创建后进程重试,runClaimedAgentGraphIntent() 会检查或恢复那个精确 Run,不会再次调用 provider。Claim 只是 admission authority,不与 Runtime terminal fact 竞争。

Child Session 会串行化自己的 claimed Graph activation。不同 operator 可以并发,同一 Session 的两个 activation 仍遵守普通 per-Session order。

Reconciliation:推进到 quiescent,再请 supervisor 判断

Host coordinator 为每个 root Graph 维护一个进程内 single-flight driver。持久 row,而不是这个内存 driver,仍然是 restart authority。

一次 reconciliation 会:

  1. 读取 schedule revision、provision、claim、AgentRun 与已提交 RuntimeEvent;
  2. 重建 monotonic topology 与当前 observation;
  3. 应用 stop 与 supersession decision;
  4. 为尚无 operator 的 catalog-agent work 做 provision;
  5. 解析 scheduled work 与已配置 readiness intent;
  6. 拒绝或 defer 未提交 input;
  7. 在当前 revision 上 claim 并 begin eligible activation;
  8. 通过 child Session 并发 dispatch 不同 operator;
  9. fold 新 RuntimeEvent,并重复直到 quiescent、cancelled、stale、failed 或达到 activation bound。
stateDiagram-v2
    [*] --> Observe
    Observe --> ApplyControl
    ApplyControl --> Provision
    Provision --> Resolve
    Resolve --> Claim: eligible intent
    Resolve --> Quiescent: no eligible intent
    Claim --> Execute
    Execute --> Observe: RuntimeEvent committed
    Quiescent --> WakeSupervisor: useful dispatch or failure
    WakeSupervisor --> Observe: supervisor adds work
    WakeSupervisor --> Closed: supervisor finishes
    Closed --> [*]

Quiescence 只描述当前事实与 policy:此刻没有更多 activation eligible。它不表示用户任务完成。只有持久 finish update 才会关闭 fresh Graph admission。

Structural reconciliation 也不拥有 resource permit 或 global fairness。Shared child-run capacity、provider backpressure 与 cross-Graph priority 属于 dispatcher 外围的 host admission layer。

主 Agent 始终在图旁

主 Agent 既不是每条 record 必经的 node,也不是 child execution 内部 callback。它是 external supervisor,承担三类职责:

  1. **Observe:**检查紧凑 schedule、topology、operator state、wait、failure 与 candidate result record。
  2. **Control:**添加 dependent work、follow up 已有 operator、stop/replace 失去价值的 work,并关闭 schedule。
  3. **Synthesize:**读取权威 child output、选择已提交 result record,并回答用户。

这个位置同时保留自治与响应性。Operator 可以按照持久 control decision 推进,root Agent 仍然是普通 conversation participant。用户可以通过 host 观察或停止 Graph,而不把 supervisor 变成 data-delivery bottleneck。

Observer callback 只用于 presentation,并且 fire-and-forget。损坏的 Desktop listener 或 supervisor observation hook 不能让 operator activation 失败。

持久 supervisor wake

一个有用 checkpoint 即使没有新的用户消息,也必须最终把主 Agent 带回来。因此 host 会在 SQLite 中持久保存 supervisor wake。

Wake 状态流转为:

pending → running → delivered
                  ↘ waiting_permission
                  ↘ retryable_failed → running

每次 delivery attempt 都预分配 root Turn identity,并以 agent_graph origin 启动一次普通 root Session turn。Prompt 要求主 Agent inspect Graph,在需要时读取 child output,然后继续 schedule 或 finish。

“Prompt 已持久化”不等于“wake 已 delivered”。只有 host 观察到 root AgentRun completed,delivery 才完成。Permission suspension 会被显式 parked。重启后,wake coordinator 会对比 stored attempt 与 AgentRun fact,把被中断 attempt 标记为 retryable,只恢复安全的 delivery。

Context overflow 与普通 transient failure 分开处理。Host 会记录 overflow diagnostic, 最多执行一次 aggressive compaction,并在可用时报告压缩前后 token 估算与 dropped event 数量。若第二次仍 overflow,会立即返回有界的 durable partial result;不会带着完全相同的 超长 context 再做第三次重试。

Session activity registry 会把这个 host-created turn 与其它 root Session activity 串行化。多个 client 可以观察同一个持久 Session 与 Graph state,但不会成为 scheduler owner。

Persistence 与 authority

Graph 把 SQLite 用作 workspace/session metadata control plane,而不是 transcript 或 Runtime ledger 的替代品。

数据 Authority 原因
Child Session 配置与 parent relation Session storage 加 metadata transaction 产品 identity 与冻结 runtime snapshot
Agent execution lifecycle AgentRun ledger 精确 Turn/Run state 与 terminal semantics
Message、tool、permission、usage、terminal fact Runtime Event Log Canonical interaction facts
Schedule revision SQLite 有序、幂等的 supervisor control decision
Operator provision 与 topology relation SQLite 原子的 child Session/operator identity
Intent claim 与 admission state SQLite Revision-linearized exactly-once admission
Supervisor wake 与 attempt SQLite 可恢复的 root-turn delivery
Graph record、route、readiness、replay timeline 确定性 projection 建立在持久事实上的可重建 view
Desktop snapshot 与 terminal activity page SQLite materialized read side 有界、高效的 client read

权威 schedule、provision、claim 或 wake 操作发生 SQLite failure 时应直接报错。Coordinator 不会扫描 JSONL 来替代 Graph control plane。

Materialized Desktop projection 不同:它是 derived state。Incremental projection commit 可以失败,而不影响 Runtime 或 schedule authority。Coordinator 会把 projection 标记为 dirty,在 reconciliation 边界做 best-effort rebuild,并在 client read 前再次 repair;成功 rebuild 后才清除 dirty state。

三个 status plane 不能压扁

Client 可能同时观察到:

work.status                       = requested
claim.admissionState              = executing
operator.currentActivation.status = completed

这不是矛盾。

  • Work status 记录 supervisor intent,以及它是否被 stopped 或 superseded。
  • Claim admission 记录某个确定性 intent 是否已 admission 或 cancelled。
  • Activation status 记录 Runtime 实际发生了什么。

把三者压成一个 generic node state 会抹掉因果。Bounded client read model 可以派生 presentation status,但仍保留 work、claim、control decision 与 Run reference 供检查。

重建一条 replayable Graph timeline

Graph 还可以跨 control plane 与 data plane 重建一条统一的 reference-only timeline。getTimeline() 会 join:

  • 一份 transactionally consistent SQLite snapshot,其中包含 schedule update、operator provision、current admission,以及 supervisor wake 与 attempt;
  • 创建 schedule decision 或执行 wake turn 的 root Session AgentRuns;
  • 每个 provisioned operator 的 committed child RuntimeEvent projection。

可分页 event stream 覆盖 supervisor-turn start/termination、schedule commit/finish、operator provision、intent claim、activation start、committed record、activation terminal、wake claim、wake attempt 和 wake settlement。Response 会在 page-level currentState 中单独返回 current admission 与 wake state;这些 mutable snapshot 不是携带 cursor 的 historical event。

Timeline event 有意不暴露 schedule instruction、finish reason、child message content 或 tool payload,只保留回答以下问题所需的 ID、facet、source RuntimeEvent reference 与 Run coordinate:

  • 哪个 supervisor turn 创建了这项 work?
  • 哪个 operator 和 child Session 接收了它?
  • 哪个精确 activation 产生了 candidate record?
  • Graph 是否在 final schedule decision 前唤醒了 supervisor?

重建顺序先按 event time,再按稳定 event-kind rank 与 type-specific identity tie-break 排序。公开的 sequence 是 deterministic reconstruction order,不表示 SQLite 与 Runtime ledger 共享一个物理 commit sequence。同一毫秒内的 Runtime record 保留 committed ledger order。

每页默认 100 个 event,上限 256。Opaque cursor 绑定 Graph、event identity 与 event time;页面同时报告 total event、前置 omission 与后置 omission。

Coverage 会被显式报告,而不是靠读者猜测。对于本次读取的 immutable ledger,Runtime record 是 complete 的;但当前 SQLite schema 只保留最新 admission state 与最新 wake state,不保留每个被覆盖的 transition。Reconciliation-loop iteration 也没有作为历史 event 持久化。Timeline 会报告全部三项限制:

admission_transition_history_not_persisted
supervisor_wake_transition_history_not_persisted
reconcile_history_not_persisted

因此 timeline 可以 replay、可以用于诊断,却不会冒充新的 authority。每个 event 都能指回真正拥有 underlying fact 的 store。

Client 访问与 Desktop 产品接线

Runtime Host 通过有界的 agent.graph.query 与 agent.graph.operator.query operation 暴露持久化 Graph projection。Client 通过 agent.graph.stop 显式控制 Graph;关闭连接或 Session subscription 永远不会停止 Graph。需要一致 live view 的 client,应先为 root Session 建立 subscription,再执行首次 query。此后,subscription.agent_graph_changed 与 Session update 共用该 subscription 的有序 sequence,并通知 client 重新查询 projection。它只是 invalidation hint,不是 replay log,也不是第二套 source of truth。Query result 通过 omitted data 与 continuation cursor 表达边界,而不会无限增长。

Desktop 组合了当前 host-managed Graph profile:

  • Graph 可以是 Session orchestration mode,也可以是 one-turn override;
  • /graph on、/graph off 与 /graph <task> 暴露这些选择;
  • 只有 root Session 获得 view_agent_graph、update_agent_graph 与 agent_output;
  • Electron main 拥有 coordinator、wake coordinator、SQLite store、Runtime adapter 与 startup recovery;
  • renderer IPC 只暴露 bounded snapshot、operator inspection、stop 与 invalidation hint;
  • Agent Graph panel 展示 aggregate state、visible operator、wait、selected result,并可打开 child Session;
  • Stop Graph 会 abort reconciliation,并通过 Runtime 停止已知 child Session;
  • Startup 先 repair interrupted Runtime state,再恢复 wake 与 Graph schedule。

Renderer invalidation 遵循同一契约。重新连接的 client 会重新查询持久化 projection,不把进程内 notification replay 成事实。

当前 panel 是 operational view,不是 node-and-edge authoring canvas。主 Agent 仍通过 typed schedule update 编写 topology。

End-to-end sequence

sequenceDiagram
    participant U as User
    participant M as Main Agent
    participant SQL as SQLite control plane
    participant G as Graph coordinator
    participant CS as Child Session operator
    participant R as AgentRun / RuntimeEvent log
    participant D as Desktop read model

    U->>M: Graph-mode task
    M->>SQL: update_agent_graph(add_work)
    SQL-->>G: durable schedule revision
    G->>SQL: provision operator + child Session relation
    G->>SQL: claim intent with Turn/Run IDs
    G->>CS: run claimed activation
    CS->>R: ordinary model/tool execution
    R-->>G: committed RuntimeEvents
    G->>D: materialize records and operator state
    G->>SQL: claim supervisor wake at checkpoint
    SQL-->>M: host starts root supervisor Turn
    M->>G: view_agent_graph
    M->>R: agent_output(child Session, Run)
    M->>SQL: add dependent work or finish(result record IDs)
    SQL-->>D: closed schedule and selected results
    M-->>U: synthesized answer

注意 child result 不经过 supervisor callback 传输。Runtime 先提交它,Graph 再 projection 出一个引用;主 Agent 随后决定是否以及何时读取权威 payload。

Failure 与 recovery invariant

当前实现保护这些 invariant:

  • schedule update append-only、按 revision 排序,并按 source identity 幂等;
  • operator provision 单调且 retry-safe;
  • provisioned operator 永远解析到同一个 linked child Session;
  • 一个 intent 最多对应一个 claim 与精确 Turn/Run identity;
  • 已存在的 claimed Run 会被观察或恢复,不会盲目再次执行;
  • record 只引用已提交 non-partial RuntimeEvent;
  • callback 与 renderer failure 不能改变 Graph execution;
  • closure 阻止 fresh admission,但不遗弃 existing claim;
  • Graph stop 保留 durable schedule fact 与 historical Runtime fact;
  • startup recovery 从 SQLite control row 与 Runtime ledger 派生工作,而不是依赖内存 registry;
  • supervisor wake 只有在 root AgentRun completed 后才算 delivered;
  • derived client projection 失败后可以 rebuild,而不改变 authority。
  • replay timeline 不暴露 child 或 schedule payload,并显式报告不完整的 transition coverage。

这些 invariant 比任何单个 UI 或 prompt 的形状都重要。新的 host adapter 必须保留它们。

当前限制与 non-goal

当前 Graph 不能被误解为通用 distributed stream processor。

  • Topology 是只做 monotonic add 的 directed acyclic graph;任意 deletion、rewire 与 cycle 尚未实现。
  • Desktop 默认通过 supervisor schedule update 显式推进 dependent work,不会暗中推断自动 policy-driven topology。
  • map 与 all_settled 是 structural readiness primitive,不是完整 window、watermark、keyed state 或 backpressure system。
  • Structural scheduler 不拥有 global resource permit、fairness、provider rate limit 或 distributed lease。
  • Quiescence 不是 graph completion;finish 是显式 supervisor decision。
  • Read model 有界且 reference-only;完整 child content 必须走权威 Runtime read path。
  • Desktop panel 是 inspection 与 stop surface,不是 visual graph editor。
  • Coordinator 已暴露 paginated replay timeline,但 Desktop IPC 与当前 Agent Graph panel 尚未把它渲染成交互式 chronological visualization。
  • Admission 与 wake row 目前只向 timeline reconstruction 暴露 latest state,reconcile-loop history 也没有持久化。

这些都是有意保留的边界。它们让 Graph 有用,同时不把 workflow semantic、resource management 或 product presentation 塞进 Agent runtime。

Graph、Swarm、agent_spawn 与 Rive

四种机制解决不同的协调问题。

需求 机制 Ownership model
有限独立 fan-out,随后一次 synthesis Swarm 模式 主 Agent 把独立 item 排进同一张 Graph,并异步监督
一次 linked specialist execution 或 follow-up agent_spawn / child Session Parent Agent 显式拥有 delegation
从 root conversation 监督动态依赖 Agent work Agent Graph Child Session 与 Runtime record 之上的 SQLite schedule/control plane
显式 workflow step、任意 resume policy 或分布式 workflow authority Rive Workflow runtime 拥有 workflow state

Graph 位于 foreground fan-out 与独立 workflow runtime 之间:足够动态、持久,可以协调 dependent Agent work;同时 Session Runtime 仍是唯一 execution universe。

代码阅读地图

建议按以下顺序阅读:

  1. packages/core/src/orchestration.ts 与 graph-command.ts:Session 与 one-turn Graph mode。
  2. packages/runtime/src/graph-mode.ts:main-Agent supervisor contract。
  3. packages/core/src/agent-graph-schedule.ts:work、stop、finish、revision 与 store protocol。
  4. packages/core/src/agent-graph-topology.ts:monotonic operator provision。
  5. packages/runtime/src/stream-graph-projection.ts:RuntimeEvent-to-record projection 与 replay。
  6. packages/runtime/src/stream-graph-trace.ts:topology validation 与 reference-only route。
  7. packages/runtime/src/stream-graph-readiness.ts:map 与 sealed all_settled readiness。
  8. packages/core/src/agent-graph-control.ts 与 packages/runtime/src/stream-graph-admission.ts:durable intent claim。
  9. packages/runtime/src/stream-graph-dispatch.ts:structural drive-to-quiescence loop。
  10. packages/runtime/src/stream-graph-schedule-reconcile.ts:schedule、dynamic provision、stop、claim 与 dispatch convergence。
  11. packages/runtime/src/session-manager.ts:child Session provision 与 claimed activation execution。
  12. packages/runtime/src/stream-graph-coordinator.ts:host-owned single-flight lifecycle、client projection repair 与 root-only timeline access。
  13. packages/runtime/src/agent-graph-timeline.ts:reference-only control/data-plane reconstruction、stable order、coverage 与 pagination。
  14. packages/runtime/src/agent-graph-supervisor-wake.ts:回到 root Agent 的持久路径。
  15. packages/storage/src/sqlite-session-metadata-schema.ts 与 sqlite-session-metadata-store.ts:Graph control-plane transaction 与 timeline metadata snapshot。
  16. apps/desktop/src/main/main.ts、runtime-host-session-domains-ipc-main.ts 与 apps/desktop/src/renderer/agent-graph-panel.tsx:产品组合与 bounded UI。Graph 变更事件走通用 session-domains 桥接的 agentGraphChanged,没有 Graph 专属的主进程 IPC 模块。

最相关的 contract tests 位于:

  • packages/runtime/src/__tests__/stream-graph-*.test.ts
  • packages/runtime/src/__tests__/agent-graph-timeline.test.ts
  • packages/runtime/src/__tests__/agent-graph-supervisor-wake.test.ts
  • packages/runtime/src/__tests__/session-manager.test.ts
  • packages/storage/src/__tests__/sqlite-session-metadata-store.test.ts
  • packages/storage/src/__tests__/agent-graph-timeline-metadata.test.ts

总结

Maka Graph 从一个流处理视角出发:

subagent work   表现得像 operator
Agent message  表现得像 stream record
dependency     表现得像 route 与 input frontier
coordination   表现得像 graph 上的 scheduling

实现把这个观察具体化,却没有改写 Agent runtime。Child Session 提供稳定 operator container;AgentRun 提供 activation;RuntimeEvent 提供 immutable fact;确定性 projection 提供 record、route 与 readiness;SQLite 提供 revision-linearized schedule、topology、admission、client materialization 与 supervisor wake;Desktop 提供 host 与 operational view。

主 Agent 是这个设计最有辨识度的部分。它始终在图旁:对用户保持可用,可以检查任意 operator,可以添加或停止 work,并负责选择和综合最终 record。Data path 无需等待模型批准即可推进,而 judgment 留在用户能够看见和影响的 conversation 中。

这就是该架构的承诺:复用一套可信 Runtime,增加一层持久 Graph control plane,让监督 Agent 足够靠近 schedule、能够理解和修改它,同时不成为它的 bottleneck。