配置 🔧

OpenClaw 从 ~/.openclaw/openclaw.json 读取可选的 JSON5 配置文件(允许注释和尾随逗号)。

如果文件不存在,OpenClaw 使用相对安全的默认值(嵌入式 Pi agent + 每个发送者的 session + workspace ~/.openclaw/workspace)。通常你只需要配置文件来:

  • 限制谁可以触发机器人(channels.whatsapp.allowFromchannels.telegram.allowFrom 等)
  • 控制群组白名单和提及行为(channels.whatsapp.groupschannels.telegram.groupschannels.discord.guildsagents.list[].groupChat)
  • 自定义消息前缀(messages)
  • 设置 agent 的 workspace(agents.defaults.workspaceagents.list[].workspace)
  • 调整嵌入式 agent 默认值(agents.defaults)和 session 行为(session)
  • 设置每个 agent 的身份(agents.list[].identity)

配置新手? 查看配置示例指南获取带详细解释的完整示例!

严格配置验证

OpenClaw 仅接受完全匹配 schema 的配置。 未知键、格式错误的类型或无效值会导致 Gateway 拒绝启动以确保安全。

当验证失败时:

  • Gateway 不会启动。
  • 仅允许诊断命令(例如:openclaw doctoropenclaw logsopenclaw healthopenclaw statusopenclaw serviceopenclaw help)。
  • 运行 openclaw doctor 查看具体问题。
  • 运行 openclaw doctor --fix(或 --yes)应用迁移/修复。

Doctor 永远不会写入更改,除非你明确选择 --fix/--yes

Schema + UI 提示

Gateway 通过 config.schema 为 UI 编辑器公开配置的 JSON Schema 表示。 Control UI 从此 schema 渲染表单,并提供原始 JSON 编辑器作为应急出口。

Channel 插件和扩展可以为其配置注册 schema + UI 提示,因此 channel 设置在应用程序之间保持 schema 驱动,无需硬编码表单。

提示(标签、分组、敏感字段)与 schema 一起提供,因此客户端可以渲染更好的表单,而无需硬编码配置知识。

应用 + 重启 (RPC)

使用 config.apply 验证 + 写入完整配置并一步重启 Gateway。 它写入重启哨兵并在 Gateway 恢复后 ping 最后活动的 session。

警告:config.apply 替换整个配置。如果只想更改几个键,使用 config.patchopenclaw config set。保留 ~/.openclaw/openclaw.json 的备份。

参数:

  • raw(字符串)— 整个配置的 JSON5 负载
  • baseHash(可选)— 来自 config.get 的配置哈希(当配置已存在时必需)
  • sessionKey(可选)— 用于唤醒 ping 的最后活动 session 键
  • note(可选)— 包含在重启哨兵中的注释
  • restartDelayMs(可选)— 重启前的延迟(默认 2000)

示例(通过 gateway call):

openclaw gateway call config.get --params '{}' # 捕获 payload.hash
openclaw gateway call config.apply --params '{
  "raw": "{\\n  agents: { defaults: { workspace: \\"~/.openclaw/workspace\\" } }\\n}\\n",
  "baseHash": "<hash-from-config.get>",
  "sessionKey": "agent:main:whatsapp:dm:+15555550123",
  "restartDelayMs": 1000
}'

部分更新 (RPC)

使用 config.patch 将部分更新合并到现有配置中,而不会破坏无关的键。它应用 JSON merge patch 语义:

  • 对象递归合并
  • null 删除键
  • 数组替换

config.apply 一样,它验证、写入配置、存储重启哨兵并安排 Gateway 重启(当提供 sessionKey 时可选唤醒)。

参数:

  • raw(字符串)— 仅包含要更改的键的 JSON5 负载
  • baseHash(必需)— 来自 config.get 的配置哈希
  • sessionKey(可选)— 用于唤醒 ping 的最后活动 session 键
  • note(可选)— 包含在重启哨兵中的注释
  • restartDelayMs(可选)— 重启前的延迟(默认 2000)

示例:

openclaw gateway call config.get --params '{}' # 捕获 payload.hash
openclaw gateway call config.patch --params '{
  "raw": "{\\n  channels: { telegram: { groups: { \\"*\\": { requireMention: false } } } }\\n}\\n",
  "baseHash": "<hash-from-config.get>",
  "sessionKey": "agent:main:whatsapp:dm:+15555550123",
  "restartDelayMs": 1000
}'

最小配置(推荐起点)

{
  agents: { defaults: { workspace: "~/.openclaw/workspace" } },
  channels: { whatsapp: { allowFrom: ["+15555550123"] } }
}

首次构建默认镜像:

scripts/sandbox-setup.sh

自聊模式(推荐用于群组控制)

防止机器人响应 WhatsApp 群组中的 @-提及(仅响应特定文本触发器):

{
  agents: {
    defaults: { workspace: "~/.openclaw/workspace" },
    list: [
      {
        id: "main",
        groupChat: { mentionPatterns: ["@openclaw", "reisponde"] }
      }
    ]
  },
  channels: {
    whatsapp: {
      // 白名单仅用于 DM;包含你自己的号码启用自聊模式。
      allowFrom: ["+15555550123"],
      groups: { "*": { requireMention: true } }
    }
  }
}

配置包含 ($include)

使用 $include 指令将配置拆分为多个文件。这对以下场景很有用:

  • 组织大型配置(例如,每个客户端的 agent 定义)
  • 跨环境共享通用设置
  • 将敏感配置分开

基本用法

// ~/.openclaw/openclaw.json
{
  gateway: { port: 18789 },
  
  // 包含单个文件(替换键的值)
  agents: { "$include": "./agents.json5" },
  
  // 包含多个文件(按顺序深度合并)
  broadcast: { 
    "$include": [
      "./clients/mueller.json5",
      "./clients/schmidt.json5"
    ]
  }
}
// ~/.openclaw/agents.json5
{
  defaults: { sandbox: { mode: "all", scope: "session" } },
  list: [
    { id: "main", workspace: "~/.openclaw/workspace" }
  ]
}

合并行为

  • 单个文件:替换包含 $include 的对象
  • 文件数组:按顺序深度合并文件(后面的文件覆盖前面的)
  • 带同级键:同级键在 includes 之后合并(覆盖包含的值)
  • 同级键 + 数组/原始值:不支持(包含的内容必须是对象)
// 同级键覆盖包含的值
{
  "$include": "./base.json5",   // { a: 1, b: 2 }
  b: 99                          // 结果: { a: 1, b: 99 }
}

嵌套包含

包含的文件本身可以包含 $include 指令(最多 10 层深度):

// clients/mueller.json5
{
  agents: { "$include": "./mueller/agents.json5" },
  broadcast: { "$include": "./mueller/broadcast.json5" }
}

路径解析

  • 相对路径:相对于包含文件解析
  • 绝对路径:按原样使用
  • 父目录:../ 引用按预期工作
{ "$include": "./sub/config.json5" }      // 相对路径
{ "$include": "/etc/openclaw/base.json5" } // 绝对路径
{ "$include": "../shared/common.json5" }   // 父目录

错误处理

  • 文件缺失:清晰的错误消息包含解析的路径
  • 解析错误:显示哪个包含的文件失败
  • 循环包含:检测并报告包含链

示例:多客户端法律设置

// ~/.openclaw/openclaw.json
{
  gateway: { port: 18789, auth: { token: "secret" } },
  
  // 通用 agent 默认值
  agents: {
    defaults: {
      sandbox: { mode: "all", scope: "session" }
    },
    // 合并所有客户端的 agent 列表
    list: { "$include": [
      "./clients/mueller/agents.json5",
      "./clients/schmidt/agents.json5"
    ]}
  },
  
  // 合并广播配置
  broadcast: { "$include": [
    "./clients/mueller/broadcast.json5",
    "./clients/schmidt/broadcast.json5"
  ]},
  
  channels: { whatsapp: { groupPolicy: "allowlist" } }
}
// ~/.openclaw/clients/mueller/agents.json5
[
  { id: "mueller-transcribe", workspace: "~/clients/mueller/transcribe" },
  { id: "mueller-docs", workspace: "~/clients/mueller/docs" }
]
// ~/.openclaw/clients/mueller/broadcast.json5
{
  "[email protected]": ["mueller-transcribe", "mueller-docs"]
}

通用选项

环境变量 + .env

OpenClaw 从父进程(shell、launchd/systemd、CI 等)读取环境变量。

此外,它加载:

  • 当前工作目录中的 .env(如果存在)
  • ~/.openclaw/.env(即 $OPENCLAW_STATE_DIR/.env)的全局回退 .env

这两个 .env 文件都不会覆盖现有的环境变量。

你还可以在配置中提供内联环境变量。这些仅在进程环境缺少键时应用(相同的非覆盖规则):

{
  env: {
    OPENROUTER_API_KEY: "sk-or-...",
    vars: {
      GROQ_API_KEY: "gsk-..."
    }
  }
}

