雨天小六

读懂 Codex(7.3):AgentRegistry 的注册、活动索引与 SpawnReservation

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

#Codex#Agent Runtime#Multi-Agent#Extension#软件架构

AgentRegistry 用一次可回滚预留同时保护总量、路径和昵称;只有子 Thread 创建成功后才 commit 元数据,失败路径由 Reservation 的析构回滚。

本节只研究“运行时地址注册事务”。输入是 容量上限、候选 AgentPath、Role、昵称,状态由 每棵 Root Agent 树共享的 AgentRegistry 持有,成功输出为 原子注册的 AgentMetadata 或完全释放的失败预留。相邻章节中看起来相似的对象如果由不同组件拥有,就不能用一个布尔状态替代。

先确定边界和状态所有者

问题本节答案
谁发起容量上限、候选 AgentPath、Role、昵称
谁拥有可变状态每棵 Root Agent 树共享的 AgentRegistry
成功产物原子注册的 AgentMetadata 或完全释放的失败预留
不在本节内运行时地址注册事务之外的上游产品策略和下游业务实现

这张表的用途不是复述名词,而是约束实现顺序:校验必须发生在副作用之前;已经提交的状态只能由原所有者撤销;只读投影不能反过来成为控制权威。

端到端调用链

  1. 原子增加 total_count
  2. 预留唯一 AgentPath
  3. 预留昵称
  4. 创建 Thread
  5. commit ThreadId/metadata
AgentRegistry 的注册、活动索引与 SpawnReservation的端到端机制流程,展示原子增加 total_count、预留唯一 AgentPath、预留昵称、创建 Thread、commit ThreadId/metadata
图 7.3-1:原子增加 total_count → 预留唯一 AgentPath → 预留昵称 → 创建 Thread → commit ThreadId/metadata。图中每条箭头都表示下一层只接收上一层已经确认的状态。

这条链里至少有三种时间尺度:配置或身份在 Thread 创建时冻结,Turn 内状态由 Session 串行协调,Step 级目录与能力在每次模型采样前重新捕获。若把后一个时点的新状态拿去解释前一个时点已经发出的调用,就会产生跨代错误。

源码机制拆解

Root 不计入子 Agent 总量

Root 用专用注册入口写入 /root,释放计数时也只对非 Root 元数据递减。V2 的 Session 总并发配置另有 Root 占一个位置的计算,不能与这里混为一谈。

这项约束直接决定了边界两侧的数据形状。实现时应先证明前置状态,再写入由 每棵 Root Agent 树共享的 AgentRegistry 持有的对象;不能用日志、UI 状态或模型描述代替真实状态更新。

路径占位先于 Thread 创建

reserve_agent_pathagent_tree 中插入只有路径的占位元数据,竞争者随后会得到 path already exists,而不是各自创建 Thread 后再争抢。

这项约束直接决定了边界两侧的数据形状。实现时应先证明前置状态,再写入由 每棵 Root Agent 树共享的 AgentRegistry 持有的对象;不能用日志、UI 状态或模型描述代替真实状态更新。

Reservation 的 Drop 是事务回滚

未 commit 时会释放路径并递减 total_count;昵称被有意留在 used 集合,直到昵称池耗尽后统一 reset,避免快速失败造成昵称立刻重复。

这项约束直接决定了边界两侧的数据形状。实现时应先证明前置状态,再写入由 每棵 Root Agent 树共享的 AgentRegistry 持有的对象;不能用日志、UI 状态或模型描述代替真实状态更新。

双向索引需要一起维护

commit 时写入 thread_pathsagent_tree;同一 Thread 或路径已有旧映射时会清理另一侧,防止出现一个 Thread 对应两个活动地址。

这项约束直接决定了边界两侧的数据形状。实现时应先证明前置状态,再写入由 每棵 Root Agent 树共享的 AgentRegistry 持有的对象;不能用日志、UI 状态或模型描述代替真实状态更新。

Python 风格伪代码

下面的伪代码提炼状态机与错误顺序,不逐行翻译 Rust,也不假装 Python 对象具有 Rust 的所有权保证:

async def register_spawn(registry, request, create_thread):
    reservation = registry.reserve_count(request.max_threads)
    try:
        reservation.reserve_path(request.agent_path)
        reservation.reserve_nickname(request.preferred_nickname)
        thread = await create_thread()
        reservation.commit(AgentMetadata(
            thread_id=thread.id,
            path=request.agent_path,
            role=request.role,
            nickname=reservation.nickname,
        ))
        return thread
    finally:
        # uncommitted reservation releases count/path automatically
        reservation.close_if_uncommitted()

