bots.json 配置
通过 ~/.botmux/bots.json 配置机器人。运行 botmux setup 交互式创建,或手动编辑。文件是一个数组,每个元素是一个 bot(生产环境一个 bot 对应一个独立 daemon 进程)。
多数字段可选——只填
larkAppId/larkAppSecret就能跑起来,其余按需增配。适用:想手动调 CLI / 模型 / 工作目录 / 权限 / 沙箱等;日常配置更推荐用 dashboard 的 Bot 配置页(改的是同一份bots.json)。改完botmux restart生效。
字段较多,按用途分组列出,绝大多数都是可选的——只填 larkAppId / larkAppSecret 就能跑起来,其余按需增配。
必填
CLI 与模型
nativeSubagentRuntime 只改写 Trae 原生 spawn_agent 创建的新子代理,不改变父代理自身配置。缺少某一维时透传子代理请求中的原值;custom 使用固定值。自定义模型和自定义思考强度同时设置时,BotMux 会校验该组合是否受 Trae 支持。切换到其它 CLI 会自动删除此字段。Dashboard 中“透传子代理请求”对应字段缺失;该策略属于 Bot 行为配置,克隆 Bot 时会复制,但不会进入可移植 Agent preset。旧版 mode: "inherit" 配置无效且不会生效。
群级新话题默认模型
每个 Bot 的 groupDefaultModels 独立配置;不同群、不同 Bot 的模型互不影响。Dashboard 中的 CLI 跟随 Bot 的 Agent 配置,只显示当前 CLI 的模型和思考强度。下拉列表复用 Agent 配置的静态候选、实时模型探测及强度校验,支持继承默认值和自定义模型名称。旧版模型字符串配置仍兼容。
新话题创建时保存该群的模型快照。后续修改或清空群配置只影响新话题,已有话题在重启、恢复时仍使用创建时的群模型。话题首次选择另一种 CLI 时只使用该 CLI 对应的快照,不会把 Claude 模型传给 Codex。未配置群模型的话题继续使用原有 Bot 默认模型规则;没有 Bot 模型时由 CLI 自行选择。私聊、普通群的 chat-scope 会话和外部接管会话不使用此快照。
优先级:显式触发模型 > 新话题保存的群模型 > 同 CLI 的 Bot 模型 > 原有 CLI 不匹配回退。思考强度也在新话题创建时保存,显式触发参数仍可覆盖。此配置不改变 CLI 类型或运行环境。
Dashboard 保存后无需重启 daemon。模型、思考强度分别选择“继承 Agent”可取消相应覆盖;两项都继承时删除当前 CLI 的覆盖,保留其它 CLI 的历史配置。手动编辑 bots.json 则沿用原有配置加载方式。
CLI 限额自动交接
quotaFallbackBot 让 daemon 在当前 CLI 确认进入额度限制状态时,用固定文案在原会话落点真实 @ 一个备用 Bot。它不调用已耗尽额度的主模型,也不会改变原有的限额卡片或 owner 通知。

targetAppId必须是备用 Bot 的稳定飞书 App ID;不要配置或复制ou_xxx,因为open_id按发送应用隔离。daemon 会在发送时从当前群的实时成员解析接收方视角下的 mention handle。kinds可选usage(用量上限)和 / 或rate(速率限制);省略时两类都处理。message省略时使用示例中的默认文案,最多 1000 字符,不能为空或包含原生<at>标签。- 目标必须是本机已配置且当前确实在群内的 Bot;跨部署 / 团队目录目标暂不支持,因为 daemon 目前无法安全证明远端 App ID 对应哪个实时
open_id。非本机目标、self、不在群或实时解析失败都会安全跳过。 - 保存和复制 Bot 时会用「即将落盘」的完整配置检查交接图,拒绝 self 和
A → B → C → A这类环路;无环链可以继续级联。若手工修改配置引入环路,botmux start/restart会跳过环路中的 Bot,但仍启动 Dashboard 和无关 Bot;Dashboard 的 Bot 配置列表会标记这些未启动 Bot,并允许在「高级 → 额度耗尽交接」直接修复,保存后重启即可恢复。supervisor 重拉 daemon 时仍会在加载层禁用环路交接并记录 warning,避免异常配置扩大影响。

