打开文档导航

为什么每个 Family Member 仍是独立 Run

一句话

使用同一份 prepared input 不等于共享同一次运行:每个 family member 都有自己的执行身份、配置、workspace、deadline 和最终记录,需要 capability 时还必须使用自己的 Plan/Broker。

先看一个例子

两个 Agent 使用同一矩阵。Agent A 只能调用 metrics.read,写入 workspace A;Agent B 可以调用另一项能力,写入 workspace B。即使它们处理相同数据,也不能因为属于同一个 family 就共用权限表、execution ID 或目录。

如果 A 超时,系统还要能把 A 记为 timeout,而不是关闭 B 的输入或把 B 也当作失败。若 B 从未运行,关闭 family 时应把它记为 closed_unrun,不能悄悄把这个 runner 留给下一次请求。

真实机制

Host 用 PreparedRunnerConfig 为每个 member 冻结自己的 RunConfigInvocationRef、可选 Plan/Broker factory 和可选 workspace。创建 runner 时,family 会先检查 artifact/profile/import/memory 与 image 是否兼容,并深拷贝 CapabilityGrants 等可变配置。

Authority 还有更严格的隔离:

  • 需要 capability 的 member 使用不同的 Plan 对象和 Broker;即使两个 Plan 的内容等价,也不能复用同一 mutable authority 对象;不使用 capability 时 Plan 与 Broker 同时为空;
  • Broker factory 必须绑定该 member 的 exact Plan pointer、Plan digest 和 execution identity;
  • Invocation ID、execution ID 和非空 workspace Ref 在整个 family 生命周期内不得重复;
  • request 的 run_id 必须等于 runner 持有的 InvocationRef.ExecutionID
  • caller 不能额外传入 trustedPrepare,避免在 sealed family input 之外再偷偷注入状态。

Member 生命周期是:

new → running → terminal → closed

Run 只能成功进入一次。第二次或并发调用会得到 consumed/busy error,不会重新进入 Guest。Family 同时限制总 consumer 数与 active 数:总数上限阻止再创建 runner;active 上限在 Guest 前拒绝本次调用,但保留 runner 的 new 状态,容量释放后可以再调用同一个 runner。只有真正开始后的 success、Guest error、timeout、cancellation 和 trap 才会消费这个 runner。

Runner 在执行前关闭会进入 closed_unrun;执行中关闭会等待当前 Run 按 context cancellation 规则终止。Family 关闭时若仍有 active member,会拒绝关闭;active member 全部结束后,它让未运行的 runner 进入 terminal,释放 image/body/runtime resources,并保持 Close 幂等。

每个 terminal member 产生 body-free record,包含 family/input identity、member/Run/Invocation/execution identity、Plan 与 frozen grants digest、物理处置、outcome,以及可选 final workspace digest。Record 不保存 ndarray、source、response、credential 或 Host path。Acceptance report 只在 family 成功关闭后,把这些身份与 Host 声明的 source commit/tree 汇总;它不会自行访问 Git 或替代 Broker receipt、workspace receipt。

PreparedFamilyRunnerFactory 可把这种 runner 接到 subagent orchestrator,但 factory 只负责冻结并复核 child authority tuple。并发、重试、选择和发布仍属于 orchestrator。

为什么重要

技术上: 输入共享不会把权限、取消、workspace 或 cleanup 合并成一个大生命周期。一个 member 的 mutation 和 terminal outcome 不会改变 sibling 的 authority 或输入。

产品和业务上: 平台可以让多个 Agent 围绕同一数据并行探索,又能单独追踪每个候选是否完成、失败、超时或未运行,并只发布明确选中的 workspace root。

不能推出什么

  • Family member 不是 workflow continuation,也不会继承 sibling 的 Python frame、result 或 receipt。
  • Single-use runner 不提供自动 retry;要重试必须由 Host 创建新的、有新身份的 member,并判断外部 effect 是否允许。
  • Body-free member record 不是 external-world truth,也不替代 capability receipt。
  • Family close 不会自动选择或合并 workspace。

术语卡

  • Family member:Prepared Family 创建的一个有限、single-use consumer。
  • PreparedRunnerConfig:绑定该 member 执行配置、authority 与 workspace 的 Host 配置。
  • InvocationRef:Host 持有的 Agent/turn/output/attempt/execution 身份关系。
  • Terminal record:记录一个 member 最终处置及相关身份的 body-free Host record。
  • closed_unrun:runner 未执行便被关闭或随 family 结束的终态。

继续阅读