docs(agent): clarify late steering timing
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write
|
||||
2026-07-17-one-send-one-turn.md: 852a2f24d33d88933568fe1d1d937e10003202df
|
||||
2026-07-17-one-send-one-turn.zh.md: f40086ee202bf74e4207081a402737d86e9dfa87
|
||||
2026-07-17-one-send-one-turn.md: 7eec39e1e5b4678c9d454260f326929f4beff6c9
|
||||
2026-07-17-one-send-one-turn.zh.md: f28c93929045b3fcb0f2df8ff3c33adfb8a308ae
|
||||
|
||||
@@ -10,7 +10,7 @@ An ordinary `Agent.send()` payload is one complete caller message. Opportunistic
|
||||
|
||||
An ordinary turn contains prompt admission, `turn/start`, `turn/end`, and the durability checkpoint. Combining messages would let a later ordinary message join an earlier message's model request instead of observing the earlier ordinary turn's closed result in the same session log, while mixed allowed and blocked prompts would require lifecycle states no caller explicitly requested.
|
||||
|
||||
`steer()` already expresses joining the active turn, while `inject()` records model-facing context without acting as an ordinary message. Implicit ordinary-send batching would make `send()` overlap both explicit operations instead of preserving a single meaning.
|
||||
`steer()` already selects steering semantics while the agent driver is running, while `inject()` records model-facing context without acting as an ordinary message. Implicit ordinary-send batching would make `send()` overlap both explicit operations instead of preserving a single meaning.
|
||||
|
||||
## Decision
|
||||
|
||||
@@ -18,7 +18,7 @@ Each successful `send()` synchronously validates agent state, snapshots and free
|
||||
|
||||
Prompt admission decides one message. An allowed prompt becomes that turn's `user/message`; a blocked prompt appends one durable `prompt/blocked` and ends that one-message turn as `rejected`. There are no mixed-batch or all-blocked-batch branches.
|
||||
|
||||
Running `steer()` appends to the active turn's steering FIFO. Idle `steer()` delegates to `send()` and therefore creates an independent ordinary queue item. `inject()` retains its turn-enclosure and flush behavior. `cancel()`, `status`, and `whenIdle()` remain whole-agent operations rather than per-message controls.
|
||||
Running `steer()` adds to the steering FIFO. An open turn records it at the next steering checkpoint before a request or continuation decision. Steering can make continuation default to another step, but continuation or terminal policy can still stop before that step begins. After turn close and its durability checkpoint, remaining steering becomes later queued input. Terminal `agent/turn-stop`, cancellation, or disposal may discard it. Idle `steer()` delegates to `send()` and therefore creates an independent ordinary queue item. `inject()` retains its turn-enclosure and flush behavior. `cancel()`, `status`, and `whenIdle()` remain whole-agent operations rather than per-message controls.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
@@ -30,10 +30,10 @@ Running `steer()` appends to the active turn's steering FIFO. Idle `steer()` del
|
||||
- A real-composition test pipes two lines through the built stdio binary and observes two model requests and two turn boundaries.
|
||||
- A deferred first ordinary-turn flush proves the next queued ordinary turn cannot start before the checkpoint settles and that its request sees the preceding assistant result; a rejected flush still settles before the next ordinary turn starts.
|
||||
- Prompt veto and listener failure, broad cancellation, disposal, and pre-commit `turn/start` failure preserve balanced recorded turns and do not merge or strand surviving queued work.
|
||||
- Running and idle `steer()`, `inject()`, whole-agent status, and `whenIdle()` retain their existing coverage.
|
||||
- Open-turn, post-turn-close, and idle `steer()`, `inject()`, whole-agent status, and `whenIdle()` retain their existing coverage.
|
||||
|
||||
## Consequences
|
||||
|
||||
Ordinary turn boundaries are deterministic, and a FIFO successor that reaches turn processing observes the preceding completed ordinary turn's closed session result after that turn's checkpoint settles; settlement does not mean a failed flush became durable. Several queued items can still run under one global `running` interval, and broad cancellation can discard the entire unstarted tail, so status and quiescence remain agent-wide observations rather than per-message results.
|
||||
Ordinary turn boundaries are deterministic, and a FIFO successor that reaches turn processing observes the preceding completed ordinary turn's closed session result after that turn's checkpoint settles; settlement does not mean a failed flush became durable. Several queued items can still run under one global `running` interval, which can also cover turn close and its checkpoint, so `running` does not prove a turn is open. Broad cancellation can discard the entire unstarted tail, and status and quiescence remain agent-wide observations rather than per-message results.
|
||||
|
||||
Workloads that relied on coincidental ordinary-send batching make more model requests, incur more checkpoints, and may take longer to drain; FIFO queues may grow under sustained producers. Ordinary-send batching can return only through an explicit measured contract.
|
||||
|
||||
@@ -10,7 +10,7 @@ Status: implemented
|
||||
|
||||
普通轮次包含提示词准入、`turn/start`、`turn/end` 和持久性检查点。合并消息会让后一条普通消息加入前一条普通消息的模型请求,无法观察同一会话日志中前一个已关闭普通轮次的结果;获准与被阻止提示词的混合还会引入调用方从未显式请求的生命周期状态。
|
||||
|
||||
`steer()` 已经用于表达加入当前轮次,`inject()` 则记录面向模型的上下文而不充当普通消息。普通 send 的隐式批处理会让 `send()` 与这两种显式操作产生语义重叠,无法保持单一含义。
|
||||
`steer()` 已经用于在 agent(智能体)驱动器运行时选择 steering(中途引导)语义,`inject()` 则记录面向模型的上下文而不充当普通消息。普通 send 的隐式批处理会让 `send()` 与这两种显式操作产生语义重叠,无法保持单一含义。
|
||||
|
||||
## 决策
|
||||
|
||||
@@ -18,7 +18,7 @@ Status: implemented
|
||||
|
||||
提示词准入只处理一条消息。获准提示词成为该轮次的 `user/message`;被阻止提示词追加一条持久的 `prompt/blocked`,并让这个单消息轮次以 `rejected` 结束。实现中没有混合批次或全阻止批次分支。
|
||||
|
||||
运行中的 `steer()` 会把消息追加到当前轮次的 steering(中途引导)FIFO。空闲时的 `steer()` 委托给 `send()`,因此创建一个独立的普通队列项。`inject()` 保持现有的轮次封闭与持久化刷新行为。`cancel()`、`status` 和 `whenIdle()` 仍是面向整个 agent 的操作,不变成逐消息控制。
|
||||
运行中的 `steer()` 会把消息加入 steering(中途引导)FIFO。打开的轮次会在下一个 steering 检查点、请求或 continuation 决策之前记录该消息。Steering 可以让默认 continuation 决策进入下一步骤,但 continuation 或终止策略仍可在该步骤开始前停止轮次。轮次关闭且其持久性检查点处理结束后,剩余的 steering 会成为后续排队输入。终止性的 `agent/turn-stop`、取消或 dispose(资源释放)可能丢弃该消息。空闲时的 `steer()` 委托给 `send()`,因此创建一个独立的普通队列项。`inject()` 保持现有的轮次封闭与持久化刷新行为。`cancel()`、`status` 和 `whenIdle()` 仍是面向整个 agent 的操作,不变成逐消息控制。
|
||||
|
||||
## 曾考虑的替代方案
|
||||
|
||||
@@ -30,10 +30,10 @@ Status: implemented
|
||||
- 真实组合测试会通过 stdio 构建产物同时写入两行,并观察两个模型请求和两个轮次边界。
|
||||
- 延迟第一个普通轮次的持久化刷新可以证明下一个排队的普通轮次不能在检查点处理结束前开始,且其请求能看到前一条助手结果;刷新即使失败,下一个普通轮次也要等它结束后才会开始。
|
||||
- 提示词否决、监听器失败、广义取消、dispose 和 `turn/start` 提交前失败都会保持已记录轮次边界平衡,不会合并消息或让仍应处理的排队工作滞留。
|
||||
- 运行中与空闲时的 `steer()`、`inject()`、面向整个 agent 的状态和 `whenIdle()` 保持原有覆盖。
|
||||
- 轮次打开时、轮次关闭后与空闲时的 `steer()`、`inject()`、面向整个 agent 的状态和 `whenIdle()` 保持原有覆盖。
|
||||
|
||||
## 后果
|
||||
|
||||
普通轮次边界是确定的;FIFO 后继项进入轮次处理时,会观察前一个已完成普通轮次在会话中已关闭的结果;检查点处理结束不表示失败的持久化刷新已经成功。多个排队项仍可在同一个全局 `running` 区间内执行,广义取消也可以丢弃整个未启动队尾,因此状态和静止性仍是面向整个 agent 的观察,而不是逐消息结果。
|
||||
普通轮次边界是确定的;FIFO 后继项进入轮次处理时,会观察前一个已完成普通轮次在会话中已关闭的结果;检查点处理结束不表示失败的持久化刷新已经成功。多个排队项仍可在同一个全局 `running` 区间内执行,该区间也可以覆盖轮次关闭及其检查点,因此 `running` 不表示轮次必然仍然打开。广义取消可以丢弃整个未启动队尾,状态和静止性仍是面向整个 agent 的观察,而不是逐消息结果。
|
||||
|
||||
依赖普通 send 偶然批处理的工作负载会产生更多模型请求和检查点,队列清空时间也可能延长;持续有消息进入时,FIFO 队列还可能增长。只有建立显式且经过测量的契约后,才能重新引入普通 send 批处理。
|
||||
|
||||
Reference in New Issue
Block a user