ΓDocsInteractiveNet

10 · M2:单机 AIN 执行层

状态:核心切片完成(2026-11)。本文记录实际实现与规格的差异,避免把 M2 当成完整 Ainet。

10.1 实现了什么

crates/ain-runtime(新 crate):

能力 实现
Stateful agents 每个 agent 有 id/kind/config/state/inbox/ports
确定性调度 单线程;按 agent id 字典序选下一个有消息的 inbox;FIFO
Effects EffectBus + mock llm / mock search;同步调用;usage 记账
Budget {usd, tokens, steps} 上限;超支返回 BudgetExceeded
Trace receive/act/send/effect/error/finish 事件(JSON)
Replay 从 trace 的 effect 记录重放;校验 request hash + 最终 state hash
Outputs 没有 edge 的端口进入 outputs["<agent>.<port>"]

crates/ain-cli:

ain flow demo
ain flow run examples/research-pipeline.json
ain flow run examples/research-pipeline.json --save-trace examples/research-trace.json
ain flow replay examples/research-pipeline.json examples/research-trace.json

3 Agent demo(Researcher → Critic → Writer):

  • Researcher:task → mock search → mock LLM → draft
  • Critic:draft → mock LLM → review
  • Writer:review → mock LLM → final(终端输出)
  • 4 次 effect;约 0.0003 USD;7 步。

10.2 为什么不是纯交互网

标准交互网没有:

  • 可寻址的 agent 信箱;
  • effect 请求/响应;
  • 预算;
  • 可重放的外部结果。

M2 按 docs/04-ain-model.md 的分层实现 L1(状态)+ L3(effects)+ L6(成本) 的运行时; 纯计算/组合子仍由 ain-core 负责。Agent 间通信暂由运行时信箱管理(actor-style), 而不是 session-typed net channel。这是有意的工程取舍:

  • 先验证"确定性 + 能力 + 成本"是否真的可用;
  • 避免在 M2 就陷入 session continuation / 通道重连的复杂语义;
  • M3 再把信箱降到 net wire + session types,做真正的图级分布。

10.3 数据流

FlowSpec (JSON)
   │
   ▼
Runtime (single node)
   ├── agents: BTreeMap<id, AgentState>   // state + inbox + ports
   ├── behaviors: kind -> Behavior        // researcher/critic/writer
   ├── effects: EffectBus                 // llm / search (mock)
   ├── ledger: tokens/usd/effects/steps
   └── log: Vec<Event>                    // trace + replay

调度:

loop {
  agent = first inbox non-empty (id order)
  msg = agent.inbox.pop_front()
  action = behavior.handle(agent, msg)
  agent.state = action.state
  for (port, msg) in action.send { route or output }
  if action.effect { call; ledger.add; enqueue "effect" response }
}

10.4 重放

Runtime::replay_log(&log):

  1. 从 Event::Effect 提取 (request_hash, response)。
  2. 重置 agents/ledger/outputs/step。
  3. 用相同 spec/behaviors 重跑;effect 请求必须匹配记录。
  4. 比较最终 state_hash 与 outputs。

测试:

  • replay_is_deterministic_100x:live 跑 100 次,state hash 全等。
  • replay_log_reproduces_state:从 trace 重放,state hash 与 outputs 全等。
  • 失败路径:budget 超支、step 上限、未知 behavior。

10.5 与规格的差异

规格(docs/04–06) M2 实际 顺延
AIN net 上的 state-indexed agents 运行时 AgentState M3 编译到 net
Join/Select/session channels 运行时信箱 + ports map M3
Effect cell(net 节点) 运行时 EffectBus M3
单机多线程 + work stealing 单线程确定性 M3
WAL + fsync + checkpoint JSON trace 文件 M3
文本 Ainet DSL JSON FlowSpec M3
真实 LLM/HTTP/tool mock LLM/search M3

10.6 下一步(M3)

  1. ain-lang:解析 Ainet Flow 文本 → FlowSpec;类型检查 effect/budget/端口。
  2. Session channels:把运行时信箱降到 net wire;Join/Select;死锁检查。
  3. 真实 effects:LLM provider、HTTP、工具沙箱;异步/超时/取消。
  4. WAL/checkpoint:append-only log + 快照;崩溃恢复。
  5. 并行 runtime:多 worker、work stealing、原子链接(复用 ain-core)。
  6. ain trace view:复用 Netbook 渲染器展示 flow/effect 时间线。

在 GitHub 编辑本文