命令队列

命令队列 (2026-01-16)

我们通过一个小型进程内队列序列化入站自动回复运行(所有频道),以防止多个 agent 运行冲突,同时仍然允许跨会话的安全并行。

为什么

  • 自动回复运行可能很昂贵(LLM 调用),并且当多个入站消息紧密到达时可能冲突。
  • 序列化避免竞争共享资源(会话文件、日志、CLI stdin)并减少上游速率限制的机会。

如何工作

  • 车道感知 FIFO 队列以可配置的并发上限排出每个车道(默认 1 用于未配置的车道;main 默认 4,subagent 默认 8)。
  • runEmbeddedPiAgent会话键(车道 session:<key>)入队,以保证每个会话只有一个活动运行。
  • 然后每个会话运行入队到全局车道(默认 main),因此整体并行性由 agents.defaults.maxConcurrent 上限。
  • 启用详细日志时,如果排队运行在开始之前等待超过 ~2 秒,则发出简短通知。
  • 打字指示器仍然在入队时立即触发(当频道支持时),因此用户体验在我们等待时不变。

队列模式(每频道)

入站消息可以转向当前运行、等待后续轮次,或两者都做:

  • steer:立即注入到当前运行(在下一个工具边界后取消待定工具调用)。如果不流式传输,回退到 followup。
  • followup:在当前运行结束后为下一个 agent 轮次排队。
  • collect:将所有排队消息合并到单个后续轮次(默认)。如果消息针对不同频道/线程,它们单独排出以保持路由。
  • steer-backlog(又名 steer+backlog):现在转向保留消息用于后续轮次。
  • interrupt(遗留):中止该会话的活动运行,然后运行最新消息。
  • queue(遗留别名):与 steer 相同。

Steer-backlog 意味着你可以在转向运行后获得后续响应,因此流式表面可能看起来像重复。如果你希望每个入站消息一个响应,优先使用 collect/steer。 发送 /queue collect 作为独立命令(每会话)或设置 messages.queue.byChannel.discord: "collect"

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

  • 所有表面 → collect

通过 messages.queue 全局或每频道配置:

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

队列选项

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

  • debounceMs:在开始后续轮次之前等待安静(防止"continue, continue")。
  • cap:每会话最大排队消息。
  • drop:溢出策略(oldnewsummarize)。

Summarize 保留丢弃消息的简短项目符号列表,并将其作为合成后续提示注入。 默认:debounceMs: 1000cap: 20drop: summarize

每会话覆盖

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

范围和保证

  • 适用于使用 gateway 回复管道的所有入站频道的自动回复 agent 运行(WhatsApp web、Telegram、Slack、Discord、Signal、iMessage、webchat 等)。
  • 默认车道(main)是进程范围的,用于入站 + 主心跳;设置 agents.defaults.maxConcurrent 以允许多个会话并行。
  • 可能存在额外车道(例如 cronsubagent),因此后台作业可以并行运行而不会阻塞入站回复。
  • 每会话车道保证只有一个 agent 运行在给定时间触及给定会话。
  • 无外部依赖或后台工作线程;纯 TypeScript + promises。

故障排除

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