Child Agent messages precede their settlement notices
Child Agent 消息先于其结算通知
A continuable child can send selected content and later produce an unconditional manager-authored settlement notice. If those two messages enter queues with different claim priority, the later settlement notice can reach the parent model before the earlier child message. The first step of a turn claims the complete `next-step` batch before one `next-turn` message, so mixing a FIFO later-turn send with a next-step set
English
Problem
A continuable child can send selected content and later produce an unconditional manager-authored settlement notice. If those two messages enter queues with different claim priority, the later settlement notice can reach the parent model before the earlier child message. The first step of a turn claims the complete next-step batch before one next-turn message, so mixing a FIFO later-turn send with a next-step settlement reverses causal order. Issue #2600 records the defect.
The child instruction says to send a finding whenever it changes what the parent should do next. Deferring that message to a later turn contradicts its scheduling meaning and separates causally ordered messages across queues with different claim priority.
Decision
Every model-authored adjacent-Agent message uses fixed Steer delivery through SubagentRuntime.sendMessage(). A running parent reads the child message at its nearest safe step boundary and an idle parent starts a turn. There is no quiet or next-turn model delivery option.
The continuation manager retains sendWaking() around messages delivered to resident continuable parents and routes the synchronous send through the parent's private SubagentInbox. The wrapper accepts the send before its closing promise is installed or rejects it afterwards, and an accepted attempt renews the Activation's wake generation before returning. The receiving Activation therefore cannot settle over an accepted waking send.
Ordering across parent states
A running parent receives an accepted child message and the child's later settlement notice in the same next-step FIFO. If the parent becomes idle before settlement arrives, it has already claimed the child message; settlement may then open a later turn without reversing observed order.
During parent maintenance, the child message occupies next-step and latches a wake, while settlement may occupy next-turn because maintenance reports idle status. The initial claim still takes next-step input before the queued turn. Waking input submitted after cancellation follows the core Agent's cancellation convergence rather than bypassing it.
Verification
The control-tool suite holds a parent inside an active model request, submits child messages, settles the child, and verifies sender identity, Steer admission, FIFO batching, and preservation after settlement. Continuation coverage pins waking admission accounting for a resident continuable parent and keeps the runtime-owned settlement source distinct from agent-message.
The keyless continuable-subagent snapshot uses the shipped fixed delivery. Its child-visible tool schema is the same as the parent's, and the accepted child message precedes the later settlement notice without a scheduling overlay.
Alternatives considered
Offer quiet delivery. A quiet message can remain unread after an idle parent parks. It also gives equivalent model-authored messages different liveness semantics and reopens deployment-dependent ordering.
Offer next-turn delivery. A later next-step settlement notice can still overtake it. Preserving message-before-settlement would require a cross-queue ordering barrier, and no current model operation requires later-turn isolation strongly enough to own that mechanism.
Move settlement notices to next-turn. Settlement batching uses the next-step queue so several children finishing together cost one parent step instead of one turn each. Moving settlement would increase latency and model work to retain an unnecessary message scheduling mode.
Consequences
- A child message may extend an open parent turn. It never interrupts the active model request or tool execution; the agent loop admits it only at a step boundary.
- Messages accepted together share one next-step batch, preserving FIFO order and limiting turn amplification.
- Model callers cannot choose a delivery mode, so ordering and wake behavior do not vary by deployment or call.
- A child-to-parent send still requires the direct parent to remain live; the service provides no durable parent mailbox.
中文
问题
可继续 child 可以发送选中内容,之后还会产生一条由管理器编写且无条件投递的结算通知。如果这两条消息进入领取优先级不同的队列,较晚的结算通知可能先于较早的 child 消息到达 parent 模型。一个轮次的第一个 step 会先领取完整 next-step 批次,再领取一条 next-turn 消息,因此混用 FIFO 后续轮次发送与 next-step 结算会颠倒因果顺序。Issue #2600记录了该缺陷。
child 指令要求在发现会改变 parent 下一步动作时发送该发现。把这条消息推迟到后续轮次既违背其调度含义,也会把具有因果顺序的消息拆到领取优先级不同的队列。
决策
每条模型编写的相邻 Agent 消息都通过 SubagentRuntime.sendMessage() 使用固定 Steer 投递。运行中的 parent 在最近安全 step 边界读取 child 消息,空闲 parent 则启动一个轮次。模型没有静默或 next-turn 投递选项。
继续执行管理器会在投递到驻留可继续 parent 的消息周围保留 sendWaking(),并通过 parent 的私有 SubagentInbox 执行同步发送。包装层会在安装 closing promise 前接受发送,并在安装后拒绝发送;被接受的尝试会在返回前更新 Activation 的 wake generation。因此,接收方 Activation 不会越过一条已接受的唤醒发送完成结算。
不同 parent 状态下的顺序
运行中的 parent 在同一条 next-step FIFO 中接收已接受的 child 消息与该 child 随后的结算通知。如果 parent 在结算到达前变为空闲,它已经领取 child 消息;结算随后可以开启后续轮次,而不会颠倒观察顺序。
parent 处于 maintenance 时,child 消息占用 next-step 并锁存一次唤醒,而结算可能因 maintenance 报告空闲状态而占用 next-turn。初始领取仍会先取 next-step 输入,再取排队轮次。取消后提交的唤醒输入遵循核心 Agent 的取消收敛,而不会绕过它。
验证
控制工具测试套件让 parent 保持在活跃模型请求中,提交 child 消息、结算 child,并验证 sender 身份、Steer 准入、FIFO 批处理与结算后保留。继续执行覆盖固定驻留可继续 parent 的唤醒准入记账,并让 runtime 所有的结算来源与 agent-message 保持不同。
无密钥可继续 subagent 快照使用随附的固定投递。其 child 可见工具 schema 与 parent 相同,且已接受的 child 消息先于之后的结算通知,无需调度 overlay。
考虑过的替代方案
提供静默投递。 空闲 parent 停驻后可能永远不读取静默消息。它还会让等价的模型编写消息具有不同存活语义,并重新引入依赖部署的顺序。
提供 next-turn 投递。 较晚的 next-step 结算通知仍可能越过它。保持消息先于结算需要跨队列顺序屏障,而当前没有模型操作对后续轮次隔离的需求强到足以承担该机制。
把结算通知移到 next-turn。 结算批处理使用 next-step 队列,使多个 child 同时结束只消耗 parent 的一个 step,而不是每个 child 一个轮次。移动结算会为了保留不必要的消息调度模式而增加延迟与模型工作。
后果
- child 消息可以延长开放的 parent 轮次。它绝不会中断活跃模型请求或工具执行;agent loop 只在 step 边界接纳它。
- 一起被接受的消息共享一个 next-step 批次,保持 FIFO 顺序并限制轮次放大。
- 模型调用方不能选择投递模式,因此顺序与唤醒行为不会随部署或调用而变化。
- child 到 parent 的发送仍要求直接 parent 保持在线;服务不提供持久 parent mailbox。