阅读这段伪代码时要检查三件事:第一,输入是否在副作用前完成规范化;第二,异步等待是否仍携带原 Thread/Turn/Step 身份;第三,失败后究竟释放了什么、又保留了什么。只写快乐路径会把本节最重要的一致性条件删掉。

失败、取消与恢复

AgentRegistry 的注册、活动索引与 SpawnReservation的三类失败分支、可观察结果和恢复责任
图 7.3-2:失败不会抹掉已经提交的状态;每条分支都由拥有该状态的组件执行恢复或补偿。
故障点已发生的状态可观察结果恢复责任
达到 max_threads计数未增加返回 AgentLimitReached等待关闭或提高容量
路径已被占用total_count 已预留Reservation Drop 递减计数换 task_name
Thread 创建失败路径占位存在未 commit 的 Reservation 自动回滚路径/计数保留错误给调用方

取消不自动等于回滚,列表不自动等于权威存储,模型看见的描述也不自动等于已经获准执行。对于已经建立的 Thread、写入的 Edge、入队的 Mailbox、安装的插件或外部工具副作用,必须由相应所有者执行显式关闭、补偿或保留。

并发与一致性不变量

  • 同一身份不能在并发路径中被重复预留或重复注册;若允许幂等重试,幂等键必须是稳定路径、ThreadId、request id 或 catalog revision,而不是展示名称。
  • 一次模型采样看见的 Prompt、工具目录和执行入口必须来自同一个 Step 快照;刷新只影响后续 Step。
  • Watch/Activity/事件是通知机制,不是状态本身。被唤醒后必须重新读取 Registry、Session、Mailbox、Store 或 Binding 的权威值。
  • 失败路径不得“为了干净”删除仍可恢复的历史;同样也不得把只剩历史的对象伪报成当前仍驻留运行。

设计思路与代价

本节设计保护的核心不变量是:AgentRegistry 用一次可回滚预留同时保护总量、路径和昵称;只有子 Thread 创建成功后才 commit 元数据,失败路径由 Reservation 的析构回滚。代价是同一个功能会跨越地址、配置、Session、队列、存储或扩展适配层,测试也必须覆盖正常、并发和中途失败。更短的单体实现虽然容易演示,却无法区分“存在、已加载、正在运行、可恢复、已关闭、模型可见”这些彼此独立的事实。

设计动机部分是根据生产类型、调用顺序和测试行为归纳;源码可直接证明的是字段、分支、状态所有者和失败结果。文章不会把推断写成服务端或产品层的未公开事实。

源码与测试证据

位置能证明什么
codex-rs/core/src/agent/registry.rs计数、路径/昵称预留与 commit/drop
codex-rs/core/src/agent/control/spawn.rsSpawn 事务使用预留的顺序
测试/可执行检查覆盖重点预期
codex-rs/core/src/agent/registry_tests.rs正常、边界与状态转换应与本节不变量一致
codex-rs/core/src/agent/control_tests.rs失败、并发或兼容行为应与本节不变量一致

当前环境没有 Cargo,本轮不伪报 Rust 测试执行;验证由锁定提交下的源码—测试静态对读、源文件存在性检查、Mermaid 渲染、Astro 生产构建和公开页面检查组成。

Mini Codex 复刻建议

Mini Codex 应先复刻本节的协议不变量:明确状态所有者、稳定身份、可回滚预留、同 Step 快照、超时/取消和单一终态。平台沙箱、远程 Executor、OAuth、Backend App Route 或第三方 MCP Server 的安全性质不能由一个本地 Python mock 证明,适配器只能验证调用顺序和故障处理。

本节结论

AgentRegistry 用一次可回滚预留同时保护总量、路径和昵称;只有子 Thread 创建成功后才 commit 元数据,失败路径由 Reservation 的析构回滚。 掌握这一点后,再看相邻模块时就能判断它是在改变身份、运行状态、模型可见上下文、外部能力,还是仅提供观察快照。

阅读导航

上一节:Built-in Role、Agent TOML 与模型覆盖 · 下一节:AgentStatus 的事件投影、终态和 Interrupted 语义

源码依据

本文基于锁定提交 fe01054a28fa4bd04716d9ceadb410f2443a50ce 的生产代码和相邻测试静态核对。关键入口如下:

评论


← 返回文章列表