04 · AIN:Agent Interaction Nets 计算模型
轨道 B 的语义核心。目标:在保留交互网纯核(局部性、强合流、线性)的前提下,补上 Agent 需要的状态、同步、效果、位置、失败、成本六件事,并明确哪些性质仍然成立。
4.1 设计压力
把标准交互网直接拿来跑 Agent,会在六个地方断裂:
| 压力 | 标准 IN 的表现 | Agent 的需要 |
|---|---|---|
| 状态 | cell 是无状态的符号 | Agent 有记忆、有阶段 |
| 同步 | 只能等一个输入 | join/barrier/select/race |
| 效果 | 纯重写,无 I/O | LLM、HTTP、工具、人工 |
| 位置 | 线是抽象的 | 多机、租户、数据驻留 |
| 失败 | 规则总是成功 | 超时、异常、重试、补偿 |
| 成本 | 只计交互数 | token、美元、延迟、配额 |
AIN 的策略:纯核不动,扩展分层。每一层扩展都有独立的语义与类型,不污染纯子集。
┌──────────────────────────────────────────────┐
│ L6 Cost / Budget / Scheduling policy │
├──────────────────────────────────────────────┤
│ L5 Supervision / Error / Compensation │
├──────────────────────────────────────────────┤
│ L4 Locations / Remote wires / Migration │
├──────────────────────────────────────────────┤
│ L3 Effects (LLM / Tool / Human) │
├──────────────────────────────────────────────┤
│ L2 Synchronization (Join / Select / Gate) │
├──────────────────────────────────────────────┤
│ L1 Stateful agents (state-indexed cells) │
├──────────────────────────────────────────────┤
│ L0 Pure interaction nets (γ/δ/ε + constrs) │
└──────────────────────────────────────────────┘
4.2 形式定义
一个 AIN 网是七元组:
N = (C, W, Σ, S, ℓ, F, policy)
C:有限 cell 集合。Σ:agent 签名;每个α ∈ Σ有 arity 与端口名。S:状态域;每个 cellc有状态s(c) ∈ S_{α(c)}。W:wire 集合;每条 wire 连接两个端口;每个端口至多一条。ℓ : C → Loc:位置(节点 id)。F:free ports(接口)。policy:调度策略/预算/优先级标注(可继承)。
cell:
c = (α, s, p₀, p₁…pₙ)
p₀:principal port(v1 的用户 agent 恰好一个)。p₁…pₙ:auxiliary ports,带名字与类型。- 对 multiport cell(L2),
P(c)是 principal port 的有序集合。
活跃对:一条 wire 连接两个 principal port。对 multiport,活跃"配置"是一组 wire,连接规则模式中所有 principal port。
规则:
rule α[s](x₁…xₘ) ⋈ β[t](y₁…yₙ) => N'
s,t是状态模式(可绑定变量)。- 对每对
(α,β),至多一条规则;状态由编译器展开为互斥的 agent 类型(见 4.3),因此不违反"每对至多一条"。 N'的 free ports 恰好是x₁…xₘ, y₁…yₙ。
归约:删除活跃对,插入 N',按端口名对接外部线。
范式:无活跃对(可能仍有 effect pending / remote message in flight;见 4.9 的 quiescence)。
4.3 L1:状态——把状态编码进类型
问题:标准 IN 的规则只按 agent 类型匹配;Agent 需要"同一角色、不同阶段"。
方案:state-indexed agents。
agent Planner<S> {
ports { inbox: ?Task; llm: !LLM; out: !Plan }
state Idle | Thinking { draft: Text } | Done { plan: Plan }
}
编译后展开为:
Planner_Idle, Planner_Thinking, Planner_Done
每个状态是一个不同的 agent 符号;规则表按 (Planner_Idle, Task)、(Planner_Thinking, LLMResult) 等生成。这样:
- 规则仍然"每对至多一条"。
- 纯核的强合流保持。
- 状态转移就是 cell 类型的改变(旧 cell 被规则替换为新 cell)。
对于运行时内部 cell(Effect、Supervisor、Remote),允许可变状态(Pending(job) 等),因为它们不在纯子集里;它们的语义由运行时协议定义,不参与纯合流定理。
4.4 L2:同步——受控的 multiport
标准 IN 无法表达"等两个输入都到齐"。Mazza 的 multiport IN 允许一个 cell 有多个 principal port;活跃对是多对多。我们只引入三种受控形式:
Join(k)
Join(k) : (T₁, …, Tₖ) → T
- k 个 principal port;每个连接到一条消息 wire。
- 当 k 个消息都到达时点火一次,消费全部,产生一个 tuple/结果。
- 类型:
⊗ᵏ T → T。 - 用途:fan-in、map-reduce 的 reduce 阶段、barrier。
Select(k)
Select(k) : (T₁, …, Tₖ) → T ⊕ Cancelled
- k 个 principal port;第一个到达的消息获胜,其余被取消。
- 需要取消协议:每个未获胜的输入收到
Cancel;上游必须支持取消(Effect/Agent 的 cancel 端口)。 - 类型:
⊕ᵏ T → T(内部选择的外部化)。 - 用途:race、超时、投机执行、多模型投票(第一个成功)。
Gate / Barrier(k)
Barrier(k):收齐 k 个信号后,向 k 个输出各发一个信号(广播释放)。Gate:一个开关 cell,只有 open 时消息通过;用于人工审批、限流。
类型与死锁
- Join/Select 的端口类型必须满足 session 对偶;例如 Join 的输入是
?T,上游是!T。 - 对树形协议(无循环等待),well-typed 网满足 progress(不会卡死)。
- 环形协议需要显式顺序(给 cell 一个全局 rank,或使用 session 的
rec加 guard),v1 先用静态检查拒绝潜在环。 - 这部分的形式化在
specs/ain-sync.md;实现先用保守检查 + 运行时超时兜底。
为什么不用完整 multiport IN?完整版表达力等价于 π 演算,但规则匹配/调度/类型都复杂得多。v1 只需要同步原语;保留未来升级到完整 multiport 的接口。
4.5 L3:Effects——把副作用变成显式节点
Effect cell:
Effect<Op> {
principal req : ?Request<Op>
auxiliary res : !Response<Op>
auxiliary cancel : ?Cancel
state Idle | Pending(JobId) | Cancelled
}
生命周期:
Idle收到Request→ 创建 jobj,cell 变Pending(j)。- 运行时异步执行
Op(LLM/HTTP/tool/human)。 - 完成 → 在
res上注入Result(v);cell 回Idle(可复用)或Done(一次性)。 - 失败 → 注入
Error(e);按策略重试。 Cancel→ 运行时取消(若支持),注入Cancelled。
Effect 描述:
effect llm(model: Text, prompt: Text, max_tokens: Nat) -> Completion
effect http(method: Method, url: Url, body: Bytes) -> Response
effect tool(name: Text, args: Json) -> Json
effect human(form: Form) -> Decision
语义:带标签的迁移
N --(eff req j)--> N' (cell → Pending)
N --(eff done j v)--> N'' (result injected)
Effect log:
{ job_id, op, input_hash, model, params, output_hash, output,
started_at, ended_at, cost, idempotency_key, retries, node }
- 重放时,Effect 不重新执行;直接按
job_id从 log 注入结果。 job_id由(net prefix hash, cell id, request hash, attempt)决定;同一输入重放稳定。- 对非确定性输出(LLM 温度、工具外部状态),log 是唯一事实来源。
- 隐私:log 可配置只存 hash + 加密的 output;或存引用(对象存储)。
流式:Response 可以是 Stream<Chunk> cell;每个 chunk 是一条消息,Agent 可以增量处理;背压由通道窗口控制。
幂等:外部工具调用带 idempotency_key;运行时维护去重表;重试不重复扣费(对支持幂等的 API)。
4.6 L4:分布——cell 归属 + 远程通道
不变量:
每个 cell 在任意时刻恰好属于一个节点;只有 owner 能点火的规则的 LHS 中包含该 cell 的活跃对。
跨节点线:不共享内存;编译为 Remote 通道:
Cell A (node 1) ── wire ── Cell B (node 2)
│ │
SendProxy ── QUIC/gRPC ── RecvProxy
- 每个方向一个有序通道;消息带
(net_id, wire_id, seq, payload)。 - 接收端把消息注入为本地
Messagecell,形成本地活跃对。 - 因此跨节点没有分布式锁:所有点火都是本地的;远程只是消息传递。
迁移(v1 可选,v2 必需):
- 触发:负载不均、数据驻留、节点下线。
- 过程:暂停 owner(lease)→ 序列化 cell + 邻接 proxy → 目标节点恢复 → 更新路由 → 释放 lease。
- 安全:epoch/fencing token 防止双 owner。
- 代价:迁移成本计入调度器;小 cell 优先。
放置:
- 初始:按 agent 声明/租户/数据位置。
- 动态:基于通信图(谁和谁交互多)做图分区;目标是最小化跨节点 wire。
- v1 先用静态放置 + 一致性哈希;v2 做在线迁移。
故障:
- 节点失联 → owner 的 cell 丢失;supervisor 从检查点/重放恢复。
- 远程消息至少一次;接收端按
(wire_id, seq)去重。 - 网络分区:v1 选择 CP(停止少数派写入)或 AP(可用但可能重复)需按场景配置;默认 CP + 明确错误。
4.7 L5:失败与监督
Error cell:
Error<E> { principal port; payload: E }
- 规则可以产生
Error而不是正常结果。 Trycell:连接一个计算和一个 handler;捕获Error并转换为正常值。Timeoutcell:包装一个 Effect/子网,超时注入Error<Timeout>。
Supervisor cell:
Supervisor {
children: [ChildSpec]
policy: RestartOne | RestartAll | Stop | Escalate
max_restarts: Nat
window: Duration
}
- 子 Agent 的
Exit(Ok|Error)消息连到 supervisor 的 principal port。 - 按策略重启:重新实例化子网(复制 ChildSpec),保留/重置状态。
- 重启计数超限 → 升级到父 supervisor 或终止。
- 这是 Erlang/OTP 的语义,但在图上显式化:supervision tree 就是一张网。
补偿:
Compensatecell:记录已完成的副作用,失败时按逆序调用补偿 effect。- 对 LLM/工具,补偿通常是"发消息/回滚外部状态",不是事务。
重试:
- Effect 级:
max_attempts,backoff,jitter,retry_on。 - 规则级:不自动重试(纯规则不应失败);失败只来自 effect/supervisor。
- 幂等键保证重试安全。
4.8 L6:成本与预算
成本向量:
cost(step) = (
interactions, // 纯计算
input_tokens, // LLM
output_tokens,
usd, // 外部计费
latency_us,
energy_j // 可选
)
每个规则模板声明静态成本;每个 effect 声明动态成本(按模型/工具定价表)。
Budget cell:
Budget {
principal spend : ?Spend
auxiliary status : !Status
remaining: { tokens, usd, wall_time }
}
- Agent 在发起 effect 前先
spend;不足则收到Denied,必须走降级路径(更小模型/缓存/人工)。 - 预算可嵌套:父预算 → 子 Agent 子预算;超额向上传播。
- 账本:每个 step/effect 记
(agent_id, task_id, tenant, cost);可导出。
调度目标:
minimize makespan
subject to Σ cost ≤ budget
deadline_i ≤ d_i
fairness(tenant)
- v1:EDF(deadline)+ WFQ(fairness)+ 预算准入;关键路径优先。
- v2:基于通信图/成本的启发式放置;可选 RL/学习型策略(保持可解释)。
4.9 操作语义(小步)
(STEP) N ≡ N₀[a ⋈ b] rule(a,b) = N' N₀[N'] ≡ N₁
-------------------------------------------------
N → N₁
(EFF-REQ) c = Effect<Op> at Idle, msg = Request(op, input)
-------------------------------------------------
N → N[c ↦ Pending(j)] with j = job(op,input)
(EFF-DONE) job j completes with v
-------------------------------------------------
N → N[inject Result(v) at c.res; c ↦ Idle]
(EFF-FAIL) job j fails with e
-------------------------------------------------
N → N[inject Error(e) at c.res; c ↦ Idle]
(REMOTE) wire w = (a@n₁, b@n₂)
-------------------------------------------------
N → N[send(w, msg) to n₂]
(RECV) message (w, seq, payload) arrives at n₂
-------------------------------------------------
N → N[inject Message(payload) at b]
(MIGRATE) lease(c) acquired; state(c) serialized
-------------------------------------------------
N → N[c @ n₂]
可观察性:trace 是标签序列;纯 step 的标签是 (redex, rule);effect 是 (job, req/done);remote 是 (wire, seq)。
静止(quiescence):没有活跃对、没有 pending effect、没有 in-flight remote message。正常终止 = quiescent + 所有接口已消费/关闭。
4.10 类型系统(概要)
Types T ::= Unit | Bool | Nat | Text | Bytes | Json | Data | Port | Agent
PortType P ::= !T.S | ?T.S | !T | ?T
Session S ::= end | !T.S | ?T.S | ⊕{lᵢ:Sᵢ} | &{lᵢ:Sᵢ} | rec X.S | X
EffectRow E ::= ∅ | {op} ∪ E
AgentType A ::= Agent<α, S, P₁…Pₙ, E>
判断:
Γ ⊢ net : Δ (线性:Γ/Δ 中每个端口恰好一次)
Γ ⊢ rule : (α,β) → E (规则引入的 effect 行)
规则:
- 线性:wire 的两端各消费一个端口;free port 不能重复出现。
- session 对偶:
!T.S只能接?T.S;⊕只能接&。 - effect 子行:规则/agent 声明的 effect 必须被运行时 handler 覆盖;未声明的 effect 是类型错误。
- 预算:
@budget(n)标注;类型检查只保证"声明了预算",运行时保证"不超支"。 - 状态:
Agent<S>的S必须是有限 ADT;编译器展开。 - multiport:
Join(k)要求 k 个输入类型可组合;Select(k)要求输出类型一致 + 可取消。
v1 实现子集:
- 单态 + 简单泛型(
List<T>,Result<T,E>)。 - session 只支持
!/?/end+ 递归(无&/⊕的完整子类型)。 - effect row 显式声明,不做推断(后续加)。
- 线性检查是保守的:拒绝可能需要别名分析的网。
4.11 Agent 模式 → 网构造
| 模式 | 网构造 | 关键点 |
|---|---|---|
| 顺序流水线 | A ─msg→ B ─msg→ C |
每段是一个 cell;消息是 wire 上的 token |
| 扇出 | δ 复制任务到 n 个 worker |
复制是显式的;成本可计 |
| 扇入/join | Join(n) 等 n 个结果 |
类型 ⊗ⁿ;缺一不点火 |
| 竞速/超时 | Select(n) + Timeout |
败者取消;上游需支持 cancel |
| map-reduce | Split + worker pool + Join + Reduce |
可嵌套;预算按子网分配 |
| 路由/分发 | Router cell,按 tag 规则转发 |
规则表 = 路由表;可热更新(v2) |
| 黑板/共享状态 | Ref cell:Read/Write 消息串行化 |
线性 token 保证互斥;无锁 |
| 会话/对话 | 两个 session 端点 A ↔ B,交替 !/? |
类型保证顺序;可递归 |
| 监督树 | Supervisor + 子 Exit 端口 |
restart/stop/escalate;计数窗口 |
| 人工审批 | Effect<Human> + Gate |
长延迟;可恢复;审计 |
| 投机执行 | Sup(带标签的叠加)+ Select |
标签控制共享/分支;败者擦除 |
| 缓存/共享 | hash-consed Result cell + Lookup |
相同子网共享;命中直接返回 |
| 重试/补偿 | Retry/Compensate 包装 cell |
幂等键 + 逆序补偿 |
| 多模型投票 | 扇出到 n 个 LLM + Vote |
成本/质量权衡;可加权 |
| 层级团队 | 子网 + 边界端口(Subnet cell) |
封装/复用;预算继承 |
一个 3 Agent 流水线的网
Question ──▶ Researcher ──draft──▶ Critic ──verdict──▶ Writer ──▶ Report
│ │ │
└──── LLM cap ───────┴──── LLM cap ────┘
Researcher的out连到Critic的in;Critic的out连到Writer的in。- 三个 agent 各自有一个
LLMcapability 端口;能力由宿主注入,不能凭空访问网络。 - 如果
Critic失败,Supervisor重启它;Researcher的 draft 可以缓存复用(结构化共享)。 Budget挂在流水线入口,按 token/$ 分配。
4.12 与其他模型的关系
| 模型 | 对应 | AIN 的增量 |
|---|---|---|
| λ 演算 | 函数/应用/复制 | 图重写、显式共享、并行、效果 |
| Actor | cell ≈ actor;port ≈ address;mailbox ≈ wire | 强合流、线性能力、结构化共享、图级 trace |
| π 演算 | 通道/移动 | multiport 可编码 π(Mazza);我们只取同步子集 + 显式 location |
| Petri 网 | place/transition/token | 更强的表达力(可编码 λ);层级/类型 |
| 数据流 | 算子/边 | 复制/擦除/共享是显式节点;可最优归约 |
| 工作流引擎 | DAG + 持久化 | 语义级并发、图重写、成本调度;借鉴 durability |
| 会话类型 | 协议 | 图上的端点;运行时可检查 |
4.13 开放理论问题
- Effectful 合流:在 effect 交错下,最终网是否只依赖于 effect log?需要定义"可交换的 effect"与"因果序"。
- Multiport 死锁自由:树形协议已有经典结果;带环/递归的 session 在 AIN 上的判定条件?
- 分布精化:远程通道的异步语义与集中式语义的 bisimulation 需要哪些假设(FIFO、可靠、无分区)?
- 成本最优调度:在 DAG/图上的 EDF+WFQ 近似比;预算约束下的在线算法。
- 线性与共享的边界:Agent 需要共享上下文,但线性端口不允许别名;用
Sup/显式dup还是Ref?哪种对 LLM 工作负载更自然? - 读回/可解释性:如何把一张巨大的 Agent 网折叠成人类可读的"为什么"(类似 IC 的 collapse)?
这些问题不阻塞 v1;v1 用保守子集 + 运行时检查 + 属性测试,论文/形式化随后补。