- daemon 内按「源 Bot + 限额类型」在所有会话间做 5 分钟去重;身份解析或发送失败也会占用这个去重窗口,避免短时重试风暴。
- chat-scope 会落回原群,thread-scope 会落回原话题;上下文由备用 Bot 自己读取当前历史。daemon 重启恢复旧限额状态时不会补发历史交接。
- 整个配置块缺省或
enabled不为true时完全关闭,保持旧行为。可在 Dashboard「Bot 配置 → 高级 → 额度耗尽交接」配置,也可手工编辑bots.json。
Codex 兼容发行版
如果一个独立发行的 CLI 完整保留 Codex 的参数、交互、rollout / resume 和认证语义,不需要为它新增 cliId。保留协议适配器 cliId: "codex",再声明具体运行时:
id是稳定身份,只能使用字母、数字、.、_、-,最长 64 个字符;改名会被视为切换发行版。executable是一个可执行文件名或路径,不是 shell 命令;不要在里面拼参数。Dashboard 保存时会执行只读的--version预检,输出需包含可识别的X.Y.Z版本号。displayName只影响卡片、状态与 Dashboard 展示,省略时使用id。update.provider可选auto、self、npm、none。auto只信任可精确追溯到该二进制的唯一 npm 包;无法确定来源时标记为“未托管”,绝不拿官方 Codex 的版本号比较。self才会使用 CLI 自报的结构化 doctor 信息,并要求其中的当前版本与--version一致;npm必须同时给自己的packageName;none关闭该运行时的更新检查。cliRuntime目前只支持cliId: "codex",不能和wrapperCli同时使用。BotMux 写入配置时会生成一个与executable完全相同的cliPathOverride降级影子;新版本以cliRuntime为准,旧版本仍能从影子启动同一二进制。手工配置时也必须像上例一样同时写入这个等值影子;缺失或不相等都会直接校验失败,避免出现只能升级、不能安全降级的配置。wrapper / 网关仍走下面的旧入口覆盖机制。- 旧
cliPathOverride配置不会失效;BotMux 会继续启动它,并对更新探测采取同样的安全auto策略。Dashboard 会把它显示为只读兼容态:只改模型会保留旧入口,显式选择 Official Codex 才会清除,也可选择“自定义兼容版”迁移到cliRuntime。由于旧字段无法证明完整兼容契约,Codex RPC 等增强能力仍保持关闭。
会话创建时会冻结自己的 runtime 快照。只修改模型仅影响新会话;切换 CLI、runtime 或 wrapper 时,BotMux 会立即关闭仍使用旧启动身份的活跃会话,避免它们之后 lazy resume 到错误的发行版。存量会话不会被静默换用另一 runtime。
接入 GLM / 第三方服务商(per-bot env)
让某个 bot 跑 GLM Coding Plan(或其它 Anthropic 兼容服务商),另一个 bot 仍跑官方 Claude——给前者配 env:
- GLM 国内站把
ANTHROPIC_BASE_URL换成https://open.bigmodel.cn/api/anthropic。 - 给 Codex 这类 OpenAI 协议 CLI 接入时,填
OPENAI_BASE_URL/OPENAI_API_KEY(服务商的 OpenAI 兼容端点)而非ANTHROPIC_*。 - 隔离:env 按会话注入到 CLI 进程,全后端一致(tmux / zellij 经每个 pane 注入,绝不写共享 server 全局),所以一个 bot 的服务商配置不会串到别的 bot。
- 安全:值以明文存在
bots.json与进程环境,不是密钥保险箱;/config get等聊天面会脱敏显示(dashboard 编辑器 owner 鉴权后显示原值)。 - 改完下个新会话生效。
Codex App 纯净输入(实验性)
codexAppCleanInput 用于清理 Codex App 中显示的用户消息,同时保留 Botmux 调用模型所需的上下文。默认值为 false / off,关闭时完全沿用原来的组合 prompt 行为。
可由 owner / allowedUsers 通过 /botconfig 热更新,无需重启 daemon:
也可直接写进对应 bot 的配置(手改 bots.json 后仍按本文末尾说明重启):
- 仅 Botmux 托管且 session 实际 CLI 为
codex-app时使用此开关;其它 CLI 和/adopt外部桥接 session 不受影响。session 已冻结的 CLI 优先于后来修改的 bot 默认 CLI。 - 开启后,用户发起的 turn 以用户原文作为 Codex App 的文本
UserMessage;Botmux 自己发起的 external trigger、文档预热等合成 turn 使用简短可读标签。sender、mentions、附件路径、引用、role、whiteboard、Skills 和合成 turn 的内部指令等上下文主要通过隐藏的additionalContext提供。可读的绝对路径图片还会作为localImage输入;缺失、相对或不可读图片会跳过原生图片项并记录提示,但附件路径仍留在上下文中。 - 可识别的 Codex CLI
>= 0.135才启用纯净文本和additionalContext;>= 0.136时还会附带独立的clientUserMessageId。版本过旧或无法识别时直接使用 legacy 组合 prompt。 - 只有 app-server 在
turn/started前明确拒绝additionalContext/clientUserMessageId实验字段时,runner 才用 legacy prompt 重试一次,并在该 runner 生命周期内关闭纯净模式。网络、超时、模型或一般 turn 错误不会自动重试,以免重复执行。 /botconfig切换在下一次派发给 Codex worker时采样;普通 live 消息通常就是下一条消息,等待 repo 选择的首轮则在 repo commit 时采样。已排队或正在执行的 turn 不会被中途改写,也不会回填既有历史。additionalContext不出现在 Codex App 的普通用户消息气泡中,但仍可能保存在原始 rollout / 诊断记录里。开启时 Botmux 自身也会保留 legacy prompt 与结构化 sidecar 以支持兼容降级和retry_last_task。此功能只解决 App 展示与普通历史阅读的整洁度,不是隐私擦除或安全脱敏机制。
Codex App 浏览器桥接(实验性)
此能力只解决 Botmux 以 app-server 协议运行 Codex 时无法继承 Codex App 内置 Chrome 工具的问题。它是 Botmux 自身的可选适配层,不依赖任何业务仓库、Harness 或本地代理工程。
- 需要先在同一 OS 用户的 Chrome / Edge 中安装并启用 Codex 浏览器扩展;Botmux 默认从
CODEX_HOME(或~/.codex)的官方插件缓存中选择最新完整版本。只有维护自定义插件目录时才填写绝对路径pluginRoot。 - 需要安装 Codex 桌面端附带的浏览器运行时。桥接优先使用
mcp_servers.node_repl配置;桌面端移除该 MCP 注册项时,会从已安装的桌面端定位运行时,自定义安装位置可设置BOTMUX_CODEX_NODE_REPL_PATH。身份、站点安全状态和功能配置均走官方认证请求通道,不自行读取或保存登录令牌;运行时缺失或登录失败时会中止操作,不降级为匿名请求。 - 开启后会在新建和恢复 Codex App thread 时注册
botmux_browser动态工具。已运行的 runner 需重启或重新恢复会话,才能加载更新后的工具定义。 - 工具先按标签页探测能力:优先使用可访问性树;AX 不可用时自动回退到可见 DOM / Playwright DOM,并提供受类型约束的 Playwright locator、DOM 和坐标交互。不会因为某个后端缺少
tab.ax而中断整个 Chrome 连接。 - Browser Use 发出的站点访问、上传、下载等安全确认会阻塞当前操作并投射为飞书授权卡;只有通过 Botmux
canTalk校验的用户可以选择“本会话允许 / 始终允许 / 拒绝”,回答和回答人由 Botmux ask 记录。普通“允许”也只授予当前 runner 会话,后续同一站点、操作类型和风险上下文自动复用;不同站点、操作类型、风险上下文或新会话仍会重新确认。拒绝、超时、daemon 不可达均 fail closed。 - 工具不暴露任意 JavaScript、raw CDP、cookie、local storage、浏览历史或剪贴板。上传/下载只通过 Browser Use 的受控文件选择器和安全确认执行;需要密码等秘密输入的 secure browser-auth 流程不会降级到普通飞书卡片,必须由支持安全凭证 broker 的客户端处理。
- 每个 Botmux runner 独立持有浏览器会话状态;默认关闭,未配置的 bot 启动参数和行为完全不变。
- 当前不支持与
existingAppServer、sandbox或readIsolation组合,配置冲突会在启动时直接报错,避免以不完整隔离边界运行。
工作目录
权限与授权
文件沙盒
ZMX 无法执行文件沙盒或实际生效的读隔离,开启这些边界的配置组合会 fail closed,详见 ZMX 后端边界。
卡片与终端
Dashboard 的「Bot 配置 → 消息卡片 → 实时卡片按钮」提供同一配置的可视化开关:

