雨天小六

读懂 Codex(9.18):子 Agent、Mailbox 和容量控制

· 更新于 2026-08-03 · 专栏:读懂 Codex

#Codex#Agent Runtime#Python#软件架构

具体问题与边界

Spawn、消息投递与子 Agent 终态为什么要先解决身份、预留容量和反压,再谈并行模型循环?

AgentPool 是控制面骨架:唯一 ID、父子边、状态、resident capacity、bounded mailbox 和 final 通知;它不替子 Agent 运行 Session/ModelClient。 下面同时给出状态所有者、顺序、伪代码、故障残留和不可外推边界。

状态所有权

对象所有者生命周期持久化
AgentRecord registryAgentPool根树生命周期Mini 仅内存
agent_id/parent_idAgentPool._createAgent 生命周期
statusAgentPoolIdle/Running/Completed/Closed
Mailbox Queue目标 AgentRecord直到消息消费
capacity countAgentPool每次 spawn 动态计算 resident

正常路径

子 Agent、Mailbox 和容量控制正常路径图
图 9.18-1:Spawn、消息投递与子 Agent 终态为什么要先解决身份、预留容量和反压,再谈并行模型循环?
  1. Host 先 create_root,AgentPool 只允许一个 root;spawn 必须引用存在且未 closed 的 parent。
  2. spawn 在创建 child 之前统计非 Closed resident。达到 max_agents 就拒绝,不产生半注册子节点。
  3. 每个 Agent 有固定容量 Queue。send_message 校验 sender/target 后 await target.mailbox.put;满时生产者自然反压。
  4. receive 可永久等待或带 timeout;消息明确携带 sender_id、kind 和 text。
  5. child complete 先把 status 改为 Completed,再向直接父 Mailbox 发送 kind=final;重复完成或 root complete 被拒绝。

Python 风格伪代码

def spawn(parent_id, name):
    parent = require_agent(parent_id)
    require(parent.status != CLOSED)
    resident = count(record.status != CLOSED)
    if resident >= max_agents:
        raise AgentCapacityError()
    child = create_record(new_id(), parent_id, bounded_mailbox)
    child.status = RUNNING
    return child

async def send_message(sender, target, text, kind="message"):
    require_agent(sender)
    record = require_agent(target)
    require(record.status != CLOSED)
    await record.mailbox.put(MailboxMessage(sender, kind, text))

async def complete(child_id, result):
    child = require_nonterminal_child(child_id)
    child.status = COMPLETED
    await send_message(child.id, child.parent_id, result, kind="final")

伪代码没有复制 Rust 语法;它保留了状态修改、await、取消、外部副作用和结果反馈的实际顺序。

失败、取消与恢复

子 Agent、Mailbox 和容量控制失败路径图
图 9.18-2:失败不是一个 exception 方框,而是各状态所有者留下的可观察组合。
故障点残留/风险处理
capacity 已满无 child recordAgentCapacityError
parent/target 不存在无可解析地址KeyError
target Closed消息不能被消费拒绝发送
Mailbox 满消息尚未入队sender await 反压
重复 complete可能发送两个终态拒绝第二次
父 Mailbox 满时 child completechild 已标 Completed,通知等待Host 必须持续 drain;这是显式成本

不变量

容量预留失败不能留下半注册 Agent;一个 child 只能产生一次 final;Mailbox 满时必须等待或显式失败,不能静默丢消息。

设计取舍与不能外推的结论

先复刻控制面能单独测试最危险的容量/终态问题,但不能据此声称多 Agent Runtime 完成。Mini 没有子 Session 启动、角色指令、Fork history、residency/eviction、AgentGraphStore 和崩溃恢复。

测试与复现

cd examples/mini-codex
uv run pytest -q -k 'test_agent_pool_enforces_capacity_and_delivers_child_result or test_bounded_mailbox_applies_backpressure'
uv run mypy src
uv run python benchmarks/runtime_baseline.py
  • test_agent_pool_enforces_capacity_and_delivers_child_result
  • test_bounded_mailbox_applies_backpressure

官方源码导航

Mini Codex 对照

  • src/mini_codex/runtime/agents.py:AgentPool、AgentRecord、Mailbox 与 capacity

本节结论

容量预留失败不能留下半注册 Agent;一个 child 只能产生一次 final;Mailbox 满时必须等待或显式失败,不能静默丢消息。

阅读导航

上一节:9.17 · 下一节:9.19

评论


← 返回文章列表