查看 /environment 了解完整优先级和来源。

env.shellEnv(可选)

选择性便利:如果启用并且尚未设置任何预期键,OpenClaw 运行你的登录 shell 并仅导入缺失的预期键(永不覆盖)。 这有效地 sources 你的 shell 配置文件。

{
  env: {
    shellEnv: {
      enabled: true,
      timeoutMs: 15000
    }
  }
}

环境变量等效:

  • OPENCLAW_LOAD_SHELL_ENV=1
  • OPENCLAW_SHELL_ENV_TIMEOUT_MS=15000

配置中的环境变量替换

你可以在任何配置字符串值中使用 ${VAR_NAME} 语法直接引用环境变量。变量在配置加载时替换,在验证之前。

{
  models: {
    providers: {
      "vercel-gateway": {
        apiKey: "${VERCEL_GATEWAY_API_KEY}"
      }
    }
  },
  gateway: {
    auth: {
      token: "${OPENCLAW_GATEWAY_TOKEN}"
    }
  }
}

规则:

  • 仅匹配大写环境变量名:[A-Z_][A-Z0-9_]*
  • 缺失或空环境变量在配置加载时抛出错误
  • 使用 $${VAR} 转义以输出字面量 ${VAR}
  • $include 配合使用(包含的文件也获得替换)

内联替换:

{
  models: {
    providers: {
      custom: {
        baseUrl: "${CUSTOM_API_BASE}/v1"  // → "https://api.example.com/v1"
      }
    }
  }
}

Auth 存储 (OAuth + API keys)

OpenClaw 将每个 agent 的 auth 配置文件(OAuth + API keys)存储在:

  • <agentDir>/auth-profiles.json(默认:~/.openclaw/agents/<agentId>/agent/auth-profiles.json)

另见:/concepts/oauth

传统 OAuth 导入:

  • ~/.openclaw/credentials/oauth.json(或 $OPENCLAW_STATE_DIR/credentials/oauth.json)

嵌入式 Pi agent 在以下位置维护运行时缓存:

  • <agentDir>/auth.json(自动管理;请勿手动编辑)