Prompt 注入
关掉后模型看不到发言人身份:多人会话里无法区分谁说的、也无法按人称呼。适合模型会把标签内容抄进回复正文的 CLI(如 cursor,见 <sender_note> 反抄写提示——标签关掉后该提示也一并消失),或不希望把每条消息的身份写进 CLI 记录的场景。
可由 owner / allowedUsers 通过 /botconfig 热更新,无需重启 daemon:
也可直接写进对应 bot 的配置:
botmux send --mention-back不受影响:它读的是 daemon 侧独立记录的本轮触发者(replyTargets[turnId].senderOpenId),与 prompt 里的这个标签是两条链路。- 关闭有两项可观测性代价:①
/adopt少一条识别「本 bot 自产会话」的指纹(其余结构判据仍覆盖现有 prompt 形态,不会因此把自产会话当外部会话列出);② dashboard 会话洞察无法再从标签判断发言人类型与 A2A 对方名字,只能靠[来自 … 的 @mention]交棒文本标记兜底,没有该标记时该轮不显示来源。 - 立即生效(下一轮起),不改写已排队或正在执行的 turn,也不回填既有历史。
- dashboard「发言人标签」开关保存的就是这个字段。
主动开工
群消息监听
让 Bot 主动盯住某个群:命中条件的群消息无需 @ 就自动拉起一个会话去处理。典型用途是报警运维——监控/告警系统本来就有自己的飞书机器人在往群里发告警,把这个 Bot 拉进那个群、开启监听,每条告警自动开工排查,不必额外配 Webhook 接入点。
推荐在 Dashboard「角色 → 消息监听」 里按群配置(可预览最近 24h 命中的消息、试运行验证效果);也可直接写 bots.json 的 messageListeners(键为 chat_id,值为下表配置):
约定与边界(V1):
- 只处理群聊顶层消息:已有话题里的普通回复不处理;显式 @ 本 Bot 的消息仍走普通 @ 路由(不重复触发)。
- 每条命中消息各拉起一个会话,回复到该消息下方的新话题。
- 触达方式:实时事件路径覆盖飞书推送到的消息;其他机器人发的、以及未 @ 的消息,靠约 30s 一次的历史轮询补齐(即最长约 30s 延迟)。所以监听第三方告警机器人时用黑名单模式(
all_except_excluded+ 含"bot")最稳——白名单按open_id匹配,而历史接口里第三方机器人按app_id上报、可能解析不出open_id从而命中不到。
总结命令
示例:
- 只有显式
@机器人 /summary会触发总结;不 @ 机器人时仍按普通群/话题的既有路由规则处理,不会因为关键词自动唤醒。 - dashboard 的「/summary 总结范围」保存的就是
summaryRange;「开启记忆」开关与「记忆文件路径」输入框分别保存summaryMemory与summaryMemoryPath。 - 如果本次触发前存在上一条
@同一机器人 /summary,总结窗口只包含上一条之后到本次触发为止的消息;找不到上一条时回退到limit/sinceHours。 limit与sinceHours是默认(无显式边界)总结窗口的安全上限;两者都为0时表示不做该维度限制。显式边界按设计优先于该上限:当summaryMemory开启且/summary带了边界文字时,botmux 尊重用户「从这条起」的明确意图,从命中的边界消息起全部纳入——普通群里limit仍约束扫描量,但比sinceHours更早的边界、以及话题群里任意早的边界都会被接受,可能超出默认配置范围。若不希望某个 bot 读入过旧内容,最可靠的做法是不要带边界文字;普通群还可以调低limit约束扫描量(但sinceHours、以及话题群里的边界都不受配置范围约束)。- 仅当
summaryMemory开启时,/summary命令后跟随的文字会被当作「硬边界」:在触发前的历史里定位最近一条包含该文字的消息,只总结从这条到本次触发为止的内容;如果扫描到的历史里找不到该边界,则不回退到更宽范围,而是把「未找到边界」错误与空历史一起交给 agent(此时记忆写入指令仍会执行)。summaryMemory关闭时,/summary后的文字仅作为对本次总结的侧重提示,历史窗口仍按summaryRange读取。 - 记忆文件由 agent 在其工作目录内写入。如果 bot 开启了 sandbox,且
summaryMemoryPath指向工作目录之外(绝对路径,或用../逃出工作目录的相对路径),请把该文件已存在的父目录加进sandboxPaths.readWrite;worker 在 spawn 时会过滤掉尚不存在的路径,而新记忆文件通常还不存在,所以只加文件本身会被丢弃(除非文件已预先创建)。否则写入可能被沙盒拒绝。
旧内容触发配置
语音
会议监听角色与群内输出形式
vcMeetingAgent.meetingConsumer.consumerProfiles 可以定义通用的会议监听角色。responseMode 与 listenerDelivery.placement 是两个独立维度:
Dashboard 的“会议角色预设”提供本地内置模板库,当前包含“会议重要信息同步”“会议纪要与行动项”“会议主持”“方案评审与风险挑战”“访谈与需求洞察”。点击“使用此模板”会复制出一个普通、可完整编辑的 profile;之后修改模板不会改写用户配置。模板目录带稳定的 templateId、版本和来源,未来可以在同一模型上接入社区源。本期不联网、不上传模板使用情况,因此不提供热度或使用量排行。
responseMode: "silent":自动模型输出不可见;适合只做内部处理或通过受管会议能力执行动作。responseMode: "listener_thread":允许把自动模型输出发到会议监听群,需要listener.output.requestcapability。listenerDelivery.placement: "auto":兼容旧行为,沿用当前会话的群/话题路由;省略该字段等同于auto。listenerDelivery.placement: "chat":每次同步都作为群顶层消息发送。listenerDelivery.placement: "topic":首条有效同步作为固定话题根消息,后续同步都回复到同一话题;移除并重新启用该 profile 后会开启新话题。
listener_thread 的自动输出使用 botmux 内部的 skip | publish 控制协议:Agent 判断当前是否值得发布,botmux 只在 publish 时把消息正文发到飞书,控制 JSON 本身不会出现在群里。该协议不做语义指纹去重,也不提供 debounce/interval 配置;是否为新信息、是否继续观察以及何时发布,都由 Agent 根据 profile prompt 和完整会议上下文判断。格式异常会 fail closed,不会把模型原始控制文本发到群里。显式人工消息仍按原引用关系回复,不走此协议。
下面是一个“会议重要信息同步”预设。它不包含事故专用结构,只通过 prompt 定义“什么值得同步”,因此也适用于项目评审、发布协调等会议:
agentAppId 是实际执行该角色的 bot App ID。把 profile id 加入 defaultConsumerIds,并将 defaultMode 设为 agents,可让它在监听开始时默认启用;否则可在会中消费者选择卡片里手动启用。
运行时状态(自动维护,勿手改)
下列字段由 botmux 自身写入并随授权 / 开关一起持久化进 bots.json,列出仅为说明,不要手动编辑:
配置优先级:
BOTS_CONFIG环境变量 →~/.botmux/bots.json。改完跑botmux restart生效。
