命令队列(Command Queue,2026-01-16)
我们会通过一个轻量的进程内队列,将所有渠道的入站自动回复 runs 串行化,以防多个 agent runs 相互冲突;同时仍允许在不同 sessions 之间进行安全并行。
为什么(Why)
- 自动回复 runs 可能很昂贵(LLM 调用),并且当多条入站消息在短时间内到达时可能互相冲突。
- 串行化可以避免争抢共享资源(session files、logs、CLI stdin),并降低触发上游限流的概率。
工作方式(How it works)
- 一个“按 lane 感知”的 FIFO 队列会按 lane 依次出队,每个 lane 具有可配置的并发上限(未配置的 lanes 默认 1;
main默认 4,subagent默认 8)。 runEmbeddedPiAgent会按 session key 入队(lanesession:<key>),以保证每个 session 同时只有一个 active run。- 每个 session run 随后还会进入一个 全局 lane(默认
main),从而使整体并行度受agents.defaults.maxConcurrent限制。 - 启用 verbose logging 时,如果某个 run 在开始前等待了超过约 2 秒,会输出一条短提示。
- typing indicators 仍会在入队时立即触发(渠道支持时),因此用户体验在等待排队时不变。
队列模式(per channel)
入站消息可以“引导(steer)”当前 run、等待一个 followup 回合,或两者都做:
steer:立即注入到当前 run(在下一个 tool 边界之后取消尚未执行的 tool calls)。如果当前 run 不在 streaming,则回退为 followup。followup:在当前 run 结束后,为下一次 agent 回合入队。collect:将所有排队消息合并为单个 followup 回合(默认)。如果消息指向不同的 channels/threads,会分别出队以保持路由一致。steer-backlog(也叫steer+backlog):现在 steer 并且保留消息以便后续 followup。interrupt(legacy):中止该 session 的 active run,然后运行最新消息。queue(legacy alias):等同于steer。
steer-backlog 意味着你可能在 steered run 之后还能得到一个 followup 响应,因此在 streaming 的对外表面上看起来像“重复回复”。如果你希望每条入站消息只产生一次回复,优先用 collect/steer。
将 /queue collect 作为独立命令(per-session)发送,或设置 messages.queue.byChannel.discord: "collect"。
默认值(未在 config 设置时):
- 所有表面 →
collect
通过 messages.queue 全局或按渠道配置:
json5
{
messages: {
queue: {
mode: "collect",
debounceMs: 1000,
cap: 20,
drop: "summarize",
byChannel: { discord: "collect" }
}
}
}队列选项(Queue options)
这些选项适用于 followup、collect 与 steer-backlog(并且当 steer 回退为 followup 时也适用):
debounceMs:在开始 followup 回合前等待一段“安静期”(避免出现“continue, continue”)。cap:每个 session 最大排队消息数。drop:溢出策略(old、new、summarize)。
summarize 会保留被丢弃消息的简短 bullet 列表,并作为合成的 followup prompt 注入。 默认:debounceMs: 1000、cap: 20、drop: summarize。
Per-session 覆盖
- 将
/queue <mode>作为独立命令发送,可将该 mode 存入当前 session。 - 选项可组合:
/queue collect debounce:2s cap:25 drop:summarize /queue default或/queue reset会清除 session 覆盖。
作用范围与保证(Scope and guarantees)
- 对所有使用 gateway reply pipeline 的入站渠道的 auto-reply agent runs 生效(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、webchat 等)。
- 默认 lane(
main)在进程范围内用于入站 + 主心跳;设置agents.defaults.maxConcurrent可允许多个 sessions 并行。 - 可能存在额外 lanes(例如
cron、subagent),以便后台任务并行运行而不阻塞入站回复。 - 每个 session 的 lane 保证同一时刻只有一个 agent run 会触碰该 session。
- 无外部依赖或后台 worker 线程;纯 TypeScript + promises。
排查(Troubleshooting)
- 如果命令看起来卡住了,启用 verbose logs 并查找类似 “queued for …ms” 的日志,以确认队列正在出队。
- 如果需要队列深度信息,启用 verbose logs 并观察队列耗时相关日志。