传统 agent 目录(多 agent 之前):

  • ~/.openclaw/agent/*(由 openclaw doctor 迁移到 ~/.openclaw/agents/<defaultAgentId>/agent/*)

覆盖:

  • OAuth 目录(仅传统导入):OPENCLAW_OAUTH_DIR
  • Agent 目录(默认 agent 根覆盖):OPENCLAW_AGENT_DIR(首选)、PI_CODING_AGENT_DIR(传统)

首次使用时,OpenClaw 将 oauth.json 条目导入 auth-profiles.json

auth

auth 配置文件的可选元数据。这存储 secrets;它将配置文件 ID 映射到 provider + mode(和可选 email),并定义用于故障转移的 provider 轮换顺序。

{
  auth: {
    profiles: {
      "anthropic:[email protected]": { provider: "anthropic", mode: "oauth", email: "[email protected]" },
      "anthropic:work": { provider: "anthropic", mode: "api_key" }
    },
    order: {
      anthropic: ["anthropic:[email protected]", "anthropic:work"]
    }
  }
}

agents.list[].identity

用于默认值和 UX 的可选每 agent 身份。这由 macOS 入职助手编写。

如果设置,OpenClaw 派生默认值(仅当你未明确设置时):

  • 活动 agentidentity.emoji 派生 messages.ackReaction(回退到 👀)
  • 从 agent 的 identity.name/identity.emoji 派生 agents.list[].groupChat.mentionPatterns(因此"@Samantha"在 Telegram/Slack/Discord/Google Chat/iMessage/WhatsApp 的群组中工作)
  • identity.avatar 接受 workspace 相对图像路径或远程 URL/data URL。本地文件必须位于 agent workspace 内。

identity.avatar 接受:

  • Workspace 相对路径(必须保持在 agent workspace 内)
  • http(s) URL
  • data: URI
{
  agents: {
    list: [
      {
        id: "main",
        identity: {
          name: "Samantha",
          theme: "helpful sloth",
          emoji: "🦥",
          avatar: "avatars/samantha.png"
        }
      }
    ]
  }
}

wizard

由 CLI 向导(onboardconfiguredoctor)编写的元数据。

{
  wizard: {
    lastRunAt: "2026-01-01T00:00:00.000Z",
    lastRunVersion: "2026.1.4",
    lastRunCommit: "abc1234",
    lastRunCommand: "configure",
    lastRunMode: "local"
  }
}

logging

  • 默认日志文件:/tmp/openclaw/openclaw-YYYY-MM-DD.log
  • 如果你想要稳定路径,设置 logging.file/tmp/openclaw/openclaw.log
  • 控制台输出可以通过以下方式单独调整:
    • logging.consoleLevel(默认为 info,当 --verbose 时提升到 debug)
    • logging.consoleStyle(pretty | compact | json)
  • 工具摘要可以被编辑以避免泄露 secrets:
    • logging.redactSensitive(off | tools,默认:tools)
    • logging.redactPatterns(正则表达式字符串数组;覆盖默认值)
{
  logging: {
    level: "info",
    file: "/tmp/openclaw/openclaw.log",
    consoleLevel: "info",
    consoleStyle: "pretty",
    redactSensitive: "tools",
    redactPatterns: [
      // 示例:用你自己的规则覆盖默认值。
      "\\bTOKEN\\b\\s*[=:]\\s*([\"']?)([^\\s\"']+)\\1",
      "/\\bsk-[A-Za-z0-9_-]{8,}\\b/gi"
    ]
  }
}

channels.whatsapp.dmPolicy

控制如何处理 WhatsApp 直接聊天(DMs):

  • "pairing"(默认):未知发送者获得配对代码;所有者必须批准
  • "allowlist":仅允许 channels.whatsapp.allowFrom(或配对的允许存储)中的发送者
  • "open":允许所有入站 DM(需要 channels.whatsapp.allowFrom 包含 "*")
  • "disabled":忽略所有入站 DM

配对代码在 1 小时后过期;机器人仅在创建新请求时发送配对代码。默认情况下,待处理的 DM 配对请求上限为每个 channel 3 个

配对批准:

  • openclaw pairing list whatsapp
  • openclaw pairing approve whatsapp <code>

channels.whatsapp.allowFrom

可以触发 WhatsApp 自动回复的 E.164 电话号码白名单(仅 DM)。 如果为空且 channels.whatsapp.dmPolicy="pairing",未知发送者将收到配对代码。 对于群组,使用 channels.whatsapp.groupPolicy + channels.whatsapp.groupAllowFrom

{
  channels: {
    whatsapp: {
      dmPolicy: "pairing", // pairing | allowlist | open | disabled
      allowFrom: ["+15555550123", "+447700900123"],
      textChunkLimit: 4000, // 可选出站块大小(字符)
      chunkMode: "length", // 可选分块模式(length | newline)
      mediaMaxMb: 50 // 可选入站媒体上限(MB)
    }
  }
}

channels.whatsapp.sendReadReceipts

控制入站 WhatsApp 消息是否标记为已读(蓝勾)。默认:true

即使启用,自聊模式始终跳过已读回执。

每个帐户覆盖:channels.whatsapp.accounts.<id>.sendReadReceipts

{
  channels: {
    whatsapp: { sendReadReceipts: false }
  }
}

channels.whatsapp.accounts(多账户)

在一个 gateway 中运行多个 WhatsApp 账户:

{
  channels: {
    whatsapp: {
      accounts: {
        default: {}, // 可选;保持默认 id 稳定
        personal: {},
        biz: {
          // 可选覆盖。默认:~/.openclaw/credentials/whatsapp/biz
          // authDir: "~/.openclaw/credentials/whatsapp/biz",
        }
      }
    }
  }
}

注意:

  • 如果存在 default,出站命令默认使用账户 default;否则使用第一个配置的账户 id(已排序)。
  • 传统单账户 Baileys auth 目录由 openclaw doctor 迁移到 whatsapp/default

channels.telegram.accounts / channels.discord.accounts / channels.googlechat.accounts / channels.slack.accounts / channels.mattermost.accounts / channels.signal.accounts / channels.imessage.accounts

每个 channel 运行多个账户(每个账户都有自己的 accountId 和可选 name):

{
  channels: {
    telegram: {
      accounts: {
        default: {
          name: "Primary bot",
          botToken: "123456:ABC..."
        },
        alerts: {
          name: "Alerts bot",
          botToken: "987654:XYZ..."
        }
      }
    }
  }
}

注意:

  • 省略 accountId 时使用 default(CLI + 路由)。
  • 环境变量 token 仅适用于默认账户。
  • 基本 channel 设置(群组策略、提及门控等)适用于所有账户,除非每个账户覆盖。
  • 使用 bindings[].match.accountId 将每个账户路由到不同的 agents.defaults。

群组聊天提及门控 (agents.list[].groupChat + messages.groupChat)

群组消息默认需要提及(元数据提及或正则表达式模式)。适用于 WhatsApp、Telegram、Discord、Google Chat 和 iMessage 群组聊天。

提及类型:

  • 元数据提及:原生平台 @-提及(例如,WhatsApp 点击提及)。在 WhatsApp 自聊模式下忽略(参见 channels.whatsapp.allowFrom)。
  • 文本模式:agents.list[].groupChat.mentionPatterns 中定义的正则表达式模式。无论自聊模式如何,始终检查。
  • 仅当提及检测可能时(原生提及或至少一个 mentionPattern),才强制执行提及门控。
{
  messages: {
    groupChat: { historyLimit: 50 }
  },
  agents: {
    list: [
      { id: "main", groupChat: { mentionPatterns: ["@openclaw", "openclaw"] } }
    ]
  }
}

messages.groupChat.historyLimit 设置群组历史上下文的全局默认值。Channel 可以使用 channels.<channel>.historyLimit(或多账户的 channels.<channel>.accounts.*.historyLimit)覆盖。设置 0 禁用历史包装。

DM 历史限制

DM 对话使用 agent 管理的基于 session 的历史。你可以限制每个 DM session 保留的用户轮次数:

{
  channels: {
    telegram: {
      dmHistoryLimit: 30,  // 将 DM session 限制为 30 个用户轮次
      dms: {
        "123456789": { historyLimit: 50 }  // 每用户覆盖(用户 ID)
      }
    }
  }
}

解析顺序:

  1. 每 DM 覆盖:channels.<provider>.dms[userId].historyLimit
  2. Provider 默认:channels.<provider>.dmHistoryLimit
  3. 无限制(保留所有历史)

支持的 providers:telegramwhatsappdiscordslacksignalimessagemsteams

每 agent 覆盖(设置时优先,即使是 []):

{
  agents: {
    list: [
      { id: "work", groupChat: { mentionPatterns: ["@workbot", "\\+15555550123"] } },
      { id: "personal", groupChat: { mentionPatterns: ["@homebot", "\\+15555550999"] } }
    ]
  }
}

提及门控默认值位于每个 channel(channels.whatsapp.groupschannels.telegram.groupschannels.imessage.groupschannels.discord.guilds)。当设置 *.groups 时,它也充当群组白名单;包含 "*" 以允许所有群组。

仅响应特定文本触发器(忽略原生 @-提及):

{
  channels: {
    whatsapp: {
      // 包含你自己的号码以启用自聊模式(忽略原生 @-提及)。
      allowFrom: ["+15555550123"],
      groups: { "*": { requireMention: true } }
    }
  },
  agents: {
    list: [
      {
        id: "main",
        groupChat: {
          // 仅这些文本模式将触发响应
          mentionPatterns: ["reisponde", "@openclaw"]
        }
      }
    ]
  }
}

群组策略(每个 channel)

使用 channels.*.groupPolicy 控制是否完全接受群组/房间消息:

{
  channels: {
    whatsapp: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15551234567"]
    },
    telegram: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["tg:123456789", "@alice"]
    },
    signal: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["+15551234567"]
    },
    imessage: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["chat_id:123"]
    },
    msteams: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["[email protected]"]
    },
    discord: {
      groupPolicy: "allowlist",
      guilds: {
        "GUILD_ID": {
          channels: { help: { allow: true } }
        }
      }
    },
    slack: {
      groupPolicy: "allowlist",
      channels: { "#general": { allow: true } }
    }
  }
}

注意:

  • "open":群组绕过白名单;提及门控仍然适用。
  • "disabled":阻止所有群组/房间消息。
  • "allowlist":仅允许匹配配置的白名单的群组/房间。
  • channels.defaults.groupPolicy 在 provider 的 groupPolicy 未设置时设置默认值。
  • WhatsApp/Telegram/Signal/iMessage/Microsoft Teams 使用 groupAllowFrom(回退:显式 allowFrom)。
  • Discord/Slack 使用 channel 白名单(channels.discord.guilds.*.channelschannels.slack.channels)。
  • 群组 DM(Discord/Slack)仍由 dm.groupEnabled + dm.groupChannels 控制。
  • 默认为 groupPolicy: "allowlist"(除非被 channels.defaults.groupPolicy 覆盖);如果未配置白名单,则阻止群组消息。

多 agent 路由 (agents.list + bindings)

在一个 Gateway 内运行多个隔离的 agents(单独的 workspace、agentDir、sessions)。 入站消息通过 bindings 路由到 agent。

  • agents.list[]:每 agent 覆盖。
    • id:稳定的 agent id(必需)。
    • default:可选;当设置多个时,第一个获胜并记录警告。 如果未设置,列表中的第一个条目是默认 agent。
    • name:agent 的显示名称。
    • workspace:默认 ~/.openclaw/workspace-<agentId>(对于 main,回退到 agents.defaults.workspace)。
    • agentDir:默认 ~/.openclaw/agents/<agentId>/agent
    • model:每 agent 默认模型,覆盖该 agent 的 agents.defaults.model
      • 字符串形式:"provider/model",仅覆盖 agents.defaults.model.primary
      • 对象形式:{ primary, fallbacks }(fallbacks 覆盖 agents.defaults.model.fallbacks;[] 禁用该 agent 的全局 fallbacks)
    • identity:每 agent 名称/主题/emoji(用于提及模式 + ack 反应)。
    • groupChat:每 agent 提及门控(mentionPatterns)。
    • sandbox:每 agent sandbox 配置(覆盖 agents.defaults.sandbox)。
      • mode:"off" | "non-main" | "all"
      • workspaceAccess:"none" | "ro" | "rw"
      • scope:"session" | "agent" | "shared"
      • workspaceRoot:自定义 sandbox workspace 根
      • docker:每 agent docker 覆盖(例如 imagenetworkenvsetupCommand、limits;当 scope: "shared" 时忽略)
      • browser:每 agent 沙盒浏览器覆盖(当 scope: "shared" 时忽略)
      • prune:每 agent sandbox 修剪覆盖(当 scope: "shared" 时忽略)
    • subagents:每 agent sub-agent 默认值。
      • allowAgents:从此 agent 的 sessions_spawn 的 agent ids 白名单(["*"] = 允许任何;默认:仅相同 agent)
    • tools:每 agent 工具限制(在 sandbox 工具策略之前应用)。
      • profile:基本工具配置文件(在 allow/deny 之前应用)
      • allow:允许的工具名称数组
      • deny:拒绝的工具名称数组(deny 获胜)
  • agents.defaults:共享 agent 默认值(model、workspace、sandbox 等)。
  • bindings[]:将入站消息路由到 agentId
    • match.channel(必需)
    • match.accountId(可选;* = 任何账户;省略 = 默认账户)
    • match.peer(可选;{ kind: dm|group|channel, id })
    • match.guildId / match.teamId(可选;channel 特定)

确定性匹配顺序:

  1. match.peer
  2. match.guildId
  3. match.teamId
  4. match.accountId(精确,无 peer/guild/team)
  5. match.accountId: "*"(channel 范围,无 peer/guild/team)
  6. 默认 agent(agents.list[].default,否则第一个列表条目,否则 "main")

在每个匹配层内,bindings 中的第一个匹配条目获胜。

每 agent 访问配置文件(多 agent)

每个 agent 可以携带自己的 sandbox + 工具策略。使用它在一个 gateway 中混合访问级别:

  • 完全访问(个人 agent)
  • 只读工具 + workspace
  • 无文件系统访问(仅消息/session 工具)

查看 Multi-Agent Sandbox & Tools 了解优先级和其他示例。

完全访问(无 sandbox):

{
  agents: {
    list: [
      {
        id: "personal",
        workspace: "~/.openclaw/workspace-personal",
        sandbox: { mode: "off" }
      }
    ]
  }
}

只读工具 + 只读 workspace:

{
  agents: {
    list: [
      {
        id: "family",
        workspace: "~/.openclaw/workspace-family",
        sandbox: {
          mode: "all",
          scope: "agent",
          workspaceAccess: "ro"
        },
        tools: {
          allow: ["read", "sessions_list", "sessions_history", "sessions_send", "sessions_spawn", "session_status"],
          deny: ["write", "edit", "apply_patch", "exec", "process", "browser"]
        }
      }
    ]
  }
}

无文件系统访问(启用消息/session 工具):

{
  agents: {
    list: [
      {
        id: "public",
        workspace: "~/.openclaw/workspace-public",
        sandbox: {
          mode: "all",
          scope: "agent",
          workspaceAccess: "none"
        },
        tools: {
          allow: ["sessions_list", "sessions_history", "sessions_send", "sessions_spawn", "session_status", "whatsapp", "telegram", "slack", "discord", "gateway"],
          deny: ["read", "write", "edit", "apply_patch", "exec", "process", "browser", "canvas", "nodes", "cron", "gateway", "image"]
        }
      }
    ]
  }
}

示例:两个 WhatsApp 账户 → 两个 agents:

{
  agents: {
    list: [
      { id: "home", default: true, workspace: "~/.openclaw/workspace-home" },
      { id: "work", workspace: "~/.openclaw/workspace-work" }
    ]
  },
  bindings: [
    { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } },
    { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } }
  ],
  channels: {
    whatsapp: {
      accounts: {
        personal: {},
        biz: {},
      }
    }
  }
}

tools.agentToAgent(可选)

Agent 到 agent 消息传递是选择性的:

{
  tools: {
    agentToAgent: {
      enabled: false,
      allow: ["home", "work"]
    }
  }
}

messages.queue

控制当 agent 运行已经活动时入站消息的行为方式。

{
  messages: {
    queue: {
      mode: "collect", // steer | followup | collect | steer-backlog (steer+backlog ok) | interrupt (queue=steer legacy)
      debounceMs: 1000,
      cap: 20,
      drop: "summarize", // old | new | summarize
      byChannel: {
        whatsapp: "collect",
        telegram: "collect",
        discord: "collect",
        imessage: "collect",
        webchat: "collect"
      }
    }
  }
}

messages.inbound

对来自同一发送者的快速入站消息进行去抖,以便多条连续消息成为单个 agent 轮次。去抖的作用域是每个 channel + 对话,并使用最新的消息进行回复线程/ID。

{
  messages: {
    inbound: {
      debounceMs: 2000, // 0 禁用
      byChannel: {
        whatsapp: 5000,
        slack: 1500,
        discord: 1500
      }
    }
  }
}

注意:

  • 去抖批处理纯文本消息;媒体/附件立即刷新。
  • 控制命令(例如 /queue/new)绕过去抖,因此它们保持独立。

commands(聊天命令处理)

控制如何在连接器之间启用聊天命令。

{
  commands: {
    native: "auto",         // 在支持时注册原生命令(auto)
    text: true,             // 解析聊天消息中的斜杠命令
    bash: false,            // 允许 !(别名:/bash)(仅主机;需要 tools.elevated 白名单)
    bashForegroundMs: 2000, // bash 前台窗口(0 立即后台)
    config: false,          // 允许 /config(写入磁盘)
    debug: false,           // 允许 /debug(仅运行时覆盖)
    restart: false,         // 允许 /restart + gateway restart 工具
    useAccessGroups: true   // 强制执行命令的访问组白名单/策略
  }
}

注意:

  • 文本命令必须作为独立消息发送并使用前导 /(无纯文本别名)。
  • commands.text: false 禁用解析聊天消息中的命令。
  • commands.native: "auto"(默认)为 Discord/Telegram 启用原生命令并保持 Slack 关闭;不支持的 channels 保持纯文本。
  • 设置 commands.native: true|false 强制全部,或使用 channels.discord.commands.nativechannels.telegram.commands.nativechannels.slack.commands.native(bool 或 "auto")按 channel 覆盖。false 在启动时清除 Discord/Telegram 上先前注册的命令;Slack 命令在 Slack 应用中管理。
  • channels.telegram.customCommands 添加额外的 Telegram 机器人菜单条目。名称已规范化;与原生命令的冲突被忽略。
  • commands.bash: true 启用 ! <cmd> 运行主机 shell 命令(/bash <cmd> 也作为别名工作)。需要 tools.elevated.enabled 并在 tools.elevated.allowFrom.<channel> 中将发送者列入白名单。
  • commands.bashForegroundMs 控制 bash 在后台之前等待多长时间。当 bash 作业正在运行时,新的 ! <cmd> 请求被拒绝(一次一个)。
  • commands.config: true 启用 /config(读取/写入 openclaw.json)。
  • channels.<provider>.configWrites 控制由该 channel 发起的配置变更(默认:true)。这适用于 /config set|unset 加 provider 特定的自动迁移(Telegram 超级群组 ID 更改、Slack channel ID 更改)。
  • commands.debug: true 启用 /debug(仅运行时覆盖)。
  • commands.restart: true 启用 /restart 和 gateway 工具 restart 操作。
  • commands.useAccessGroups: false 允许命令绕过访问组白名单/策略。
  • 斜杠命令和指令仅对授权发送者执行。授权来自 channel 白名单/配对加 commands.useAccessGroups

web(WhatsApp web channel 运行时)

WhatsApp 通过 gateway 的 web channel(Baileys Web)运行。当链接的 session 存在时自动启动。 设置 web.enabled: false 默认保持关闭。

{
  web: {
    enabled: true,
    heartbeatSeconds: 60,
    reconnect: {
      initialMs: 2000,
      maxMs: 120000,
      factor: 1.4,
      jitter: 0.2,
      maxAttempts: 0
    }
  }
}

channels.telegram(bot transport)

仅当存在 channels.telegram 配置部分时 OpenClaw 才启动 Telegram。bot token 从 channels.telegram.botToken(或 channels.telegram.tokenFile)解析,默认账户的 TELEGRAM_BOT_TOKEN 作为回退。 设置 channels.telegram.enabled: false 禁用自动启动。 多账户支持位于 channels.telegram.accounts 下(参见上面的多账户部分)。环境变量 token 仅适用于默认账户。 设置 channels.telegram.configWrites: false 阻止 Telegram 发起的配置写入(包括超级群组 ID 迁移和 /config set|unset)。

{
  channels: {
    telegram: {
      enabled: true,
      botToken: "your-bot-token",
      dmPolicy: "pairing",                 // pairing | allowlist | open | disabled
      allowFrom: ["tg:123456789"],         // 可选;"open"需要["*"]
      groups: {
        "*": { requireMention: true },
        "-1001234567890": {
          allowFrom: ["@admin"],
          systemPrompt: "Keep answers brief.",
          topics: {
            "99": {
              requireMention: false,
              skills: ["search"],
              systemPrompt: "Stay on topic."
            }
          }
        }
      },
      customCommands: [
        { command: "backup", description: "Git backup" },
        { command: "generate", description: "Create an image" }
      ],
      historyLimit: 50,                     // 包括最后 N 条群组消息作为上下文(0 禁用)
      replyToMode: "first",                 // off | first | all
      linkPreview: true,                   // 切换出站链接预览
      streamMode: "partial",               // off | partial | block (draft streaming;与 block streaming 分开)
      draftChunk: {                        // 可选;仅用于 streamMode=block
        minChars: 200,
        maxChars: 800,
        breakPreference: "paragraph"       // paragraph | newline | sentence
      },
      actions: { reactions: true, sendMessage: true }, // 工具操作门控(false 禁用)
      reactionNotifications: "own",   // off | own | all
      mediaMaxMb: 5,
      retry: {                             // 出站重试策略
        attempts: 3,
        minDelayMs: 400,
        maxDelayMs: 30000,
        jitter: 0.1
      },
      network: {                           // transport 覆盖
        autoSelectFamily: false
      },
      proxy: "socks5://localhost:9050",
      webhookUrl: "https://example.com/telegram-webhook",
      webhookSecret: "secret",
      webhookPath: "/telegram-webhook"
    }
  }
}

Draft streaming 注意事项:

  • 使用 Telegram sendMessageDraft(draft 气泡,不是真正的消息)。
  • 需要私人聊天主题(DM 中的 message_thread_id;bot 已启用主题)。
  • /reasoning stream 将推理流式传输到 draft 中,然后发送最终答案。 重试策略默认值和行为记录在重试策略中。

channels.discord(bot transport)

通过设置 bot token 和可选门控配置 Discord bot: 多账户支持位于 channels.discord.accounts 下(参见上面的多账户部分)。环境变量 token 仅适用于默认账户。

{
  channels: {
    discord: {
      enabled: true,
      token: "your-bot-token",
      mediaMaxMb: 8,                          // 限制入站媒体大小
      allowBots: false,                       // 允许 bot 作者消息
      actions: {                              // 工具操作门控(false 禁用)
        reactions: true,
        stickers: true,
        polls: true,
        permissions: true,
        messages: true,
        threads: true,
        pins: true,
        search: true,
        memberInfo: true,
        roleInfo: true,
        roles: false,
        channelInfo: true,
        voiceStatus: true,
        events: true,
        moderation: false
      },
      replyToMode: "off",                     // off | first | all
      dm: {
        enabled: true,                        // false 时禁用所有 DM
        policy: "pairing",                    // pairing | allowlist | open | disabled
        allowFrom: ["1234567890", "steipete"], // 可选 DM 白名单("open"需要["*"])
        groupEnabled: false,                 // 启用群组 DM
        groupChannels: ["openclaw-dm"]          // 可选群组 DM 白名单
      },
      guilds: {
        "123456789012345678": {               // guild id(首选)或 slug
          slug: "friends-of-openclaw",
          requireMention: false,              // 每 guild 默认
          reactionNotifications: "own",       // off | own | all | allowlist
          users: ["987654321098765432"],      // 可选每 guild 用户白名单
          channels: {
            general: { allow: true },
            help: {
              allow: true,
              requireMention: true,
              users: ["987654321098765432"],
              skills: ["docs"],
              systemPrompt: "Short answers only."
            }
          }
        }
      },
      historyLimit: 20,                       // 包括最后 N 条 guild 消息作为上下文
      textChunkLimit: 2000,                   // 可选出站文本块大小(字符)
      chunkMode: "length",                    // 可选分块模式(length | newline)
      maxLinesPerMessage: 17,                 // 每条消息的软最大行数(Discord UI 剪切)
      retry: {                                // 出站重试策略
        attempts: 3,
        minDelayMs: 500,
        maxDelayMs: 30000,
        jitter: 0.1
      }
    }
  }
}

仅当存在 channels.discord 配置部分时 OpenClaw 才启动 Discord。token 从 channels.discord.token 解析,默认账户的 DISCORD_BOT_TOKEN 作为回退(除非 channels.discord.enabledfalse)。在指定 cron/CLI 命令的交付目标时使用 user:<id>(DM)或 channel:<id>(guild channel);裸数字 ID 是模糊的并被拒绝。 Guild slugs 是小写的,空格替换为 -;channel 键使用 slugged channel 名称(无前导 #)。首选 guild ids 作为键以避免重命名歧义。 默认情况下忽略 bot 作者消息。使用 channels.discord.allowBots 启用(自己的消息仍被过滤以防止自回复循环)。 反应通知模式:

  • off:无反应事件。
  • own:对 bot 自己消息的反应(默认)。
  • all:对所有消息的所有反应。
  • allowlist:来自 guilds.<id>.users 对所有消息的反应(空列表禁用)。 出站文本由 channels.discord.textChunkLimit(默认 2000)分块。设置 channels.discord.chunkMode="newline" 在长度分块之前在空行(段落边界)上拆分。Discord 客户端可以剪切非常高的消息,因此 channels.discord.maxLinesPerMessage(默认 17)即使在 2000 字符以下也会拆分长多行回复。 重试策略默认值和行为记录在重试策略中。

channels.googlechat(Chat API webhook)

Google Chat 通过 HTTP webhooks 运行,具有应用级别身份验证(服务账户)。 多账户支持位于 channels.googlechat.accounts 下(参见上面的多账户部分)。环境变量仅适用于默认账户。

{
  channels: {
    "googlechat": {
      enabled: true,
      serviceAccountFile: "/path/to/service-account.json",
      audienceType: "app-url",             // app-url | project-number
      audience: "https://gateway.example.com/googlechat",
      webhookPath: "/googlechat",
      botUser: "users/1234567890",        // 可选;改进提及检测
      dm: {
        enabled: true,
        policy: "pairing",                // pairing | allowlist | open | disabled
        allowFrom: ["users/1234567890"]   // 可选;"open"需要["*"]
      },
      groupPolicy: "allowlist",
      groups: {
        "spaces/AAAA": { allow: true, requireMention: true }
      },
      actions: { reactions: true },
      typingIndicator: "message",
      mediaMaxMb: 20
    }
  }
}

注意:

  • 服务账户 JSON 可以是内联的(serviceAccount)或基于文件的(serviceAccountFile)。
  • 默认账户的环境回退:GOOGLE_CHAT_SERVICE_ACCOUNTGOOGLE_CHAT_SERVICE_ACCOUNT_FILE
  • audienceType + audience 必须匹配 Chat 应用的 webhook 身份验证配置。
  • 设置交付目标时使用 spaces/<spaceId>users/<userId|email>

channels.slack(socket mode)

Slack 在 Socket Mode 下运行,需要 bot token 和 app token:

{
  channels: {
    slack: {
      enabled: true,
      botToken: "xoxb-...",
      appToken: "xapp-...",
      dm: {
        enabled: true,
        policy: "pairing", // pairing | allowlist | open | disabled
        allowFrom: ["U123", "U456", "*"], // 可选;"open"需要["*"]
        groupEnabled: false,
        groupChannels: ["G123"]
      },
      channels: {
        C123: { allow: true, requireMention: true, allowBots: false },
        "#general": {
          allow: true,
          requireMention: true,
          allowBots: false,
          users: ["U123"],
          skills: ["docs"],
          systemPrompt: "Short answers only."
        }
      },
      historyLimit: 50,          // 包括最后 N 条 channel/群组消息作为上下文(0 禁用)
      allowBots: false,
      reactionNotifications: "own", // off | own | all | allowlist
      reactionAllowlist: ["U123"],
      replyToMode: "off",           // off | first | all
      thread: {
        historyScope: "thread",     // thread | channel
        inheritParent: false
      },
      actions: {
        reactions: true,
        messages: true,
        pins: true,
        memberInfo: true,
        emojiList: true
      },
      slashCommand: {
        enabled: true,
        name: "openclaw",
        sessionPrefix: "slack:slash",
        ephemeral: true
      },
      textChunkLimit: 4000,
      chunkMode: "length",
      mediaMaxMb: 20
    }
  }
}

多账户支持位于 channels.slack.accounts 下(参见上面的多账户部分)。环境变量 token 仅适用于默认账户。

当 provider 启用并且两个 token 都设置(通过配置或 SLACK_BOT_TOKEN + SLACK_APP_TOKEN)时,OpenClaw 启动 Slack。在为 cron/CLI 命令指定交付目标时使用 user:<id>(DM)或 channel:<id>。 设置 channels.slack.configWrites: false 阻止 Slack 发起的配置写入(包括 channel ID 迁移和 /config set|unset)。

默认情况下忽略 bot 作者消息。使用 channels.slack.allowBotschannels.slack.channels.<id>.allowBots 启用。

反应通知模式:

  • off:无反应事件。
  • own:对 bot 自己消息的反应(默认)。
  • all:对所有消息的所有反应。
  • allowlist:来自 channels.slack.reactionAllowlist 对所有消息的反应(空列表禁用)。

Thread session 隔离:

  • channels.slack.thread.historyScope 控制 thread 历史是每 thread(thread,默认)还是跨 channel 共享(channel)。
  • channels.slack.thread.inheritParent 控制新 thread sessions 是否继承父 channel 记录(默认:false)。

Slack 操作组(控制 slack 工具操作):

操作组默认注意
reactions启用反应 + 列出反应
messages启用读取/发送/编辑/删除
pins启用固定/取消固定/列出
memberInfo启用成员信息
emojiList启用自定义 emoji 列表

channels.mattermost(bot token)

Mattermost 作为插件提供,不与核心安装捆绑。 首先安装它:openclaw plugins install @openclaw/mattermost(或从 git checkout 的 ./extensions/mattermost)。

Mattermost 需要 bot token 加服务器的基础 URL:

{
  channels: {
    mattermost: {
      enabled: true,
      botToken: "mm-token",
      baseUrl: "https://chat.example.com",
      dmPolicy: "pairing",
      chatmode: "oncall", // oncall | onmessage | onchar
      oncharPrefixes: [">", "!"],
      textChunkLimit: 4000,
      chunkMode: "length"
    }
  }
}

当账户配置(bot token + 基础 URL)并启用时,OpenClaw 启动 Mattermost。token + 基础 URL 从 channels.mattermost.botToken + channels.mattermost.baseUrl 或默认账户的 MATTERMOST_BOT_TOKEN + MATTERMOST_URL 解析(除非 channels.mattermost.enabledfalse)。

聊天模式:

  • oncall(默认):仅在 @提及时响应 channel 消息。
  • onmessage:响应每条 channel 消息。
  • onchar:当消息以触发前缀开头时响应(channels.mattermost.oncharPrefixes,默认 [">", "!"])。

访问控制:

  • 默认 DM:channels.mattermost.dmPolicy="pairing"(未知发送者获得配对代码)。
  • 公开 DM:channels.mattermost.dmPolicy="open"channels.mattermost.allowFrom=["*"]
  • 群组:channels.mattermost.groupPolicy="allowlist" 默认(提及门控)。使用 channels.mattermost.groupAllowFrom 限制发送者。

多账户支持位于 channels.mattermost.accounts 下(参见上面的多账户部分)。环境变量仅适用于默认账户。 指定交付目标时使用 channel:<id>user:<id>(或 @username);裸 ids 被视为 channel ids。

channels.signal(signal-cli)

Signal 反应可以发出系统事件(共享反应工具):

{
  channels: {
    signal: {
      reactionNotifications: "own", // off | own | all | allowlist
      reactionAllowlist: ["+15551234567", "uuid:123e4567-e89b-12d3-a456-426614174000"],
      historyLimit: 50 // 包括最后 N 条群组消息作为上下文(0 禁用)
    }
  }
}

反应通知模式:

  • off:无反应事件。
  • own:对 bot 自己消息的反应(默认)。
  • all:对所有消息的所有反应。
  • allowlist:来自 channels.signal.reactionAllowlist 对所有消息的反应(空列表禁用)。

channels.imessage(imsg CLI)

OpenClaw 生成 imsg rpc(通过 stdio 的 JSON-RPC)。不需要守护程序或端口。

{
  channels: {
    imessage: {
      enabled: true,
      cliPath: "imsg",
      dbPath: "~/Library/Messages/chat.db",
      remoteHost: "user@gateway-host", // 使用 SSH 包装器时远程附件的 SCP
      dmPolicy: "pairing", // pairing | allowlist | open | disabled
      allowFrom: ["+15555550123", "[email protected]", "chat_id:123"],
      historyLimit: 50,    // 包括最后 N 条群组消息作为上下文(0 禁用)
      includeAttachments: false,
      mediaMaxMb: 16,
      service: "auto",
      region: "US"
    }
  }
}

多账户支持位于 channels.imessage.accounts 下(参见上面的多账户部分)。

注意:

  • 需要对 Messages DB 的完全磁盘访问权限。
  • 第一次发送将提示 Messages 自动化权限。
  • 首选 chat_id:<id> 目标。使用 imsg chats --limit 20 列出聊天。
  • channels.imessage.cliPath 可以指向包装脚本(例如 ssh 到另一台运行 imsg rpc 的 Mac);使用 SSH 密钥避免密码提示。
  • 对于远程 SSH 包装器,设置 channels.imessage.remoteHost 以在启用 includeAttachments 时通过 SCP 获取附件。

示例包装器:

#!/usr/bin/env bash
exec ssh -T gateway-host imsg "$@"

agents.defaults.workspace

设置 agent 用于文件操作的单个全局 workspace 目录

默认:~/.openclaw/workspace

{
  agents: { defaults: { workspace: "~/.openclaw/workspace" } }
}

如果启用了 agents.defaults.sandbox,非主 sessions 可以使用 agents.defaults.sandbox.workspaceRoot 下的每个作用域 workspaces 覆盖此设置。

agents.defaults.repoRoot

可选的存储库根目录,显示在系统提示的 Runtime 行中。如果未设置,OpenClaw 尝试通过从 workspace(和当前工作目录)向上查找 .git 目录来检测。路径必须存在才能使用。

{
  agents: { defaults: { repoRoot: "~/Projects/openclaw" } }
}

agents.defaults.skipBootstrap

禁用 workspace bootstrap 文件(AGENTS.mdSOUL.mdTOOLS.mdIDENTITY.mdUSER.mdBOOTSTRAP.md)的自动创建。

对于 workspace 文件来自存储库的预播种部署,请使用此选项。

{
  agents: { defaults: { skipBootstrap: true } }
}

agents.defaults.bootstrapMaxChars

在截断之前注入系统提示的每个 workspace bootstrap 文件的最大字符数。默认:20000

当文件超过此限制时,OpenClaw 记录警告并注入带有标记的截断头部/尾部。

{
  agents: { defaults: { bootstrapMaxChars: 20000 } }
}

agents.defaults.userTimezone

设置用户时区用于系统提示上下文(不用于消息信封中的时间戳)。如果未设置,OpenClaw 在运行时使用主机时区。

{
  agents: { defaults: { userTimezone: "America/Chicago" } }
}

agents.defaults.timeFormat

控制系统提示的当前日期和时间部分中显示的时间格式。 默认:auto(OS 偏好)。

{
  agents: { defaults: { timeFormat: "auto" } } // auto | 12 | 24
}

messages

控制入站/出站前缀和可选 ack 反应。 查看消息了解队列、sessions 和流式上下文。

{
  messages: {
    responsePrefix: "🦞", // 或 "auto"
    ackReaction: "👀",
    ackReactionScope: "group-mentions",
    removeAckAfterReply: false
  }
}

responsePrefix 应用于所有出站回复(工具摘要、块流式传输、最终回复),除非已存在。

如果未设置 messages.responsePrefix,默认情况下不应用前缀。WhatsApp 自聊回复是例外:当设置时它们默认为 [{identity.name}],否则为 [openclaw],因此同号码对话保持清晰。 将其设置为 "auto" 以为路由的 agent 派生 [{identity.name}](当设置时)。

模板变量

responsePrefix 字符串可以包含动态解析的模板变量:

变量描述示例
{model}短模型名称claude-opus-4-5gpt-4o
{modelFull}完整模型标识符anthropic/claude-opus-4-5
{provider}Provider 名称anthropicopenai
{thinkingLevel}当前思考级别highlowoff
{identity.name}Agent 身份名称(与 "auto" 模式相同)

变量不区分大小写({MODEL} = {model})。{think}{thinkingLevel} 的别名。 未解析的变量保持为字面文本。

{
  messages: {
    responsePrefix: "[{model} | think:{thinkingLevel}]"
  }
}

示例输出:[claude-opus-4-5 | think:high] Here's my response...

WhatsApp 入站前缀通过 channels.whatsapp.messagePrefix(已弃用:messages.messagePrefix)配置。默认保持不变:当 channels.whatsapp.allowFrom 为空时为 "[openclaw]",否则为 ""(无前缀)。使用 "[openclaw]" 时,当路由的 agent 设置了 identity.name 时,OpenClaw 将改用 [{identity.name}]

ackReaction 发送尽力而为的 emoji 反应以确认支持反应的 channels(Slack/Discord/Telegram/Google Chat)上的入站消息。默认为活动 agent 的 identity.emoji(当设置时),否则为 "👀"。将其设置为 "" 以禁用。

ackReactionScope 控制反应何时触发:

  • group-mentions(默认):仅当群组/房间需要提及并且机器人被提及时
  • group-all:所有群组/房间消息
  • direct:仅直接消息
  • all:所有消息

removeAckAfterReply 在发送回复后删除 bot 的 ack 反应(仅 Slack/Discord/Telegram/Google Chat)。默认:false

messages.tts

为出站回复启用文本转语音。启用时,OpenClaw 使用 ElevenLabs 或 OpenAI 生成音频并将其附加到响应。Telegram 使用 Opus 语音笔记;其他 channels 发送 MP3 音频。

{
  messages: {
    tts: {
      auto: "always", // off | always | inbound | tagged
      mode: "final", // final | all (包括工具/块回复)
      provider: "elevenlabs",
      summaryModel: "openai/gpt-4.1-mini",
      modelOverrides: {
        enabled: true
      },
      maxTextLength: 4000,
      timeoutMs: 30000,
      prefsPath: "~/.openclaw/settings/tts.json",
      elevenlabs: {
        apiKey: "elevenlabs_api_key",
        baseUrl: "https://api.elevenlabs.io",
        voiceId: "voice_id",
        modelId: "eleven_multilingual_v2",
        seed: 42,
        applyTextNormalization: "auto",
        languageCode: "en",
        voiceSettings: {
          stability: 0.5,
          similarityBoost: 0.75,
          style: 0.0,
          useSpeakerBoost: true,
          speed: 1.0
        }
      },
      openai: {
        apiKey: "openai_api_key",
        model: "gpt-4o-mini-tts",
        voice: "alloy"
      }
    }
  }
}

注意:

  • messages.tts.auto 控制自动 TTS(offalwaysinboundtagged)。
  • /tts off|always|inbound|tagged 设置每 session 自动模式(覆盖配置)。
  • messages.tts.enabled 是传统的;doctor 将其迁移到 messages.tts.auto
  • prefsPath 存储本地覆盖(provider/limit/summarize)。
  • maxTextLength 是 TTS 输入的硬上限;摘要被截断以适应。
  • summaryModel 覆盖 agents.defaults.model.primary 用于自动摘要。
    • 接受 provider/model 或来自 agents.defaults.models 的别名。
  • modelOverrides 启用模型驱动的覆盖,如 [[tts:...]] 标签(默认启用)。
  • /tts limit/tts summary 控制每用户摘要设置。
  • apiKey 值回退到 ELEVENLABS_API_KEY/XI_API_KEYOPENAI_API_KEY
  • elevenlabs.baseUrl 覆盖 ElevenLabs API 基础 URL。
  • elevenlabs.voiceSettings 支持 stability/similarityBoost/style(0..1)、useSpeakerBoostspeed(0.5..2.0)。

talk

Talk 模式(macOS/iOS/Android)的默认值。Voice ID 回退到未设置时的 ELEVENLABS_VOICE_IDSAG_VOICE_IDapiKey 在未设置时回退到 ELEVENLABS_API_KEY(或 gateway 的 shell 配置文件)。 voiceAliases 让 Talk 指令使用友好名称(例如 "voice":"Clawd")。

{
  talk: {
    voiceId: "elevenlabs_voice_id",
    voiceAliases: {
      Clawd: "EXAVITQu4vr4xnSDxMaL",
      Roger: "CwhRBWXzGAHq8TQ4Fs17"
    },
    modelId: "eleven_v3",
    outputFormat: "mp3_44100_128",
    apiKey: "elevenlabs_api_key",
    interruptOnSpeech: true
  }
}

agents.defaults

控制嵌入式 agent 运行时(model/thinking/verbose/timeouts)。 agents.defaults.models 定义配置的模型目录(并充当 /model 的白名单)。 agents.defaults.model.primary 设置默认模型;agents.defaults.model.fallbacks 是全局故障转移。 agents.defaults.imageModel 是可选的,仅在主模型缺少图像输入时使用。 每个 agents.defaults.models 条目可以包括:

  • alias(可选模型快捷方式,例如 /opus)。
  • params(传递给模型请求的可选 provider 特定 API 参数)。

params 也应用于流式运行(嵌入式 agent + 压缩)。今天支持的键:temperaturemaxTokens。这些与调用时选项合并;调用者提供的值获胜。temperature 是一个高级旋钮—除非你知道模型的默认值并需要更改,否则不要设置。

示例:

{
  agents: {
    defaults: {
      models: {
        "anthropic/claude-sonnet-4-5-20250929": {
          params: { temperature: 0.6 }
        },
        "openai/gpt-5.2": {
          params: { maxTokens: 8192 }
        }
      }
    }
  }
}

Z.AI GLM-4.x 模型自动启用思考模式,除非你:

  • 设置 --thinking off,或
  • 自己定义 agents.defaults.models["zai/<model>"].params.thinking

OpenClaw 还提供一些内置别名快捷方式。默认值仅在模型已在 agents.defaults.models 中存在时应用:

  • opus -> anthropic/claude-opus-4-5
  • sonnet -> anthropic/claude-sonnet-4-5
  • gpt -> openai/gpt-5.2
  • gpt-mini -> openai/gpt-5-mini
  • gemini -> google/gemini-3-pro-preview
  • gemini-flash -> google/gemini-3-flash-preview

如果你自己配置相同的别名名称(不区分大小写),你的值获胜(默认值永不覆盖)。

示例:Opus 4.5 主模型加 MiniMax M2.1 故障转移(托管 MiniMax):

{
  agents: {
    defaults: {
      models: {
        "anthropic/claude-opus-4-5": { alias: "opus" },
        "minimax/MiniMax-M2.1": { alias: "minimax" }
      },
      model: {
        primary: "anthropic/claude-opus-4-5",
        fallbacks: ["minimax/MiniMax-M2.1"]
      }
    }
  }
}

MiniMax auth:设置 MINIMAX_API_KEY(env)或配置 models.providers.minimax

agents.defaults.cliBackends(CLI 故障转移)

用于纯文本故障转移运行的可选 CLI 后端(无工具调用)。当 API providers 失败时,这些作为备用路径很有用。当你配置接受文件路径的 imageArg 时,支持图像透传。

注意:

  • CLI 后端是文本优先的;工具始终被禁用。
  • 当设置 sessionArg 时支持 Sessions;session ids 按后端持久化。
  • 对于 claude-cli,默认值已连接。如果 PATH 最小(launchd/systemd),覆盖命令路径。

示例:

{
  agents: {
    defaults: {
      cliBackends: {
        "claude-cli": {
          command: "/opt/homebrew/bin/claude"
        },
        "my-cli": {
          command: "my-cli",
          args: ["--json"],
          output: "json",
          modelArg: "--model",
          sessionArg: "--session",
          sessionMode: "existing",
          systemPromptArg: "--system",
          systemPromptWhen: "first",
          imageArg: "--image",
          imageMode: "repeat"
        }
      }
    }
  }
}
{
  agents: {
    defaults: {
      models: {
        "anthropic/claude-opus-4-5": { alias: "Opus" },
        "anthropic/claude-sonnet-4-1": { alias: "Sonnet" },
        "openrouter/deepseek/deepseek-r1:free": {},
        "zai/glm-4.7": {
          alias: "GLM",
          params: {
            thinking: {
              type: "enabled",
              clear_thinking: false
            }
          }
        }
      },
      model: {
        primary: "anthropic/claude-opus-4-5",
        fallbacks: [
          "openrouter/deepseek/deepseek-r1:free",
          "openrouter/meta-llama/llama-3.3-70b-instruct:free"
        ]
      },
      imageModel: {
        primary: "openrouter/qwen/qwen-2.5-vl-72b-instruct:free",
        fallbacks: [
          "openrouter/google/gemini-2.0-flash-vision:free"
        ]
      },
      thinkingDefault: "low",
      verboseDefault: "off",
      elevatedDefault: "on",
      timeoutSeconds: 600,
      mediaMaxMb: 5,
      heartbeat: {
        every: "30m",
        target: "last"
      },
      maxConcurrent: 3,
      subagents: {
        model: "minimax/MiniMax-M2.1",
        maxConcurrent: 1,
        archiveAfterMinutes: 60
      },
      exec: {
        backgroundMs: 10000,
        timeoutSec: 1800,
        cleanupMs: 1800000
      },
      contextTokens: 200000
    }
  }
}

agents.defaults.contextPruning(工具结果修剪)

agents.defaults.contextPruning 在请求发送到 LLM 之前,从内存中的上下文修剪旧工具结果。 它修改磁盘上的 session 历史(*.jsonl 保持完整)。

这旨在减少随时间积累大量工具输出的健谈 agents 的 token 使用。

高级别:

  • 从不触及用户/助手消息。
  • 保护最后 keepLastAssistants 个助手消息(该点之后的工具结果不被修剪)。
  • 保护 bootstrap 前缀(第一条用户消息之前的任何内容都不被修剪)。
  • 模式:
    • adaptive:当估计的上下文比率超过 softTrimRatio 时,软修剪超大工具结果(保留头部/尾部)。 然后,当估计的上下文比率超过 hardClearRatio 并且有足够的可修剪工具结果批量(minPrunableToolChars)时,硬清除最旧的合格工具结果。
    • aggressive:始终用 hardClear.placeholder 替换截止前的合格工具结果(无比率检查)。

软修剪与硬修剪(发送到 LLM 的上下文中的更改内容):

  • 软修剪:仅用于超大工具结果。保留开头 + 结尾并在中间插入 ...
    • 之前:toolResult("…very long output…")
    • 之后:toolResult("HEAD…\n...\n…TAIL\n\n[Tool result trimmed: …]")
  • 硬清除:用占位符替换整个工具结果。
    • 之前:toolResult("…very long output…")
    • 之后:toolResult("[Old tool result content cleared]")

注意/当前限制:

  • 包含图像块的工具结果现在被跳过(从不修剪/清除)。
  • 估计的"上下文比率"基于字符(近似),而不是精确的 tokens。
  • 如果 session 尚未包含至少 keepLastAssistants 个助手消息,则跳过修剪。
  • aggressive 模式下,忽略 hardClear.enabled(合格的工具结果始终替换为 hardClear.placeholder)。

默认(adaptive):

{
  agents: { defaults: { contextPruning: { mode: "adaptive" } } }
}

禁用:

{
  agents: { defaults: { contextPruning: { mode: "off" } } }
}

默认值(当 mode"adaptive""aggressive" 时):

  • keepLastAssistants:3
  • softTrimRatio:0.3(仅 adaptive)
  • hardClearRatio:0.5(仅 adaptive)
  • minPrunableToolChars:50000(仅 adaptive)
  • softTrim:{ maxChars: 4000, headChars: 1500, tailChars: 1500 }(仅 adaptive)
  • hardClear:{ enabled: true, placeholder: "[Old tool result content cleared]" }

示例(aggressive,最小):

{
  agents: { defaults: { contextPruning: { mode: "aggressive" } } }
}

示例(adaptive 调整):

{
  agents: {
    defaults: {
      contextPruning: {
        mode: "adaptive",
        keepLastAssistants: 3,
        softTrimRatio: 0.3,
        hardClearRatio: 0.5,
        minPrunableToolChars: 50000,
        softTrim: { maxChars: 4000, headChars: 1500, tailChars: 1500 },
        hardClear: { enabled: true, placeholder: "[Old tool result content cleared]" },
        // 可选:限制修剪到特定工具(deny 获胜;支持"*"通配符)
        tools: { deny: ["browser", "canvas"] },
      }
    }
  }
}

查看 /concepts/session-pruning 了解行为详情。

agents.defaults.compaction(预留空间 + 内存刷新)

agents.defaults.compaction.mode 选择压缩摘要策略。默认为 default;设置 safeguard 以启用非常长历史的分块摘要。查看 /concepts/compaction

agents.defaults.compaction.reserveTokensFloor 为 Pi 压缩强制执行最小 reserveTokens 值(默认:20000)。将其设置为 0 以禁用下限。

agents.defaults.compaction.memoryFlush 在自动压缩之前运行静默 agentic 轮次,指示模型将持久记忆存储到磁盘(例如 memory/YYYY-MM-DD.md)。当 session token 估计超过压缩限制以下的软阈值时触发。

传统默认值:

  • memoryFlush.enabled:true
  • memoryFlush.softThresholdTokens:4000
  • memoryFlush.prompt / memoryFlush.systemPrompt:带 NO_REPLY 的内置默认值
  • 注意:当 session workspace 为只读时跳过内存刷新 (agents.defaults.sandbox.workspaceAccess: "ro""none")。

示例(调整):

{
  agents: {
    defaults: {
      compaction: {
        mode: "safeguard",
        reserveTokensFloor: 24000,
        memoryFlush: {
          enabled: true,
          softThresholdTokens: 6000,
          systemPrompt: "Session nearing compaction. Store durable memories now.",
          prompt: "Write any lasting notes to memory/YYYY-MM-DD.md; reply with NO_REPLY if nothing to store."
        }
      }
    }
  }
}

Block streaming (块流式传输):

  • agents.defaults.blockStreamingDefault:"on"/"off"(默认 off)。
  • Channel 覆盖:*.blockStreaming(和每账户变体)强制启用/禁用块流式传输。 非 Telegram channels 需要显式 *.blockStreaming: true 来启用块回复。
  • agents.defaults.blockStreamingBreak:"text_end""message_end"(默认:text_end)。
  • agents.defaults.blockStreamingChunk:流式块的软分块。默认为 800–1200 字符,首选段落分隔(\n\n),然后是换行符,然后是句子。 示例:
    {
      agents: { defaults: { blockStreamingChunk: { minChars: 800, maxChars: 1200 } } }
    }
    
  • agents.defaults.blockStreamingCoalesce:在发送之前合并流式块。 默认为 { idleMs: 1000 } 并从 blockStreamingChunk 继承 minChars,maxChars 限制为 channel 文本限制。Signal/Slack/Discord/Google Chat 默认为 minChars: 1500,除非覆盖。 Channel 覆盖:channels.whatsapp.blockStreamingCoalescechannels.telegram.blockStreamingCoalescechannels.discord.blockStreamingCoalescechannels.slack.blockStreamingCoalescechannels.mattermost.blockStreamingCoalescechannels.signal.blockStreamingCoalescechannels.imessage.blockStreamingCoalescechannels.msteams.blockStreamingCoalescechannels.googlechat.blockStreamingCoalesce (和每账户变体)。
  • agents.defaults.humanDelay:第一个之后的块回复之间的随机暂停。 模式:off(默认)、natural(800–2500ms)、custom(使用 minMs/maxMs)。 每 agent 覆盖:agents.list[].humanDelay。 示例:
    {
      agents: { defaults: { humanDelay: { mode: "natural" } } }
    }
    

查看 /concepts/streaming 了解行为 + 分块详情。

Typing indicators (输入指示器):

  • agents.defaults.typingMode:"never" | "instant" | "thinking" | "message"。对于直接聊天/提及默认为 instant,对于未提及的群组聊天默认为 message
  • session.typingMode:模式的每 session 覆盖。
  • agents.defaults.typingIntervalSeconds:输入信号刷新频率(默认:6s)。
  • session.typingIntervalSeconds:刷新间隔的每 session 覆盖。 查看 /concepts/typing-indicators 了解行为详情。

agents.defaults.model.primary 应设置为 provider/model(例如 anthropic/claude-opus-4-5)。 别名来自 agents.defaults.models.*.alias(例如 Opus)。 如果你省略 provider,OpenClaw 当前假定 anthropic 作为临时弃用回退。 Z.AI 模型可用为 zai/<model>(例如 zai/glm-4.7)并需要环境中的 ZAI_API_KEY(或传统 Z_AI_API_KEY)。

agents.defaults.heartbeat 配置定期心跳运行:

  • every:持续时间字符串(mssmh);默认单位分钟。默认:30m。设置 0m 禁用。
  • model:心跳运行的可选覆盖模型(provider/model)。
  • includeReasoning:当 true 时,心跳还将在可用时传递单独的 Reasoning: 消息(与 /reasoning on 相同的形状)。默认:false
  • session:用于控制心跳在哪个 session 中运行的可选 session 键。默认:main
  • to:可选收件人覆盖(channel 特定 id,例如 WhatsApp 的 E.164、Telegram 的聊天 id)。
  • target:可选交付 channel(lastwhatsapptelegramdiscordslackmsteamssignalimessagenone)。默认:last
  • prompt:心跳正文的可选覆盖(默认:Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.)。覆盖按原样发送;如果你仍然想要读取文件,请包含 Read HEARTBEAT.md 行。
  • ackMaxChars:交付前 HEARTBEAT_OK 后允许的最大字符数(默认:300)。

每 agent 心跳:

  • 设置 agents.list[].heartbeat 以启用或覆盖特定 agent 的心跳设置。
  • 如果任何 agent 条目定义了 heartbeat,仅这些 agents 运行心跳;defaults 成为这些 agents 的共享基线。

心跳运行完整的 agent 轮次。较短的间隔消耗更多 tokens;注意 every,保持 HEARTBEAT.md 小,和/或选择更便宜的 model

tools.exec 配置后台 exec 默认值:

  • backgroundMs:自动后台之前的时间(ms,默认 10000)
  • timeoutSec:此运行时间后自动终止(秒,默认 1800)
  • cleanupMs:在内存中保留已完成 sessions 的时间(ms,默认 1800000)
  • notifyOnExit:当后台 exec 退出时排队系统事件 + 请求心跳(默认 true)
  • applyPatch.enabled:启用实验性 apply_patch(仅 OpenAI/OpenAI Codex;默认 false)
  • applyPatch.allowModels:模型 ids 的可选白名单(例如 gpt-5.2openai/gpt-5.2) 注意:applyPatch 仅在 tools.exec 下。

tools.web 配置 web 搜索 + 获取工具:

  • tools.web.search.enabled(默认:当密钥存在时为 true)
  • tools.web.search.apiKey(推荐:通过 openclaw configure --section web 设置,或使用 BRAVE_API_KEY 环境变量)
  • tools.web.search.maxResults(1–10,默认 5)
  • tools.web.search.timeoutSeconds(默认 30)
  • tools.web.search.cacheTtlMinutes(默认 15)
  • tools.web.fetch.enabled(默认 true)
  • tools.web.fetch.maxChars(默认 50000)
  • tools.web.fetch.timeoutSeconds(默认 30)
  • tools.web.fetch.cacheTtlMinutes(默认 15)
  • tools.web.fetch.userAgent(可选覆盖)
  • tools.web.fetch.readability(默认 true;禁用以仅使用基本 HTML 清理)
  • tools.web.fetch.firecrawl.enabled(默认 true,当设置 API key 时)
  • tools.web.fetch.firecrawl.apiKey(可选;默认为 FIRECRAWL_API_KEY)
  • tools.web.fetch.firecrawl.baseUrl(默认 https://api.firecrawl.dev)
  • tools.web.fetch.firecrawl.onlyMainContent(默认 true)
  • tools.web.fetch.firecrawl.maxAgeMs(可选)
  • tools.web.fetch.firecrawl.timeoutSeconds(可选)

tools.media 配置入站媒体理解(image/audio/video):

  • tools.media.models:共享模型列表(capability-tagged;在每 cap 列表之后使用)。
  • tools.media.concurrency:最大并发 capability 运行(默认 2)。
  • tools.media.image / tools.media.audio / tools.media.video:
    • enabled:选择退出开关(默认 true,当配置模型时)。
    • prompt:可选提示覆盖(image/video 自动附加 maxChars 提示)。
    • maxChars:最大输出字符(默认 image/video 500;audio 未设置)。
    • maxBytes:发送的最大媒体大小(默认:image 10MB、audio 20MB、video 50MB)。
    • timeoutSeconds:请求超时(默认:image 60s、audio 60s、video 120s)。
    • language:可选音频提示。
    • attachments:附件策略(modemaxAttachmentsprefer)。
    • scope:带 match.channelmatch.chatTypematch.keyPrefix 的可选门控(第一个匹配获胜)。
    • models:模型条目的有序列表;失败或超大媒体回退到下一个条目。
  • 每个 models[] 条目:
    • Provider 条目(type: "provider" 或省略):
      • provider:API provider id(openaianthropicgoogle/geminigroq 等)。
      • model:模型 id 覆盖(image 必需;audio providers 默认为 gpt-4o-mini-transcribe/whisper-large-v3-turbo,video 默认为 gemini-3-flash-preview)。
      • profile / preferredProfile:auth 配置文件选择。
    • CLI 条目(type: "cli"):
      • command:要运行的可执行文件。
      • args:模板化参数(支持 {{MediaPath}}{{Prompt}}{{MaxChars}} 等)。
    • capabilities:用于控制共享条目的可选列表(imageaudiovideo)。省略时的默认值:openai/anthropic/minimax → image,google → image+audio+video,groq → audio。
    • promptmaxCharsmaxBytestimeoutSecondslanguage 可以按条目覆盖。

如果未配置模型(或 enabled: false),则跳过理解;模型仍接收原始附件。

Provider auth 遵循标准模型 auth 顺序(auth 配置文件、环境变量如 OPENAI_API_KEY/GROQ_API_KEY/GEMINI_API_KEY,或 models.providers.*.apiKey)。

示例:

{
  tools: {
    media: {
      audio: {
        enabled: true,
        maxBytes: 20971520,
        scope: {

[truncated - 已翻译前 2000 行内容]