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
620 lines
36 KiB
Markdown
620 lines
36 KiB
Markdown
---
|
||
doc_id: architecture.agent-graph-stream-scheduling
|
||
title: "第七章:Graph 是调度,不是第二套 Runtime——主 Agent 监督下的流式 Agent Work"
|
||
language: zh-CN
|
||
source_language: zh-CN
|
||
counterpart: ./agent-graph-stream-scheduling-draft.md
|
||
implementation_status: current
|
||
document_status: draft
|
||
translation_status: synced
|
||
last_verified: 2026-08-23
|
||
owners:
|
||
- maka-backend
|
||
---
|
||
<!--
|
||
Licensed to the Apache Software Foundation (ASF) under one
|
||
or more contributor license agreements. See the NOTICE file
|
||
distributed with this work for additional information
|
||
regarding copyright ownership. The ASF licenses this file
|
||
to you under the Apache License, Version 2.0 (the
|
||
"License"); you may not use this file except in compliance
|
||
with the License. You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing,
|
||
software distributed under the License is distributed on an
|
||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
KIND, either express or implied. See the License for the
|
||
specific language governing permissions and limitations
|
||
under the License.
|
||
-->
|
||
|
||
# 第七章: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。
|
||
|
||
因此真正有用的抽象是:
|
||
|
||
```text
|
||
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 |
|
||
|
||
最重要的层级是:
|
||
|
||
```text
|
||
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。
|
||
|
||
```mermaid
|
||
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:
|
||
|
||
```text
|
||
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。
|
||
|
||
```mermaid
|
||
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 状态流转为:
|
||
|
||
```text
|
||
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 可能同时观察到:
|
||
|
||
```text
|
||
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 会报告全部三项限制:
|
||
|
||
```text
|
||
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
|
||
|
||
```mermaid
|
||
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 从一个流处理视角出发:
|
||
|
||
```text
|
||
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。**
|