06 · 运行时与调度网络
轨道 B 的工程核心。目标:单机把纯网跑快,把 Agent 的 effect 管好;多机把 cell 的归属、消息、迁移、故障处理清楚。 原则:compute 与 effects 分离;本地点火,远程传消息;确定性靠日志,不靠祈祷。
实现状态(M3):本文件是目标架构。M2/M3 已实现单机执行层的核心切片(stateful agents、 mock/HTTP/shell effects、effect rows、预算、journal/checkpoint、trace/replay、trace viewer、 独立 flow 批处理),见 10-m2-runtime.md 与 11-m3-language.md。 单 flow 内多线程 work stealing、真实 LLM provider、session-typed channels、分布式调度仍在 M4+。
6.1 目标与非目标
目标
| 指标 | v1 目标 |
|---|---|
| 纯网吞吐(单核) | ≥ 5M interactions/s |
| 纯网吞吐(8 核) | ≥ 20M interactions/s |
| Agent 消息吞吐(单节点) | ≥ 20k msg/s |
| 调度延迟 p99 | < 10ms(本地) |
| 重放一致率 | 100%(同 checkpoint + 同 effect log) |
| 故障恢复 | < 5s(3 节点,1 节点故障) |
| 内存 | < 64B/cell(纯网);大 payload 外置 |
| 可观测 | 每次交互/effect 可查询、可回放 |
非目标
- 不做通用 GPU 运行时(纯计算子网可编译到 HVM/IC 后端)。
- 不做跨公网拜占庭容错(v1 受信集群 + TLS)。
- 不做通用数据库/对象存储(用适配器接 S3/Postgres/Redis)。
- 不做"零拷贝跨机共享内存"(v1 消息传递;RDMA 是 v3 研究)。
6.2 总体架构
┌─────────────────────────────────────────────────────────────┐
│ ain CLI / SDK │
│ .ain → parse → typecheck → AIN IR → bytecode │
└───────────────────────────┬─────────────────────────────────┘
│ deploy / run
┌───────────────────────────▼─────────────────────────────────┐
│ aind (single node) │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ Compute │ │ Effect bus │ │ Durability │ │
│ │ workers 0..N │ │ (tokio) │ │ WAL + snapshot │ │
│ │ - redex bag │ │ - LLM │ │ - append │ │
│ │ - steal │ │ - HTTP │ │ - fsync policy │ │
│ │ - heap/GC │ │ - tool │ │ - replay │ │
│ └──────┬───────┘ │ - human │ └─────────────────┘ │
│ │ └──────┬───────┘ │
│ ┌──────▼───────────────────▼────────────────────────────┐ │
│ │ Net store (cells, wires, rules) │ │
│ │ + routing table + leases │ │
│ └───────────────────────┬───────────────────────────────┘ │
│ │ QUIC streams │
└──────────────────────────┼──────────────────────────────────┘
│
┌──────────────────┼──────────────────┐
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ node 2 │ │ node 3 │ │ node k │
└─────────┘ └─────────┘ └─────────┘
控制面(membership/placement/lease)在 v1 可以是嵌入式(每个节点跑一个轻量协调线程 + 静态配置),v2 抽出独立 ain-sched 服务。
6.3 单机运行时
6.3.1 数据表示
Term(纯网):64-bit word,HVM 风格:
1 5 18 40
┌───┬─────┬──────────┬──────────────────┐
│sub│ tag │ label │ value │
└───┴─────┴──────────┴──────────────────┘
tag:CON / DUP / ERA / VAR / NUM / CTR / REF / EFFECT / JOIN / …label:δ/γ 的标签、构造子 id、effect id。value:节点地址(40-bit 本地堆偏移)或未装箱数字。sub:是否已被替换(IC 的全局变量优化)。
Cell(Agent):
#[repr(C)]
struct Cell {
header: u64, // tag | state | flags
principal: AtomicU64, // 端口(wire)
aux: [AtomicU64; N], // 端口
payload: ValueId, // 大状态/消息体(堆外)
}
- 小状态内联;大状态(文本/JSON)放
ValueStore(bump arena + 引用计数)。 CellId = (node: u32, worker: u16, slot: u32, gen: u16),96-bit;v1 可用 128-bit 简化。
端口/线:
- 每个端口是一个
AtomicU64,存对端PortRef或FREE。 - 连接 = CAS:两边都 free 才能连;一边是变量则做替换;两边是 cell 则形成活跃对。
- 这就是 HVM2 的"atomic linker";好处:无锁、局部、可并行。
6.3.2 归约循环
fn worker_loop(w: &Worker) {
loop {
let Some(redex) = w.pop_or_steal() else { break };
if !w.claim(&redex) { continue; } // cell 状态 Idle -> Busy
let rule = w.match_rule(&redex);
let rhs = w.instantiate(rule); // 分配 RHS cell
w.splice(&redex, rhs); // 重接端口
w.push_new_redexes(); // 新活跃对入队
w.release(&redex);
}
}
关键点:
- claim:每个 cell 有
Busy位;两个 worker 不能同时点火同一个 cell。 - splice:先接新线,再断开旧线;失败可回滚(或按顺序保证不会失败)。
- redex bag:本地 deque;新 redex 优先入本地;空闲时随机偷取(Chase–Lev)。
- 批量:小规则一次处理多个,减少队列开销;大规则(effect/IO)单独走。
6.3.3 内存与 GC
交互网是线性的:一个 cell 被规则消费后,通常可以立即回收。但有三个复杂点:
- 环:vicious circle 可能形成引用环;纯 refcount 会泄漏。
- 共享:δ 复制后,两个分支共享 payload;需要引用计数或不可变数据。
- 大 payload:文本/JSON 不应复制;用
Arc/arena + 引用计数。
v1 方案:
- Arena + 引用计数:cell 分配在 per-worker slab;payload 用
Arc<Value>。 - 周期回收:每 N 次交互或内存阈值触发一次 cycle collector(Bacon–Rajan 风格);或按 epoch 重置 arena(checkpoint 后)。
- 擦除即释放:ε 规则显式减少引用;没有隐式 GC 扫描。
- 上限保护:
max_cells/max_bytes;超限返回Error<ResourceExhausted>,由 supervisor 处理。
6.3.4 规则匹配与编译
- 规则表按
(agent_tag_a, agent_tag_b)索引;O(1) 查找。 - 规则 RHS 预编译为分配模板:一串
alloc+set_port指令;避免运行时解释。 - 状态展开后,agent tag 已经包含状态;规则表可能较大(states × messages),用两级表/完美哈希。
- 数字/字符串等原生操作走内建规则(
ADD,CMP,CONCAT),避免 Church 编码。
6.3.5 确定性模式
--deterministic:单 worker + 固定 redex 顺序(FIFO);用于 golden trace/调试。--parallel:多 worker;纯网结果仍由强合流保证;trace 记录实际调度顺序。--replay:从 WAL 读 step 顺序,强制按序点火;effect 从 log 注入。
6.4 调度器
6.4.1 本地策略
| 策略 | 用途 | 说明 |
|---|---|---|
| FIFO | 基准/确定性 | 简单、可复现 |
| EDF | 截止时间 | 最早 deadline 优先;需可抢占(在交互边界) |
| WFQ | 多租户公平 | 按 weight 分配点火配额 |
| Critical Path | 降低 makespan | 优先在关键路径上的 redex(需 DAG 估计) |
| Cost-Aware | 预算约束 | 优先低成本/高价值;避免在昂贵 effect 前做无用功 |
| Locality | 分布式 | 优先本地 redex,减少远程消息 |
默认:CostAware = EDF + WFQ + 关键路径 + 预算准入。
6.4.2 优先级传播
- 每个任务有
deadline,weight,budget,criticality。 - 消息携带优先级;Agent 处理消息时继承最高优先级(priority inheritance),避免低优先级任务卡住高优先级。
- Effect 请求继承调用者的优先级;LLM 队列按优先级 + 租户配额调度。
6.4.3 抢占与取消
- 抢占只在交互边界发生(规则点火前后),不在规则中间;保证原子性。
- 取消:
Cancel消息沿网传播;Effect 支持取消的 provider 直接 abort;不支持的在结果返回后丢弃(计费仍发生)。 - 预算耗尽:调度器拒绝新的 effect 准入;已发出的调用不强制中断(除非 provider 支持)。
6.4.4 全局放置
v1:
- 静态:
@loc标注 / 租户 / agent 类型 → 节点。 - 一致性哈希:
hash(agent_id) % nodes;迁移时更新。 - 本地优先:跨节点 wire 只在必要时建立。
v2:
- 通信图分区:统计
(cell_a, cell_b)交互频率,做图分区(METIS 风格),最小化跨节点边。 - 负载感知:队列深度、CPU、effect 延迟。
- 迁移:小 cell 优先;迁移成本计入目标函数。
6.5 Effects 运行时
6.5.1 架构
EffectCell (compute worker)
│ request
▼
Effect bus (tokio)
├── LLM adapter (provider pools, rate limit, retry)
├── HTTP adapter (reqwest, timeouts)
├── Tool adapter (WASM/process sandbox)
└── Human adapter (queue, webhook)
│ completion
▼
Owner worker (inject Result cell)
- Compute worker 不阻塞:发出请求后继续跑其他 redex。
- Effect bus 是多线程 tokio runtime;每个 provider 有独立的并发/速率限制。
- 完成回调把
Result投递到 owner 的完成队列;owner 在下一个循环注入。
6.5.2 LLM 适配器
- Provider 抽象:
OpenAI,Anthropic,Google,local (vLLM/Ollama),mock。 - 请求:model, messages, temperature, max_tokens, tools, response_format。
- 响应:text/tool_calls/usage/finish_reason。
- 重试:429/5xx 指数退避 + jitter;4xx 不重试(除 408/409)。
- 流式:SSE →
Stream<Chunk>;chunk 作为消息注入;支持 early cancel。 - 成本:按 provider 价目表计算 input/output tokens;记录到账本。
- 缓存:可选 prompt cache(provider 支持时);本地 content-addressed cache(相同 prompt+params → 结果),带 TTL/租户隔离。
- 安全:API key 只在 adapter 内存;日志脱敏;可配置区域端点。
6.5.3 工具适配器
- 工具描述:JSON Schema 输入/输出;
ToolCell校验参数。 - 执行:WASM(纯函数/轻量)、子进程(隔离)、HTTP(远程)。
- 权限:工具能力由宿主注入;没有端口就调不到;审计每次调用。
- 超时/资源限制:CPU/内存/网络配额;失败返回
Error。
6.5.4 人工适配器
- 表单/审批:生成一个 URL/消息;人工决定后 webhook 回来。
- 长延迟:不占用 worker;cell 处于
Pending;可超时/升级。 - 审计:谁、何时、看了什么、决定了什么。
6.6 持久化与重放
6.6.1 WAL
追加记录:
Step { seq, redex, rule, after_hash }
Effect { job_id, op, input_hash, output_hash, output, cost, ts }
Remote { wire, seq, payload_hash }
Checkpoint { seq, snapshot_ref, effect_offset }
fsync策略:always(强一致,慢)、interval(10ms)(默认)、never(dev)。- 批量写:多个 step 合并成一个 record;CRC/哈希链。
- 保留:按时间/大小轮转;冷数据归档到对象存储。
6.6.2 检查点
- 内容:cells、wires、free ports、routing table、pending effects、effect log offset。
- 编码:bincode/postcard + zstd;大 payload 只存引用。
- 频率:每 10k steps / 30s / effect 边界;可配置。
- 一致性:暂停调度(或 copy-on-write)→ 快照 → 继续;v1 用短暂 stop-the-world(< 10ms/1M cells)。
6.6.3 重放
ain replay --checkpoint cp-123 --wal wal-123 --until seq=50000
- 加载 checkpoint;按 WAL 顺序点火;effect 从 log 注入(不重新调用)。
- 校验每步
after_hash;不一致立即报错并 dump 差异(expected vs actual)。 - 重放速度目标:纯计算 ≥ 10× 实时;effect 0 调用。
- 用途:事故复现、回归测试、审计、迁移验证。
6.6.4 一致性等级
| 模式 | 保证 | 代价 |
|---|---|---|
ephemeral |
无持久化 | 最快;崩溃丢失 |
at-least-once |
WAL + 重试 | 可能重复 effect;需幂等键 |
exactly-once-effects |
WAL + 幂等键 + 去重表 | 大多数 LLM/工具可近似 |
strict |
同步 fsync + 2PC(可选) | 慢;仅关键任务 |
v1 默认 at-least-once + 幂等键;文档明确"LLM 调用本身不可能 exactly-once,只能去重/记账"。
6.7 分布式调度网络
6.7.1 成员与路由
- 静态配置(v1):
nodes.toml列出id, addr, capacity。 - 动态(v2):gossip(SWIM)+ 一致性哈希;节点加入/离开更新路由。
- 路由表:
agent_id/tenant → node;cell_id → node;带 epoch。
6.7.2 远程 wire
node A node B
Cell a ── SendProxy ──┐
├── QUIC stream (ordered, credit)
Cell b ── RecvProxy ──┘
- 每个
(net, wire)一个双向流;消息带seq;接收端按序注入。 - 信用窗口:每流 N 条未 ack;满则发送端暂停(背压)。
- 去重:接收端滑动窗口 +
seq;重复丢弃。 - 失败:流断开 → 重连 → 从最后 ack 重发;超过阈值 →
Error<Network>。
6.7.3 Cell 归属与迁移
Owner(cell) = node;只有 owner 能点火涉及该 cell 的规则。- 跨节点活跃对不直接点火:消息到达 owner 后形成本地活跃对。
- 迁移:
- 获取 lease(epoch+1)。
- 暂停该 cell 的本地交互。
- 序列化 cell + payload 引用 + 邻接 proxy。
- 目标节点恢复;更新路由;旧节点释放。
- 重发 in-flight 消息(按 seq 去重)。
- Fencing:旧 owner 的写被 epoch 拒绝,防止双写。
6.7.4 故障处理
| 故障 | 检测 | 处理 |
|---|---|---|
| 节点崩溃 | 心跳超时 | lease 过期;supervisor 从 checkpoint 重启受影响的 agent |
| 网络分区 | 心跳/租约 | 默认 CP:少数派停止写入;返回 Error<Partition> |
| 消息丢失 | ack/超时 | 重发;幂等键去重 |
| 磁盘满 | 监控 | 降级到 ephemeral;告警 |
| Effect provider 故障 | 错误率/超时 | 重试/降级模型/人工 |
6.7.5 弹性
- Scale out:新节点加入 → 迁移部分 cell → 更新路由。
- Drain:节点标记 draining → 停止新调度 → 迁移 → 退出。
- 热点:按队列深度/交互频率触发迁移;限制迁移带宽。
6.8 可观测性
6.8.1 Trace 事件
{
"seq": 12345,
"ts": "2026-11-10T12:00:00.123Z",
"node": "n1",
"worker": 3,
"net": "research/abc",
"redex": ["c17", "c42"],
"rule": "Researcher_Idle__Task",
"before": "sha256:...",
"after": "sha256:...",
"delta": { "add": [...], "remove": [...], "rewire": [...] },
"effect": null,
"cost": { "interactions": 1, "usd": 0 }
}
- 小网存 full snapshot;大网存 delta + 周期性 snapshot。
trace_id贯穿 agent/effect/remote;OpenTelemetry span link。
6.8.2 指标
ain_interactions_total{node,rule}ain_redex_queue_depth{node,worker}ain_effect_latency_seconds{provider,op}ain_effect_cost_usd_total{tenant,agent}ain_replay_divergence_totalain_cells{node},ain_memory_bytes{node}
6.8.3 调试器
ain trace view <trace>启动本地 Web UI:- 网图(复用 Netbook 渲染器)
- 时间线/因果链
- 过滤:agent、rule、effect、cost
- 对比:两次 run 的 diff(模型/prompt/调度)
- 与 Netbook 共享
ain-wasm,保证渲染一致。
6.9 安全
| 层 | 机制 |
|---|---|
| 能力 | 端口即能力;没有全局工具表;工具 capability 由宿主显式注入 |
| 撤销 | 断线/发送 Revoke;EffectCell 检查 token epoch |
| 沙箱 | 用户规则编译到 WASM;无文件/网络/环境变量,除非显式 capability |
| 租户隔离 | 进程/WASM 隔离;CPU/内存/网络配额;静态加密 |
| 审计 | 追加日志:谁、哪个 agent、哪个 capability、输入/输出 hash、成本 |
| 数据溯源 | 消息带 provenance(来源 agent、工具、文档);策略 cell 可隔离不可信内容 |
| Prompt injection | 最小权限 + 数据/指令分离 + 策略 cell(拒绝外发敏感数据) |
| 密钥 | 只在 adapter 内存;不进入网/trace;可接 KMS/Vault |
为什么端口即能力很重要:在传统框架里,Agent 拿到一个全局 tools 对象,prompt injection 可以诱导它调用任意工具。AIN 里,Agent 只能沿它被接上的线发送消息;没有线就没有能力。这是结构性安全,不是靠 prompt 说"不要这样做"。
6.10 性能模型与基准
6.10.1 成本模型
T_total ≈ max(
Σ_interactions / throughput,
critical_path × interaction_latency,
Σ_effect_latency / effect_concurrency,
network_bytes / bandwidth
) + scheduling_overhead + GC_pause
- 纯网:交互数 × 单交互成本;work stealing 开销 < 5%。
- Agent:effect 延迟主导;调度器要保证关键路径上的 effect 优先。
- 分布式:跨节点 wire 数量 × 消息率;放置优化目标是最小化跨节点边。
6.10.2 基准套件
| 类别 | 用例 | 指标 |
|---|---|---|
| 纯网 | fib(30)、bitonic sort 1M、Church 2^20、树遍历 | MIPS、内存、扩展比 |
| λ | Church numeral、Y 组合子、列表 map/filter | 交互数 vs 朴素 λ |
| Agent | 100 任务流水线、50 扇出、10 竞速、故障注入 | msg/s、p99、成本 |
| 重放 | 1k 次重放一致性 | 一致率、速度 |
| 分布 | 3/10/50 节点、迁移、节点故障 | 恢复时间、跨节点流量 |
| 安全 | 越权调用、能力撤销、沙箱逃逸 | 拦截率(应为 100%) |
6.10.3 对比基线
- HVM4:纯网/IC 性能。
- Inpla:多线程交互网。
- Temporal:durability/重放(概念对比,不是同类)。
- LangGraph:Agent 编排吞吐/成本(同类场景)。
6.11 部署形态
| 形态 | 说明 | 阶段 |
|---|---|---|
| 单二进制 | aind + ain CLI;本地/SQLite WAL |
v1 |
| 容器 | Docker image;K8s Deployment/StatefulSet | v1 |
| 嵌入式库 | ain-runtime 作为 Rust crate;napi/PyO3 绑定 |
v2 |
| 托管控制面 | 多租户、UI、计费 | v3(可选) |
配置示例:
# aind.toml
[node]
id = "n1"
listen = "0.0.0.0:7000"
workers = 8
[storage]
wal = "/var/lib/ain/wal"
checkpoint_interval = "30s"
fsync = "interval:10ms"
[effects.llm]
providers = ["openai", "anthropic"]
max_concurrency = 64
default_budget_usd = 0.50
[cluster]
nodes = ["n1@10.0.0.1:7000", "n2@10.0.0.2:7000", "n3@10.0.0.3:7000"]
placement = "consistent-hash"
6.12 风险与缓解
| 风险 | 缓解 |
|---|---|
| 原子链接的 ABA/内存回收 | epoch + generation;压力测试;参考 HVM2 |
| 大 payload 复制 | Arc + 外置 store;消息只传引用/hash |
| Effect 长尾 | 优先级 + 超时 + 降级模型;隔离 provider |
| 重放不一致 | 每步 hash 校验;effect log 不可变;CI 跑 1k 次 |
| 分布式调试困难 | trace 全局 id;单机 deterministic 模式复现 |
| 安全漏洞 | 能力模型 + WASM 沙箱 + 审计;第三方渗透测试 |
| 复杂度失控 | v1 只做单机 + 静态 3 节点;分布式特性按需开启 |