命令队列 (2026-01-16)

我们通过一个轻量级的进程内队列来串行化所有 Channel 的入站自动回复运行,防止多个 Agent 运行相互冲突,同时仍然允许跨 Session 的安全并行。

为什么需要队列

  • 自动回复运行可能很昂贵(LLM 调用),当多条入站消息几乎同时到达时可能会发生冲突。
  • 串行化可以避免竞争共享资源(Session 文件、日志、CLI 标准输入),并减少触发上游速率限制的可能性。

工作原理

  • 一个支持 lane(通道)的 FIFO 队列,每个 lane 都有可配置的并发上限(未配置的 lane 默认为 1;main 默认为 4,subagent 默认为 8)。
  • runEmbeddedPiAgentsession key 入队(lane 为 session:<key>),保证每个 Session 同时只有一个活跃运行。
  • 每个 Session 运行随后会被排入一个全局 lane(默认为 main),这样整体并行度会被 agents.defaults.maxConcurrent 限制。
  • 当启用详细日志时,如果排队运行等待超过约 2 秒才开始,会发出一条简短通知。
  • 输入指示器仍然会在入队时立即触发(如果 Channel 支持),所以在等待期间用户体验不会改变。

队列模式(按 Channel 配置)

入站消息可以引导当前运行、等待后续轮次,或两者兼而有之:

  • steer:立即注入到当前运行中(在下一个工具边界后取消待处理的工具调用)。如果不是流式传输,则回退到 followup。
  • followup:排队等待当前运行结束后的下一个 Agent 轮次。
  • collect:将所有排队的消息合并到单个 followup 轮次(默认)。如果消息目标是不同的 Channel/线程,它们会单独排空以保留路由。
  • steer-backlog(也叫 steer+backlog):现在引导并且保留消息用于后续轮次。
  • interrupt(旧版):中止该 Session 的活跃运行,然后运行最新消息。
  • queue(旧版别名):与 steer 相同。

Steer-backlog 意味着你可以在引导运行后获得一个后续响应,所以流式传输界面可能看起来像重复。如果你希望每条入站消息对应一个响应,建议使用 collect/steer

发送 /queue collect 作为独立命令(按 Session)或设置 messages.queue.byChannel.discord: "collect"

默认值(配置中未设置时):

  • 所有界面 → collect

通过 messages.queue 全局或按 Channel 配置:

{
  messages: {
    queue: {
      mode: "collect",
      debounceMs: 1000,
      cap: 20,
      drop: "summarize",
      byChannel: { discord: "collect" },
    },
  },
}

队列选项

选项适用于 followupcollectsteer-backlog(以及 steer 回退到 followup 时):

  • debounceMs:在开始后续轮次前等待静默期(防止”继续,继续”)。
  • cap:每个 Session 的最大排队消息数。
  • drop:溢出策略(oldnewsummarize)。

Summarize 会保留一个简短的丢弃消息列表,并将其作为合成的 followup prompt 注入。

默认值:debounceMs: 1000cap: 20drop: summarize

按 Session 覆盖

  • 发送 /queue <mode> 作为独立命令,为当前 Session 存储模式。
  • 选项可以组合:/queue collect debounce:2s cap:25 drop:summarize
  • /queue default/queue reset 清除 Session 覆盖。

作用范围和保证

  • 适用于所有使用 Gateway 回复管道的入站 Channel 的自动回复 Agent 运行(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、webchat 等)。
  • 默认 lane(main)是进程级的,用于入站 + 主 Heartbeat;设置 agents.defaults.maxConcurrent 以允许多个 Session 并行。
  • 可能存在额外的 lane(例如 cronsubagent),这样后台任务可以并行运行而不会阻塞入站回复。
  • 按 Session 的 lane 保证同一时间只有一个 Agent 运行接触给定的 Session。
  • 没有外部依赖或后台工作线程;纯 TypeScript + promises。

故障排除

  • 如果命令似乎卡住了,启用详细日志并查找”queued for …ms”行来确认队列正在排空。
  • 如果你需要队列深度信息,启用详细日志并观察队列计时行。