#agent

1 messages · Page 1 of 1 (latest)

dusky roseBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

cobalt fieldBOT
#

如果你在 WSL 里跑 OpenClaw,主要用来写代码/跑重复任务,我的建议是:

结论(怎么选)

  • 只给自己用(私聊/本机自己触发):先别开 sandbox(mode: "off")。省事、少坑、性能更好,尤其是“写代码”经常要装依赖/跑构建/访问网络。
  • 会暴露给群聊/外部输入(比如 Discord 群、公开频道、多人可触发):建议开 sandbox,至少用 mode: "non-main",把“非主会话”放进 Docker 里,降低误操作/注入的爆炸半径。

关键点:Sandbox 决定“工具在哪跑(Docker vs host)”;但真正限制能力的往往是 Tool policy(allow/deny)。两者要配合用。
文档:

WSL 场景下开 sandbox 你需要知道的坑

  • OpenClaw 的 sandbox 是 Docker 容器:你得先把 Docker(Docker Desktop / WSL Docker)搞定,否则开了也跑不起来。
  • 默认 sandbox 网络是 none(无出网),而且默认镜像可能不带你需要的运行时/工具链;做“写代码”类任务时,可能需要额外配置镜像或 setupCommand(文档里有)。
  • 你如果要让 agent 直接改你的代码仓库,需要 workspaceAccess: "rw" 或 bind mount——这会降低隔离强度(但仍然比完全在 host 上跑要“收敛”一些)。

推荐配置思路(按你“写代码”的需求)

#
  1. 先跑通功能sandbox.mode = "off"
  2. 确认稳定后,如果要接入群聊/外部输入:改成 sandbox.mode = "non-main"(常见、安全感更好)
  3. 真要全程沙箱:sandbox.mode = "all",并明确 workspaceAccess / binds

另外你可以用这个命令看 OpenClaw 实际到底有没有把当前会话 sandbox 了:
openclaw sandbox explain(文档:https://docs.openclaw.ai/cli/sandbox)


你现在的使用方式是:只自己私聊用,还是会把它接到 Discord/Telegram 群里让别人也能触发?这决定我更推荐 off 还是 non-main

elder field
#

目前我自己在学习。1、我计划使用飞书创建多个机器人。写代码、写作、头脑风暴,智能客服(给其他人用或群聊)

cobalt fieldBOT
#

这种规划(飞书里多个机器人:写代码/写作/脑暴/客服)**很适合用“多 agent + 不同 sandbox/工具权限”**来做隔离:

1) 我会怎么配(推荐落地方案)

A. 你的「开发/写代码」机器人(只自己用)

  • sandbox:先关mode: "off"
  • 原因:写代码经常要 exec 跑测试/安装依赖/访问网络/读写大量文件;一上来全沙箱会多很多 Docker/镜像/网络/工具链的坑。
  • 等你熟了、或者要更安全时,再考虑把它也放进沙箱,但那时你要明确配置 workspaceAccess: "rw" / bind mounts。

B. 你的「写作 / 头脑风暴」机器人(只自己用)

  • sandbox:可关off)或 non-main
  • 工具权限:可以更保守(通常不需要 exec / process / 改文件)
  • 这个 agent 的价值是“产出文本”,不是动你的系统。

C. 你的「智能客服」机器人(给其他人用 / 群聊)

  • 强烈建议:sandbox 开到 all(或者至少 non-main,但客服这种我更倾向 all
  • 工具权限:强限制(核心思路:只允许它“回答/查资料”,不要让它“执行/写入/改文件/跑命令”)
    • deny:exec, write, edit, apply_patch, process, browser(这些基本都不该给客服)
#
  • allow:message +(如果需要联网查公开文档)web_fetch/web_search + memory_*

文档(建议你按这两篇的心智模型来配):

2) 一个“形状正确”的配置示例(你可以按这个思路改)

(下面是示意,重点看 每个 agent 不同的 sandbox + tools,具体绑定到飞书哪个 bot/群,取决于你飞书 provider 的 match 字段)

{
  agents: {
    list: [
      {
        id: "dev",
#
        default: true,
        workspace: "~/.openclaw/workspace-dev",
        sandbox: { mode: "off" }
      },
      {
        id: "writer",
        workspace: "~/.openclaw/workspace-writer",
        sandbox: { mode: "off" },
        tools: {
          deny: ["exec", "process"] // 写作一般不需要跑命令
        }
      },
      {
        id: "cs",
        workspace: "~/.openclaw/workspace-cs",
#
        sandbox: { mode: "all", scope: "agent", workspaceAccess: "none" },
        tools: {
          allow: ["group:messaging", "group:memory", "web_fetch", "web_search"],
          deny: ["group:runtime", "group:fs", "browser", "canvas"]
        }
      }
    ]
  }
}

3) 你在 WSL 里要特别注意两点

  • sandbox = Docker 容器:WSL 里你得先确认 Docker 跑通,否则开启后会卡在容器/镜像层面。
  • 沙箱默认可能 无网络,而且默认镜像可能不带完整开发工具链;所以“开发 agent 一上来就全沙箱”体验通常会比较折磨。

4) 我需要你确认两件事(决定我给你下一步怎么配)

#
  1. 你飞书这边是:每个机器人一个独立 bot token,还是同一个 bot 在不同群里用?
  2. 你现在 WSL 里 Docker 是否可用(能 docker ps)?

如果你回这两条,我可以按你的飞书拓扑(多个 bot / 多个群)给你一个更具体的“路由/绑定到 agent”的配置思路。

elder field
#

我计划把写代码/写作/脑暴放到同一个群中

#

docker可以正常使用

cobalt fieldBOT
#

把「写代码 / 写作 / 脑暴」放在同一个飞书群里,最稳、隔离最清晰的做法是:

推荐做法:同一个群里放 多个飞书机器人(多个 App),每个机器人绑定一个 agent

原因:OpenClaw 的 binding 路由主要按 (channel, accountId, peer) 把消息送到某个 agentId
如果你只有 一个飞书 bot(一个 account),那这个群基本就只能稳定路由到 一个 agent;想“同群多角色”会变成靠提示词/技能在同一个脑子里切换,隔离性差很多。

飞书支持多 account(多 bot)这一点在官方 multi-agent 文档里也明确列了 feishu
文档:Multi-Agent Routing https://docs.openclaw.ai/concepts/multi-agent

你要做的结构

  • 飞书里建 3 个 App(3 个 bot):例如 CodingBot / WriterBot / BrainstormBot
  • 把这 3 个 bot 都拉进同一个群
  • OpenClaw 里配置 3 个 channels.feishu.accounts.<id>(每个对应一个 bot 的 appId/appSecret
  • 再用 bindings 把每个 accountId 路由到对应的 agentId

飞书渠道配置文档(含 appId/appSecret/botName 这些准确字段):

#

配置“长得像这样”(示意)

{
  channels: {
    feishu: {
      enabled: true,
      accounts: {
        coding: { appId: "cli_xxx", appSecret: "xxx", botName: "CodingBot" },
        writer: { appId: "cli_yyy", appSecret: "yyy", botName: "WriterBot" },
        idea:   { appId: "cli_zzz", appSecret: "zzz", botName: "BrainstormBot" }
      }
    }
  },
#
  agents: {
    list: [
      { id: "coding", workspace: "~/.openclaw/workspace-coding", sandbox: { mode: "off" } },
      { id: "writer", workspace: "~/.openclaw/workspace-writer", sandbox: { mode: "off" }, tools: { deny: ["exec","process"] } },
      { id: "idea",   workspace: "~/.openclaw/workspace-idea",   sandbox: { mode: "off" }, tools: { deny: ["exec","process"] } }
    ]
  },

  bindings: [
    { agentId: "coding", match: { channel: "feishu", accountId: "coding" } },
    { agentId: "writer", match: { channel: "feishu", accountId: "writer" } },
    { agentId: "idea",   match: { channel: "feishu", accountId: "idea" } }
  ]
}
#

Sandbox 怎么选(针对你这个“同群三个内部机器人”的场景)

  • 这三个如果只你自己用/学习用:我会先都 sandbox: off,体验最好。
  • 以后如果这个群里会有其他人、或者你要加“客服 bot 给别人用”:再单独给客服 agent 开 sandbox: all + 严格 tools.allow/deny

两个关键确认问题(决定你接下来是不是会踩坑):

  1. 这个飞书群里只有你,还是会有同事也能发消息触发这些 bot?
  2. 你准备让 CodingBot 真的在 WSL 里 exec 跑命令+改代码吗(也就是“真·coding agent”)?

你回答这两条,我就能给你一个更具体的“coding bot 是否需要 sandbox、writer/idea 怎么限制工具权限”的最小可用配置。

#

OK,那你在 WSL 里 Docker 正常的话,sandbox 这条路就完全走得通了。

我建议你现在这样配(最省心、也最安全)

1) 你自己用的 3 个 bot(coding / writer / idea)

  • 先都不启用 sandboxsandbox.mode: "off"
  • 原因:写代码最怕被 sandbox 默认的 workspaceAccess: "none"、无网络、镜像工具链不全这些东西卡住;先把“能稳定干活”跑通最重要。
  • writer/idea 这两个可以靠 tools.deny 收紧(比如禁用 exec/process),但不一定需要 Docker sandbox。

2) “客服/给别人用”的 bot(强烈建议单独一个 bot / 单独一个 agent)

  • 启用 sandbox:mode: "all",并且严格限制 tools(基本禁掉 exec/write/edit/apply_patch/process/browser
  • 这样别人就算在群里乱问/注入,爆炸半径也小很多。

参考文档:

#

你下一步可以做的 3 件事(落地顺序)

  1. 装飞书插件(必需):openclaw plugins install @openclaw/feishu
  2. 建多个飞书 App(多个 bot),都拉进同一个群
  3. ~/.openclaw/openclaw.json 里加多个 channels.feishu.accounts.<id>,然后用 bindings 把每个 accountId 绑定到对应 agentId(这样同群里你@不同 bot,就等于切换不同 agent)

如果你也想“coding bot 也沙箱化”

可以,但你得提前规划两点,否则一定踩坑:

  • workspaceAccess 要能写(通常是 "rw"),不然它看不到/改不了你的代码
  • 以及你的项目目录要不要通过 docker.binds 挂进去(不挂的话它只会在自己的沙箱工作区里写)

最后确认一句:你这个“同一个群”里,会有其他人也能发消息触发这些 bot 吗?

  • 如果会:那客服 bot 我会强推 sandbox: all + 严格 tools;coding bot 最好也至少加 exec approvals/限制。
  • 如果不会(只有你):coding/writer/idea 全部 sandbox: off 就很舒服。
elder field
#

群只有我再用,机器人测试阶段不对外

cobalt fieldBOT
#

那就简单了:群里只有你、测试阶段不对外 → 我会把优先级放在“先跑通工作流”,sandbox 可以先不启用。

你的场景(只有你用)我推荐:

  • CodingBot(真写代码/跑命令/改文件)sandbox: off
    省掉 Docker 镜像/网络/挂载/工具链这些变量,体验最好。
  • WriterBot / BrainstormBot:也可以 sandbox: off,但建议用 tools.deny 收紧一下(比如禁用 exec/process,避免它乱跑命令)。

这样你在同一个群里通过 @不同的飞书机器人,就等于切换到不同 agent/不同 workspace,不会互相污染上下文。

什么时候再开 sandbox?

等你准备把某个 bot 给别人用 / 加到多人群 / 做客服 的时候,再单独给那个 agent 开:

  • sandbox.mode: "all"(或至少 non-main
  • 严格 tools.allow/deny(通常禁掉 exec/write/edit/apply_patch/process/browser

这样安全收益最大,而且不会影响你现在“coding bot 要高频干活”的体验。

如果你愿意,我可以根据你准备建的 3 个飞书 bot 名称(比如 coding/writer/idea)给你一份最小可用的 agents.list + channels.feishu.accounts + bindings 模板,你直接填 appId/appSecret 就能跑。

elder field
#

飞书怎么配置的 OpenClaw 2026.3.7 (42a1394) — Your personal assistant, minus the passive-aggressive calendar reminders.


◇ Config warnings ────────────────────────────────────────────────────────────────────────────────────────────╮
│ │
│ - plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may │
│ be overridden │
│ (/root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/ │
│ index.ts) │
│ │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

◇ Doctor warnings ──────────────────────────────────────────────────────────────────────────╮
│ │
│ - channels.feishu.groupPolicy is "allowlist" but groupAllowFrom (and allowFrom) is empty │
│ — all group messages will be silently dropped. Add sender IDs to │
│ channels.feishu.groupAllowFrom or channels.feishu.allowFrom, or set groupPolicy to │
│ "open".

cobalt fieldBOT
#

你这两条 warning 都很典型,按下面改完飞书就能正常在群里回了。


1) 关键问题:你现在把 channels.feishu.groupPolicy 设成了 allowlist,但白名单是空的

Doctor 已经说得很直白了:群消息会被静默丢弃

测试阶段(最推荐、最快跑通)

把飞书群策略改成 open

// ~/.openclaw/openclaw.json  (注意是 JSON5 不是 YAML)
{
  channels: {
    feishu: {
      groupPolicy: "open",
#
      // 群里默认 requireMention: true,所以要 @机器人它才会回
    }
  }
}

飞书文档里也写了:groupPolicy: "open" 是“允许所有群组”的默认行为,并且群里默认需要 @ 提及才响应。
文档(群组配置示例那一段):https://docs.openclaw.ai/zh-CN/channels/feishu

如果你坚持用 allowlist(更安全)

那就把你的群 chat_id(格式 oc_xxx)加进去:

{
  channels: {
#
    feishu: {
      groupPolicy: "allowlist",
      groupAllowFrom: ["oc_xxx"], // 你的群 chat_id
    }
  }
}

怎么拿到 oc_xxx? 文档推荐的方法也是最省事的:

  1. 启动网关
  2. 在群里 @机器人发一句
  3. openclaw logs --follow 里会打印 chat_id
    (见文档“获取群组/用户 ID”小节)

#

2) 另一个 warning:duplicate plugin id detected

这个一般是因为 feishu 插件在两个地方都被发现了(比如你装了 @openclaw/feishu,同时 OpenClaw 安装包里也带了一份 bundled 的 extensions/feishu),通常不影响功能,只是提示“哪个会被优先加载”。

你可以先不管它,先把群策略修好(第 1 条),看机器人能不能回。

如果你很想把 warning 消掉,再做这个排查:

  • openclaw plugins list 看看 feishu 实际加载来源是哪个
  • 确保只保留一种来源(一般保留 @openclaw/feishu 那份就行)

插件命令文档:https://docs.openclaw.ai/tools/plugin


3) 飞书最小可用配置(确认字段没写错)

(注意不要把 appSecret 发出来)

#
{
  channels: {
    feishu: {
      enabled: true,
      dmPolicy: "pairing",
      groupPolicy: "open",
      accounts: {
        main: {
          appId: "cli_xxx",
          appSecret: "xxx",
          botName: "我的AI助手",
        }
      }
    }
  }
#
}

你现在想先跑通“群里 @机器人就能回”的话:把 groupPolicy 改成 "open",重启 gateway,然后在群里 @它发一句。
如果还不回,把 openclaw logs --follow@那条消息附近的几行贴出来(记得打码 appSecret)。

elder field
#

openclaw channels add

🦞 OpenClaw 2026.3.7 (42a1394) — Self-hosted, self-updating, self-aware (just kidding... unless?).Install Feishu plugin?
│ Download from npm (@openclaw/feishu)
Downloading @openclaw/feishu…
Extracting /tmp/openclaw-npm-pack-YhrphP/openclaw-feishu-2026.3.7.tgz…
WARNING: Plugin "feishu" contains dangerous code patterns: Environment variable access combined with network send — possible credential harvesting (/tmp/openclaw-plugin-cFlk0j/extract/package/src/client.test.ts:74); Environment variable access combined with network send — possible credential harvesting (/tmp/openclaw-plugin-cFlk0j/extract/package/src/client.ts:12)
Installing to /root/.openclaw/extensions/feishu…
Installing plugin dependencies…
16:53:31 [plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load: feishu (/root/.openclaw/extensions/feishu/index.ts). Set plugins.allow to explicit trusted ids.
16:53:32 [plugins] feishu failed to load from /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/index.ts: Error: Cannot find module '@larksuiteoapi/node-sdk'
Require stack:

  • /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/src/client.ts

    ◇ Channel setup ───────────────────────────╮
    │ │
    │ feishu does not support onboarding yet. │ 这是为什么
cobalt fieldBOT
#

这段输出里其实有 3 件事叠在一起了,所以看起来很“迷”:


A) feishu does not support onboarding yet 是什么意思?为什么会这样?

这里的 onboarding 指的是 CLI 的交互式向导(openclaw channels add / openclaw onboard 那种一步步问你问题然后写配置)

Feishu 这个插件在你当前版本里,还没实现/没接上这个交互式向导接口,所以 channels add 走到“配置渠道”那步就只能提示“不支持 onboarding”。

但这 不代表 Feishu 不能用 —— 只是你需要 手动改 ~/.openclaw/openclaw.json 来配置 channels.feishu...(文档也给了完整配置块)。

飞书配置文档(中文):https://docs.openclaw.ai/zh-CN/channels/feishu


B) Cannot find module '@larksuiteoapi/node-sdk' 这个错误怎么回事?

这条很关键:OpenClaw 现在尝试加载的是 OpenClaw 自带的那份 bundled feishu 扩展

#

.../lib/node_modules/openclaw/extensions/feishu/...

而这份 bundled 拓展里 没有带依赖(所以找不到 @larksuiteoapi/node-sdk),于是加载失败。

你刚刚其实已经把官方插件装到了:

/root/.openclaw/extensions/feishu

那份才是“带依赖、该用的”版本。
之所以你在同一个进程里安装完插件后仍然看到它去 load bundled 版,大概率是 安装发生在命令执行途中,插件加载/缓存没刷新,导致仍然按旧的插件表去加载。

最简单的处理:

  1. 先退出当前命令(你已经结束了)
  2. 运行 openclaw plugins list,确认 feishu 的来源是 /root/.openclaw/extensions/feishu/...
  3. 然后 openclaw gateway restart(或重新启动 gateway)
  4. 再看 openclaw logs --follow 里是否还报 @larksuiteoapi/node-sdk 缺失
#

如果重启后还是报同样错误,把 openclaw plugins list 的输出贴一下(不用打码),我就能判断它到底加载的是哪一份 feishu。


C) 你看到的 “危险代码模式” WARNING 要不要慌?

这个是 插件安全扫描器的提醒:它检测到“读取环境变量 + 发送网络请求”这种组合(确实可能被用来偷凭证)。
但对一个“要读 AppSecret / 发请求到飞书”的官方渠道插件来说,这个 pattern 本身是正常的

你可以做两件事来让它更“可控”:

  • plugins.allow 明确声明你信任哪些插件 id(至少加 feishu),避免“自动加载未知插件”的风险
  • 只从 npm 安装官方包(你现在就是这么做的)

你现在应该怎么配置飞书(手动写配置,跳过 onboarding)

~/.openclaw/openclaw.json 里放最小配置(别把 appSecret 发出来):

#
{
  channels: {
    feishu: {
      enabled: true,
      dmPolicy: "pairing",
      groupPolicy: "open", // 测试阶段建议 open,先跑通群聊
      accounts: {
        main: {
          appId: "cli_xxx",
          appSecret: "xxx",
          botName: "我的AI助手"
        }
      }
    }
  },
#

  // 可选:明确只信任 feishu 插件(推荐)
  plugins: {
    allow: ["feishu"]
  }
}

然后重启 gateway:openclaw gateway restart,群里 @机器人发一句,看日志里是否收到 chat_id


如果你愿意最快定位:你把下面两段输出贴出来(都不包含敏感信息)我就能直接告诉你下一步该改哪里:

  1. openclaw plugins list
  2. 重启后 openclaw logs --follow报错那几行(别贴整屏)。
elder field
#

我计划重新卸载了。重新安装

cobalt fieldBOT
#

可以的。重装前我建议你先选一下“清理程度”,避免把以后还要用的东西(模型凭证、飞书 appSecret、workspace)一起删了。

方案 1(推荐先试):只重置本地状态,不卸载 CLI

如果你只是想“回到刚安装完的干净状态”,用 reset 更快:

方案 2:彻底卸载 + 重新安装(你现在说的这个)

如果你确定不需要保留任何配置/凭证/会话:

#
openclaw uninstall --all --yes --non-interactive

它做的事大致等价于:

  1. openclaw gateway stop
  2. openclaw gateway uninstall(卸载 systemd/服务)
  3. 删除 $HOME/.openclaw(你这边看起来是 /root/.openclaw
  4. 卸载全局 openclaw 包

重新安装

按官方安装脚本走一遍即可:

curl -fsSL https://openclaw.ai/install.sh | bash

然后再 openclaw onboard(能配模型/网关等),飞书插件之后再装。

#

两个重要提醒(避免二次踩坑)

  1. 你现在路径都是 /root/...,说明你大概率是 root 用户在跑。WSL 里更推荐用普通用户装/跑(权限和路径更干净)。
  2. 重装后装飞书插件建议立刻把信任白名单写上,避免插件自动加载提示:
    { plugins: { allow: ["feishu"] } }
    

你想要的是“彻底清空所有东西重新来”,还是“保留模型/飞书凭证,只清空配置和会话”?我可以按你的目标给你最短的命令序列。

elder field
#

已经卸载,怎么开始配置

cobalt fieldBOT
#

你现在是“全新环境从 0 配”,按这个顺序走最稳(先跑通 1 个飞书 bot,再扩展到多个 bot/agent):

0) 先确认你不是用 root 在跑(强烈建议)

你之前日志里路径都是 /root/...,说明你当时是 root 用户在装/跑,这样很容易把状态、插件、权限搞乱。

在 WSL 里建议用普通用户:

whoami
echo $HOME

如果显示是 root,建议先切到普通用户再装(后面所有路径都会变成 /home/<user>/.openclaw/...)。


1) 重新安装 OpenClaw

按官方安装脚本装一遍:

#
curl -fsSL https://openclaw.ai/install.sh | bash

装完确认:

openclaw --version

2) 先跑一次基础向导(可选但推荐)

openclaw onboard

(它主要帮你把模型/网关基础配置跑通。飞书部分就算向导不支持,我们也可以后面手动配。)

#

3) 安装飞书插件

openclaw plugins install @openclaw/feishu --pin
openclaw plugins list

plugins list 里你要看到 feishu 是从你自己的 ~/.openclaw/extensions/feishu 之类的路径加载(不要又跑去 node_modules 里那份 bundled)。


4) 手动写飞书配置(关键)

编辑 ~/.openclaw/openclaw.json(JSON5),最小可用配置长这样(别把 appSecret 发出来):

{
#
  plugins: { allow: ["feishu"] },

  channels: {
    feishu: {
      enabled: true,
      connectionMode: "websocket",
      dmPolicy: "pairing",
      groupPolicy: "open", // 测试阶段建议 open,避免群消息被 allowlist 静默丢掉
      accounts: {
        main: {
          appId: "cli_xxx",
          appSecret: "xxx",
          botName: "MyBot"
        }
      }
#

然后去飞书:

  • 把 bot 拉进群
  • 在群里 @机器人 发一句(默认 requireMention=true)
  • 日志里应该能看到 chat_id(形如 oc_xxx

6) (如果你还要配私聊)批准 pairing

私聊机器人会给 pairing code,然后:

openclaw pairing list feishu
openclaw pairing approve feishu <CODE>

等你把 一个 bot 在群里跑通后,我们再做“同群 3 个机器人(coding/writer/idea)+ 多 agent bindings”的配置,会非常顺滑。

#

你现在卡在哪一步?是 openclaw gateway 启动报错,还是飞书群里 @了不回?把 openclaw logs --follow 里最新的报错几行贴出来就行(打码 appSecret)。

elder field
#

这是为什么 openclaw plugins install @m1heng-clawd/feishu

🦞 OpenClaw 2026.3.7 (42a1394) — I run on caffeine, JSON5, and the audacity of "it worked on my machine."

Downloading @m1heng-clawd/feishu…
Extracting /tmp/openclaw-npm-pack-zeWJYr/m1heng-clawd-feishu-0.1.16.tgz…
Installing to /root/.openclaw/extensions/feishu…
Installing plugin dependencies…
22:15:01 [plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load: feishu (/root/.openclaw/extensions/feishu/index.ts). Set plugins.allow to explicit trusted ids.
22:15:02 [plugins] feishu failed to load from /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/index.ts: Error: Cannot find module '@larksuiteoapi/node-sdk'
Require stack:

  • /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/src/client.ts
    Config warnings:
  • plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)
    Config overwrite: /root/.openclaw/openclaw.json (sha256 9aece4cf28bd51f561760752cb13be8826940f364b60969fc7bc9a83f97660c9 -> ea65d31b8c0529b7e1a6cc91b314b7120910da03942a3cc6f609ee1cb46ae81b, backup=/root/.openclaw/openclaw.json.bak)
    Installed plugin: feishu
    Restart the gateway to load plugins. 这是安装成功了吗
cobalt fieldBOT
#

从这段日志看:“安装成功(文件写到了磁盘 + 配置也写进 openclaw.json)”,但 “目前还没法正常使用” ——因为 OpenClaw 现在实际加载的是 OpenClaw 自带的那份 bundled feishu(在 .../node_modules/openclaw/extensions/feishu/...),它缺少依赖 @larksuiteoapi/node-sdk,所以加载失败。

你看到的几行其实已经把结论写出来了:

  • Installing to /root/.openclaw/extensions/feishu… → 说明插件确实装进去了
  • Installed plugin: feishu → 说明安装流程走完了
  • 但紧接着:
    feishu failed to load from .../node_modules/openclaw/extensions/feishu/... Cannot find module '@larksuiteoapi/node-sdk'
    • duplicate plugin id detected; later plugin may be overridden
      说明现在有两份 id 都叫 feishu 的插件/扩展在“抢”同一个 id,结果 bundled 那份抢赢了,而它又缺依赖,所以挂了。

你现在要做的就是:把“抢赢的那份”清掉/降级,让 ~/.openclaw/extensions/feishu 这份生效

Step 1:先看当前到底加载了哪一份(请把输出贴出来)

openclaw plugins list
#
openclaw plugins info feishu

Step 2:把 feishu 彻底卸载干净再装(推荐走官方插件,别用第三方)

第三方 @m1heng-clawd/feishu 不会解决这个“重复 id”问题,反而增加变量。建议回到官方:

openclaw plugins uninstall feishu
# 然后重新安装官方插件
openclaw plugins install @openclaw/feishu --pin

plugins uninstall 会把 plugins.entries / plugins.installs / allowlist / 以及可能的 plugins.load.paths(如果是 link 安装造成的)一起清掉(见 CLI 文档)。

Step 3:在配置里显式信任插件(顺便消掉 allow 警告)

~/.openclaw/openclaw.json 加一段:

#
{
  plugins: { allow: ["feishu"] }
}

Step 4:重启 gateway(必须)

openclaw gateway restart
# 或者没装服务就直接 openclaw gateway

另外一个大雷:你现在还是在用 root(/root/.openclaw)

我强烈建议你别用 root 跑(插件/路径/权限真的容易乱)。如果你愿意折腾一次到位:换普通用户重新装,会干净很多。

#

你先把 openclaw plugins listopenclaw plugins info feishu 的输出贴出来(不含任何 secret),我就能直接判断:到底是哪条配置/路径导致 bundled 那份被优先加载。

elder field
#

root@good:~# openclaw plugins list | grep feishu
Config warnings:\n- plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)
Config warnings:\n- plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)
[plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load: feishu (/root/.openclaw/extensions/feishu/index.ts). Set plugins.allow to explicit trusted ids.
[plugins] feishu failed to load from /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/index.ts: Error: Cannot find module '@larksuiteoapi/node-sdk'
Require stack:

  • /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/src/client.ts
    │ - plugins.entries.feishu: plugin feishu: duplicate plugin id detected; │
    │ (/root/.openclaw/extensions/feishu/index.ts) │
    Config warnings:\n- plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)
    │ @openclaw/ │ feishu │ error │ stock:feishu/index.ts
    │ 2026.3.7 │
    │ feishu │ │ │ OpenClaw Feishu/Lark channel plugin (community maintained by │ │
    │ @m1heng- │ feishu │ disabled │ global:feishu/index.ts │ 0.1.16 │
    │ clawd/feishu │ │ │ OpenClaw Feishu/Lark channel plugin │
cobalt fieldBOT
#

你这个输出说明两件事:

  1. “装进去了”:插件文件确实被写到了 /root/.openclaw/extensions/feishu,而且 config 也被更新了(还生成了 .bak 备份)。
  2. 但“还不能用”:OpenClaw 现在实际优先加载的是 OpenClaw 自带那份 .../node_modules/openclaw/extensions/feishu/...(你看到的 stock:feishu/index.ts),它缺少依赖 @larksuiteoapi/node-sdk,所以报错。

所以回答你:安装“成功”是指文件落盘+配置写入成功;但当前加载失败,功能上还不算成功。


为啥会这样(核心原因)

plugins list 里已经写明白了:

  • @openclaw/ feishu error stock:feishu/index.ts ← 这份被选中加载,但缺依赖,挂了
  • @m1heng-clawd/feishu disabled global:feishu/index.ts ← 你装的这份在 ~/.openclaw/extensions,但被“抢不过/被覆盖”所以变成 disabled

这通常是因为 配置里有一条高优先级的插件加载路径/记录,让 “stock/bundled 那份 feishu” 抢先了(所以你一直看到从 .../node_modules/openclaw/extensions/feishu/... 报错)。

#

最快修复(推荐:清掉冲突 → 只留官方插件)

按下面顺序来:

1) 先卸载 feishu(清理掉 entries / installs / allowlist / load.paths 冲突)

openclaw plugins uninstall feishu

2) 重新安装官方插件(固定版本,少变量)

openclaw plugins install @openclaw/feishu --pin

3) 在 ~/.openclaw/openclaw.json 里加上(消掉 allow 警告,也更安全)

#
{
  plugins: { allow: ["feishu"] }
}

4) 重启 gateway

openclaw gateway restart

5) 验证

openclaw plugins list
openclaw plugins info feishu

你要看到 feishu 的状态是 ok/ready,并且加载来源是 .../.openclaw/extensions/feishu/...(而不是 .../node_modules/openclaw/extensions/feishu/...)。

#

重要提醒

你现在还是 root 用户(/root/.openclaw)。这会让路径、权限、以及“到底加载哪份插件”更容易乱。等你跑通后,强烈建议迁移到普通用户环境再做长期使用。


如果你愿意更精确定位“是谁把 stock 那份置顶了”:把你 ~/.openclaw/openclaw.jsonplugins 这一段贴出来(只贴 plugins: {...},不要贴任何 secret),我可以直接指出是哪一行导致 stock 优先。

elder field
#

openclaw plugins info feishu

🦞 OpenClaw 2026.3.7 (42a1394) — Built by lobsters, for humans. Don't question the hierarchy.

@openclaw/feishu
id: feishu
OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)

Status: disabled
Source: ~/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/index.ts
Origin: bundled
Version: 2026.3.7
Error: bundled (disabled by default)

cobalt fieldBOT
#

你这条 plugins info feishu 的输出其实是在说:

  • 现在你机器上 “能被识别为 feishu 的插件”只有一份:OpenClaw 自带(bundled)的那份
    Source: .../node_modules/openclaw/extensions/feishu/index.ts
  • 它的状态是 disabled,并且提示 “bundled (disabled by default)”
    这不是报错,只是说明:它默认不开启,你还没把 feishu 插件启用起来。

但你之前遇到的真正阻塞点是:一旦它被加载,就会因为缺少 @larksuiteoapi/node-sdk 报错。


推荐的“正确姿势”(避免再走到 bundled 那条路)

让 OpenClaw 优先加载你安装到 ~/.openclaw/extensions/feishu 的那份(它会带自己的依赖),而不是用 node_modules 里那份 bundled。

1) 先把 feishu 清理干净再装(避免残留冲突)

#
openclaw plugins uninstall feishu

2) 安装官方插件(npm 包那份)

openclaw plugins install @openclaw/feishu --pin

3) 强制把“你安装的那份”置顶(关键)

编辑 /root/.openclaw/openclaw.json,加上:

{
  plugins: {
    allow: ["feishu"],
#
    load: {
      paths: ["/root/.openclaw/extensions/feishu"]
    }
  }
}

plugins.load.paths 的优先级最高(文档里 scan 顺序就是它最先),这样就不会再被 .../node_modules/openclaw/extensions/feishu 那份抢走了。

4) 启用 + 重启

openclaw plugins enable feishu
openclaw gateway restart

5) 验证(你应该看到 source 指向 /root/.openclaw/extensions/feishu)

#
openclaw plugins info feishu

你先做一个确认(10 秒)

装完第 2 步后,跑一下看看插件目录是不是存在:

ls -la /root/.openclaw/extensions/feishu | head

如果这个目录都不存在,那说明你的 install 没落盘(或者 state dir 不是 /root/.openclaw),我们再沿着 OPENCLAW_STATE_DIR 去查。

elder field
#

openclaw plugins info feishu
Config warnings:\n- plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)
Config warnings:\n- plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)
22:35:49 [plugins] plugins.allow is empty; discovered non-bundled plugins may auto-load: feishu (/root/.openclaw/extensions/feishu/index.ts). Set plugins.allow to explicit trusted ids.
22:35:49 [plugins] feishu failed to load from /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/index.ts: Error: Cannot find module '@larksuiteoapi/node-sdk'
Require stack:

  • /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/src/client.ts
    Config warnings:\n- plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may be overridden (/root/.openclaw/extensions/feishu/index.ts)

🦞 OpenClaw 2026.3.7 (42a1394) — We ship features faster than Apple ships calculator updates.
◇ Config warnings
│ - plugins.entries.feishu: plugin feishu: duplicate plugin id detected; later plugin may │
│ be overridden (/root/.openclaw/extensions/feishu/index.ts) │

@openclaw/feishu
id: feishu
OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)
Status: error
Source: ~/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/index.ts
Origin: bundled
Version: 2026.3.7
Error: Error: Cannot find module '@larksuiteoapi/node-sdk'
Require stack:

  • /root/.local/share/fnm/node-versions/v24.13.0/installation/lib/node_modules/openclaw/extensions/feishu/src/client.ts
    Install: npm
    Spec: @openclaw/feishu@2026.3.7
    Install path: ~/.openclaw/extensions/feishu
    Recorded version: 2026.3.7
    Installed at: 2026-03-08T14:34:27.118Z 我麻了
cobalt fieldBOT
#

你没疯,是 OpenClaw 在加载“错误的那份 feishu 代码”

  • npm 包确实装好了(你看 Install path: ~/.openclaw/extensions/feishu
  • 但运行时实际加载的是 bundled 那份
    .../node_modules/openclaw/extensions/feishu/index.ts
    这份代码 看不到 ~/.openclaw/extensions/feishu/node_modules 里的依赖,所以一直报:
    Cannot find module '@larksuiteoapi/node-sdk'

所以:安装成功(落盘)≠ 可用(被正确加载)


解决方案(推荐):用 plugins.load.paths 强制置顶你安装的那份

按插件文档,plugins.load.paths 优先级最高(会压过 bundled)。你现在没配,所以 bundled 抢跑了。

  1. 打开配置文件:/root/.openclaw/openclaw.json
#
  1. 加上这一段(用绝对路径,别用 ~,避免解析问题):
{
  plugins: {
    allow: ["feishu"],
    load: {
      paths: ["/root/.openclaw/extensions/feishu"]
    }
  }
}
  1. 重启 gateway:
openclaw gateway restart
#
  1. 再看:
openclaw plugins info feishu

你期望看到的变化是:Source 变成 /root/.openclaw/extensions/feishu/index.ts(而不是 node_modules 那条)。


如果你照做后 Source 还是 bundled(应急兜底)

那就直接把缺的依赖装到 OpenClaw 同一个全局 node_modules 前缀里,让 bundled 那份也能 require 到:

npm i -g @larksuiteoapi/node-sdk
openclaw gateway restart
#

(这是 workaround,有点脏,但能快速验证:问题确实就是“bundled 那份找不到依赖”。)


你现在先别做太多操作:把你 /root/.openclaw/openclaw.jsonplugins: { ... } 那段贴出来(只贴 plugins 段,不要贴任何 secret),我帮你确认是不是写错位置/被其它 plugins 配置覆盖了。

elder field
#

OK,我现在已经安装好了飞书并且配置好了一个编程专家的bot。怎么配置其他几个bot

cobalt fieldBOT
#

你现在已经跑通 1 个“编程专家”飞书 bot 了,接下来加其它几个 bot(写作/脑暴/……)最稳的方式是:

一个飞书 App(机器人) = 一个 channels.feishu.accounts.<accountId> = 绑定到一个 agentId
这样你在同一个群里 @不同机器人,就会路由到不同 agent(不同 workspace/人格/工具权限)。


1)飞书侧:再创建 2~N 个 App(机器人)

对每个新 bot 重复你已经做过的那套:

  • 创建应用 → 启用机器人能力 → 配好权限 → 事件订阅用 WebSocket 长连接 + im.message.receive_v1 → 发布
  • 拿到新的 appId (cli_xxx) / appSecret
  • 把新 bot 拉进同一个群

(文档:https://docs.openclaw.ai/zh-CN/channels/feishu)


#

2)OpenClaw 配置:新增多个 Feishu account

~/.openclaw/openclaw.json 里,把 channels.feishu.accounts 从 1 个扩展成多个,比如:

{
  channels: {
    feishu: {
      groupPolicy: "open",
      accounts: {
        coding: { appId: "cli_xxx", appSecret: "xxx", botName: "CodingBot" },
        writer: { appId: "cli_yyy", appSecret: "yyy", botName: "WriterBot" },
        idea:   { appId: "cli_zzz", appSecret: "zzz", botName: "IdeaBot" }
      }
    }
  }
}
#

3)新增多个 agent(建议用向导生成工作区)

推荐用命令生成(会把 workspace / agentDir / 基础文件都建好):

openclaw agents add writer
openclaw agents add idea
# 你的 coding 如果已经是 main 或 coding agent,就不用重复 add

4)绑定:让每个 Feishu accountId 路由到对应 agentId

openclaw.jsonbindings(最简单的就是按 accountId 绑定,所有该 bot 收到的消息都去对应 agent):

#
{
  bindings: [
    { agentId: "coding", match: { channel: "feishu", accountId: "coding" } },
    { agentId: "writer", match: { channel: "feishu", accountId: "writer" } },
    { agentId: "idea",   match: { channel: "feishu", accountId: "idea" } }
  ]
}

5)可选:给不同 agent 限制工具(writer/idea 通常不需要 exec)

比如写作/脑暴 bot 禁掉跑命令:

#
{
  agents: {
    list: [
      { id: "writer", tools: { deny: ["exec", "process"] } },
      { id: "idea",   tools: { deny: ["exec", "process"] } }
    ]
  }
}

6)重启网关生效

openclaw gateway restart
#

一个容易忽略的大坑(提前说)

每个 agent 的模型登录/凭证是隔离的
也就是说你加了 writer/idea agent 后,如果它们回复时提示没模型凭证,需要你:

  • 要么分别在每个 agent 下重新做一次模型 auth
  • 要么把 auth-profiles.json 从一个 agent 复制到另一个 agent(文档里提到 auth profiles per-agent)

如果你把你现在的这 3 个 bot 计划命名发我(比如:coding / writer / idea),以及你当前 channels.feishu.accountsagents.list 的片段(appSecret 打码),我可以帮你把 bindings 那段一次性写对,避免因为 accountId/agentId 拼写不一致导致路由失败。

elder field
#

那这样的话我要重建了,因为我把main作为了编码专家。我计划的是让main接收所有消息,分配给不同的agent的。

cobalt fieldBOT
#

不用重建,你这个“main 收所有消息 → 再分配给不同 agent”在 OpenClaw 里更像是 sub-agents(子代理)编排,而不是 bindings 路由。

先讲清楚差别

  • bindings 路由:网关收到消息时,直接把这条消息路由到某个 agentId(确定性的,按 channel/accountId/peer 匹配)。这条路由发生在“进模型之前”,main 不会“先收到再转发”。
  • 你想要的 dispatcher:main 先收到消息,然后根据内容决定“让写作 agent/脑暴 agent/编码 agent 去做”,再把结果汇总回主聊天。
    这正是 Sub-agents 的用法:main 在后台 spawn 一个子代理跑任务,跑完会自动 announce 回当前聊天
    文档:https://docs.openclaw.ai/tools/subagents

方案(推荐给你现在的目标):保留 1 个飞书 bot(main),用 subagents 分派

Step 1:新建几个“专精 agent”(不影响 main)

例如:

  • coding(编码专家)
  • writer(写作)
  • idea(脑暴)
#
openclaw agents add coding
openclaw agents add writer
openclaw agents add idea

Step 2:允许 main 可以 spawn 到这些 agentId(关键开关)

~/.openclaw/openclaw.json 里给 main 加允许列表(默认只能 spawn 自己):

{
  agents: {
    list: [
      {
        id: "main",
        default: true,
#
        subagents: {
          allowAgents: ["coding", "writer", "idea"] // 或者 ["*"](你自己用的话也OK)
        }
      }
    ]
  }
}

Step 3:你在飞书里怎么用

你可以先用“手动分派”验证链路(最稳):

  • /subagents spawn writer 写一篇……
  • /subagents spawn coding 帮我改一下这段代码……
  • /subagents spawn idea 给我 20 个方案……
#

跑完它会把结果自动发回当前群聊。

等你确认这套跑通后,再去优化“自动分派”(比如你发消息用前缀 写作: / 编码: / 脑暴:,main 根据前缀自动 spawn 对应 agent)。


你说“main 已经是编码专家”怎么办?

也不用重建,有两条路:

  1. 把 main 改回“调度/总控”人设(改 main workspace 里的提示文件即可),编码工作交给 coding agent。
  2. 如果你很喜欢 main 现在的编码人设:那就新建一个 router agent 当总控,并把飞书账号的 bindings 指向 router(但你说希望 main 收所有消息,那就用方案 1)。

如果你告诉我:你希望用哪种“触发规则”来自动分派(前缀?关键词?还是你想要一个固定格式模板),我可以给你一份 main 的“调度提示词模板”,让它稳定地把任务丢给对应 subagent,而不是随机发挥。

elder field
#

这是一种办法,还有一种办法是,多个agent协作。怎么配置。

cobalt fieldBOT
#

你说的“多个 agent 协作”,在 OpenClaw 里通常有 两种实现方式(看你想要的“协作感”是哪种):


方式 1:一个主 bot(main)+ 多个专精 agent,在后台协作(推荐)

这就是我前面说的 sub-agents,但你可以把它升级成“协作模式”:

配置要点

  1. 创建多个专精 agent:coding / writer / idea / reviewer ...
  2. 允许 main 可以 spawn 到这些 agentId(否则默认只能 spawn 自己)
  3. (可选)限制每个专精 agent 的工具权限,保证安全边界(writer 禁 exec、reviewer 禁写入等)

配置示例(核心是 allowAgents)

{
  agents: {
#
    defaults: {
      subagents: {
        maxConcurrent: 4,
        runTimeoutSeconds: 900
        // model/thinking 你也可以在这里给 subagent 单独设,但先别折腾
      }
    },
    list: [
      {
        id: "main",
        default: true,
        subagents: { allowAgents: ["coding", "writer", "idea", "reviewer"] }
      },
      { id: "coding" },
      { id: "writer", tools: { deny: ["exec", "process"] } },
#
      { id: "reviewer", tools: { deny: ["write", "edit", "apply_patch", "exec"] } }
    ]
  }
}

你怎么用(协作)

  • 手动协作:/subagents spawn writer 写一篇…/subagents spawn reviewer 帮我审一下…
  • 半自动协作:你给 main 一个固定格式,比如:
    • 写作: ... → main 自动 spawn writer
    • 编码: ... → main 自动 spawn coding
    • 评审: ... → main 自动 spawn reviewer
    • 协作: ... → main 同时 spawn 2~3 个子 agent,最后汇总

文档:Sub-agents https://docs.openclaw.ai/tools/subagents

#

方式 2:多个飞书 bot(多个 account)+ 多个 agent(你在群里“@谁谁上”)

这个更像“多个人在群里”,每个 bot 就是一个人格/专长。配置是:

  • channels.feishu.accounts 里加多个 bot 凭证
  • agents.list 里加多个 agent
  • bindingsaccountId → agentId 一一绑定

你在群里 @WriterBot / @CodingBot 就等于“召唤对应 agent”,这是最直观的“协作”。


你想要哪种“协作”?

  1. 一个 bot 统一对话 + 自动拉人干活 + 最后汇总(方式 1)
  2. 多个 bot 像群里多个同事一样,你 @谁谁来回答(方式 2)

你选一个,我就按那个给你最小可用配置(包括你现在已经有的 main/coding 怎么调整)。如果选方式 1,我还可以给你一份“协作触发模板”(比如前缀规则),让 main 稳定地把任务分发出去。

elder field
#

选择这个 2) 多个 bot 像群里多个同事一样,你 @谁谁来回答(方式 2)

cobalt fieldBOT
#

好,选方式 2 的话,配置思路就是:

每个飞书 bot = 一个 channels.feishu.accounts.<accountId> 账号
每个账号绑定到一个 agentId(独立 workspace / 人设 / 工具权限)
你在群里 @哪个 bot,就等于在“叫哪个同事出来回答”。


1)飞书侧:准备多个 bot(多个 App)

你已经有 1 个编程专家 bot 了;再建几个(比如 WriterBot、IdeaBot):

  • 每个 bot 都要:启用机器人能力、权限、WebSocket 长连接订阅 im.message.receive_v1、发布
  • 把这些 bot 全部拉进同一个群

2)OpenClaw:新增多个 Feishu accounts

#

~/.openclaw/openclaw.json 里,把 channels.feishu.accounts 扩展成多个(accountId 就是你自己起的 key,后面 bindings 要用同名):

{
  channels: {
    feishu: {
      enabled: true,
      groupPolicy: "open", // 测试阶段建议 open
      accounts: {
        coding: { appId: "cli_xxx", appSecret: "xxx", botName: "CodingBot" },
        writer: { appId: "cli_yyy", appSecret: "yyy", botName: "WriterBot" },
        idea:   { appId: "cli_zzz", appSecret: "zzz", botName: "IdeaBot" }
      }
    }
  }
}
#

3)OpenClaw:创建多个 agent(每个“同事”一个脑子)

openclaw agents add coding
openclaw agents add writer
openclaw agents add idea

4)OpenClaw:bindings 绑定账号 → agent

把每个飞书账号(bot)固定路由到对应 agent:

{
#
  agents: {
    list: [
      { id: "coding", default: true },
      { id: "writer" },
      { id: "idea" }
    ]
  },

  bindings: [
    { agentId: "coding", match: { channel: "feishu", accountId: "coding" } },
    { agentId: "writer", match: { channel: "feishu", accountId: "writer" } },
    { agentId: "idea",   match: { channel: "feishu", accountId: "idea" } }
  ]
}
#

改完重启:

openclaw gateway restart

验证路由:

openclaw agents list --bindings

5)容易忘的点:每个 agent 的模型凭证是独立的

你新建 writer/idea 后,如果它们不回消息/提示没 auth,通常是因为它们没有对应的 auth-profiles.json

最省事的做法是把 coding(或 main)那份 auth profiles 复制过去(不要共用 agentDir,只是复制文件):

  • 源文件位置一般是:~/.openclaw/agents/<agentId>/agent/auth-profiles.json
#

6)群里使用体验(默认行为)

  • 默认群里需要 @机器人 才会回复(每个 bot 都一样)
  • 所以同一个群里放多个 bot 很清爽:你 @WriterBot 就是写作同事出场;@CodingBot 就是编码同事出场

你打算加哪些“同事”(比如:writer / idea / reviewer / customer-support)?把你想要的 bot 列表发我,我给你一份对应的 accounts + agents + bindings 完整模板,你只要把每个 bot 的 appId/appSecret 填进去就行。

elder field
#

writer / idea / code /reviewer / customer-support

cobalt fieldBOT
#

好,这 5 个“同事”非常标准:writer / idea / code / reviewer / customer-support。下面给你一份可直接套用的模板(你只需要填每个飞书 App 的 appId/appSecret,然后重启网关)。

目标结构:5 个飞书 bot(5 个 accounts)→ 绑定到 5 个 agent(5 个 workspace)
在同一个群里:你 @哪个 bot,就由哪个“同事”回答。


Step 0:先把 5 个飞书 bot 都准备好

每个 bot 都需要:

  • WebSocket 长连接订阅 im.message.receive_v1
  • 发布应用
  • 拉进同一个群

(你已经会做一个了,其它 4 个照抄即可)


#

Step 1:创建 5 个 agent(建议用向导生成目录)

openclaw agents add code
openclaw agents add writer
openclaw agents add idea
openclaw agents add reviewer
openclaw agents add customer-support

Step 2:把 5 个飞书 bot 加进 channels.feishu.accounts

把下面这段合并进你的 ~/.openclaw/openclaw.json别泄露 appSecret):

{
#
  channels: {
    feishu: {
      enabled: true,
      groupPolicy: "open", // 测试阶段建议 open;后面要收紧再改 allowlist
      accounts: {
        code: {
          appId: "cli_CODE",
          appSecret: "SECRET_CODE",
          botName: "CodeBot"
        },
        writer: {
          appId: "cli_WRITER",
          appSecret: "SECRET_WRITER",
          botName: "WriterBot"
        },
#
        idea: {
          appId: "cli_IDEA",
          appSecret: "SECRET_IDEA",
          botName: "IdeaBot"
        },
        reviewer: {
          appId: "cli_REVIEW",
          appSecret: "SECRET_REVIEW",
          botName: "ReviewerBot"
        },
        "customer-support": {
          appId: "cli_CS",
          appSecret: "SECRET_CS",
          botName: "SupportBot"
        }
#
      }
    }
  }
}

Step 3:bindings:每个 accountId 固定路由到对应 agentId

{
  bindings: [
    { agentId: "code", match: { channel: "feishu", accountId: "code" } },
    { agentId: "writer", match: { channel: "feishu", accountId: "writer" } },
    { agentId: "idea", match: { channel: "feishu", accountId: "idea" } },
#
    { agentId: "reviewer", match: { channel: "feishu", accountId: "reviewer" } },
    { agentId: "customer-support", match: { channel: "feishu", accountId: "customer-support" } }
  ]
}

Step 4(强烈建议):给每个 agent 加最基本的工具边界

你可以先用最轻的限制(后面再收紧):

{
  agents: {
    list: [
#
      { id: "code", default: true }, // coding agent 一般权限最大

      { id: "writer", tools: { deny: ["exec", "process"] } },
      { id: "idea", tools: { deny: ["exec", "process"] } },

      // reviewer:只读审查(能 read,但不能 exec / 写文件)
      { id: "reviewer", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } },

      // customer-support:尽量别让它碰你的本地文件/命令(纯对话/查公开资料)
      { id: "customer-support", tools: { deny: ["group:runtime", "group:fs", "browser", "canvas", "nodes"] } }
    ]
  }
}

说明:customer-support 以后如果要联网查资料,你再按需加 web_fetch/web_search(以及沙箱网络配置)。你现在是自用测试,先把“别乱动本机”放第一位。

#

Step 5:重启网关 + 验证

openclaw gateway restart
openclaw agents list --bindings

一个容易忽略的大坑:每个 agent 的模型凭证默认是独立的

新 agent 如果不回/提示缺 auth,多半是它没有 provider auth。最省事的方式是把现有那份 auth profiles 复制到其它 agent(不要共享 agentDir,只复制文件)。


如果你愿意,把你当前 openclaw.json 里这三段贴出来(appSecret 打码):

  • channels.feishu.accounts
#
  • agents.list
  • bindings

我可以帮你检查:accountId/agentId 是否一一对应、有无拼写导致路由不到、以及哪些工具 deny 会不会过头。

elder field
#

openclaw gateway restart
Invalid config at /root/.openclaw/openclaw.json:\n- channels.bindings: unknown channel id: bindings

🦞 OpenClaw 2026.3.7 (42a1394) — I can't fix your code taste, but I can fix your build and your backlog.


◇ Config ───────────────────────────────────────────────────╮
│ │
│ Config invalid; doctor will run with best-effort config. │
│ │
├────────────────────────────────────────────────────────────╯

◇ Doctor changes ─────────────────────────────────────────────╮
│ │
│ Moved channels.feishu single-account top-level values into │
│ channels.feishu.accounts.default. │
│ │
├──────────────────────────────────────────────────────────────╯

◇ Doctor warnings ────────────────────────────────────────────────────────────────────────╮
│ │
│ - channels.feishu.accounts.default.groupPolicy is "allowlist" but groupAllowFrom (and │
│ allowFrom) is empty — all group messages will be silently dropped. Add sender IDs to │
│ channels.feishu.accounts.default.groupAllowFrom or │
│ channels.feishu.accounts.default.allowFrom, or set groupPolicy to "open". │

◇ Doctor ──────────────────────────────────────────────╮
│ │
│ Run "openclaw doctor --fix" to apply these changes. │

Config invalid
File: ~/.openclaw/openclaw.json
Problem:

  • channels.bindings: unknown channel id: bindings
    Run: openclaw doctor --fix
    Restarted systemd service: openclaw-gateway.service 哪里出了问题
cobalt fieldBOT
#

问题很明确:你把 bindings 写进了 channels 下面

OpenClaw 会把 channels 里的每个 key 当成“渠道 id”(discord/telegram/feishu…),所以它看到:

channels: {
  bindings: [...]
}

就会报:

channels.bindings: unknown channel id: bindings

因为 bindings 不是渠道,它必须是 顶层字段


#

你要怎么改(立刻修好)

把配置结构改成这样(bindingschannels 同级):

{
  channels: {
    feishu: {
      enabled: true,
      // 建议先 open,避免群消息被 allowlist 静默丢掉
      groupPolicy: "open",
      accounts: {
        // 你的多个 bot 账号都在这里
        // code: { appId, appSecret, botName },
        // writer: ...
      }
    }
#
  },

  agents: {
    list: [
      // { id: "code", default: true },
      // { id: "writer" },
    ]
  },

  bindings: [
    // { agentId: "code", match: { channel: "feishu", accountId: "code" } },
    // ...
  ]
}
#

然后按顺序跑

  1. 先修完 JSON 后,跑一次让 doctor 把迁移真正写回去:
openclaw doctor --fix
  1. 再重启:
openclaw gateway restart

额外提醒(你日志里的 warning)

Doctor 还在提醒:你当前 groupPolicyallowlist 但没填 groupAllowFrom/allowFrom,会导致群消息全部丢弃。测试阶段直接用 groupPolicy: "open" 最省事(等你要上线再收紧 allowlist)。

#

如果你愿意最快对上你的现有配置:把 openclaw.json 里从 channels:bindings: 这一段贴出来(appSecret 打码),我帮你把层级和多账号/多 agent 的写法一次性整理正确。

elder field
#

/root/.openclaw/openclaw1.json 看下我这个哪里错了

cobalt fieldBOT
#

我这边没法直接访问你 WSL 里的 /root/.openclaw/openclaw1.json 路径(只能看你贴出来的内容),所以需要你把配置内容发到线程里我才能帮你逐行找错。

注意别把密钥发出来appSecret / token 之类的要打码)。

你可以二选一:

方式 A(推荐):只贴关键三段(最够用)

openclaw1.json 里这三块贴出来就行(打码):

  • channels.feishu(尤其 groupPolicyaccounts
  • agents.list
  • bindings(确认是不是顶层,不在 channels 下面)

方式 B:整份配置自动打码后贴出来

在 WSL 里跑(会把 appSecret 打成 ***):

sed -E 's/(appSecret\\s*:\\s*\")[^\"]+\"/\\1***\"/g' /root/.openclaw/openclaw1.json | head -200
#

如果前 200 行不够,我再告诉你继续贴哪里。

另外确认一下:OpenClaw 实际读取的是 openclaw.json 还是 openclaw1.json
你跑一下这个,把里面显示的 config path 贴出来:

openclaw gateway status

你把上面任意一种结果贴出来后,我就能直接指出“哪一行/哪一级缩进”写错了(比如你之前那个 channels.bindings 问题)。

elder field
#

"channels": {
"feishu": {
"enabled": true,
"domain": "feishu",
"groupPolicy": "allowlist",
"accounts": {
"code": {
"appId": "cli_a",
"appSecret": "Z",
"botName": "CodeBot"
},
"reviewer": {
"appId": "cli_a9",
"appSecret": "Ml",
"botName": "ReviewerBot"
},
"writer": {
"appId": "cli_a9",
"appSecret": "ke",
"botName": "WriterBot"
},
"idea": {
"appId": "cli_a",
"appSecret": "i",
"botName": "IdeaBot"
},
"customer-support": {
"appId": "cli_a9",
"appSecret": "6C",
"botName": "SupportBot"
}
},
"appId": "cli_a93",
"appSecret": "zFlny"
},
"bindings": [
{
"agentId": "code",
"match": {
"channel": "feishu",
"accountId": "code"
}
},
{
"agentId": "writer",
"match": {
"channel": "feishu",
"accountId": "writer"
}
},
{
"agentId": "idea",
"match": {
"channel": "feishu",
"accountId": "idea"
}
},
{
"agentId": "reviewer",
" match": {
"channel": "feishu",
"accountId": "reviewer"
}
},
{
"agentId": "customer-support",
"match": {
"channel": "feishu",
"accountId": "customer-support"
}
}
]
},

cobalt fieldBOT
#

你这段里有 3 个硬错误 + 2 个会导致“收不到群消息”的配置问题


硬错误 1:你把 bindings 放进了 channels 下面

现在是:

"channels": {
  "feishu": { ... },
  "bindings": [ ... ]   // ❌ 这里不对
}

OpenClaw 会把 channels 里的每个 key 当成“渠道 id”,所以报:channels.bindings: unknown channel id: bindings

✅ 修法:把 bindings 挪到顶层,和 channels 同级:

#
{
  channels: { feishu: { ... } },
  bindings: [ ... ]
}

硬错误 2:你有个 key 写成了 " match"(前面多了空格)

这里:

{
  "agentId": "reviewer",
  " match": { ... }   // ❌ 多了一个前导空格
#
}

✅ 改成:

"match": { ... }

硬错误 3:你在 multi-account 配置里还留了旧的 feishu.appId/appSecret

你现在 channels.feishu 里既有 accounts: {...},又有顶层的:

#
"appId": "...",
"appSecret": "..."

这是单账号老格式,Doctor 也提示过会迁移到 accounts.default。你现在既然走多账号,就把这两个顶层字段删掉(避免被 doctor 搬来搬去、还可能干扰判断)。

✅ 结论:保留 accounts 就行,删掉 channels.feishu.appId/appSecret


会导致“群里不回”的问题 1:groupPolicy: "allowlist" 但你没填 allowlist

你现在:

"groupPolicy": "allowlist"
#

但没有 groupAllowFrom(也没有 allowFrom),所以 Doctor 说的没错:群消息会被静默丢掉

✅ 测试阶段最省事:改成

"groupPolicy": "open"

(等稳定后再改 allowlist 并填 groupAllowFrom: ["oc_xxx"]


会导致“多个 bot 其实不是多个”的问题 2:你复用了 appId

比如 codeidea 用了同一个 appId: cli_a(其它几个也重复了)。
一个 appId 就是一个飞书 App / 一个 bot 身份。如果你想 5 个“同事”都在群里有独立名字/头像/身份,appId 必须是 5 个不同的 App。


#

建议你直接改成这个结构(最小正确骨架)

(只展示结构,secret 自己填;并把 groupPolicy 先改 open)

{
  channels: {
    feishu: {
      enabled: true,
      domain: "feishu",
      groupPolicy: "open",
      accounts: {
        code: { appId: "cli_...", appSecret: "***", botName: "CodeBot" },
        reviewer: { appId: "cli_...", appSecret: "***", botName: "ReviewerBot" },
        writer: { appId: "cli_...", appSecret: "***", botName: "WriterBot" },
        idea: { appId: "cli_...", appSecret: "***", botName: "IdeaBot" },
        "customer-support": { appId: "cli_...", appSecret: "***", botName: "SupportBot" }
#
      }
    }
  },

  bindings: [
    { agentId: "code", match: { channel: "feishu", accountId: "code" } },
    { agentId: "writer", match: { channel: "feishu", accountId: "writer" } },
    { agentId: "idea", match: { channel: "feishu", accountId: "idea" } },
    { agentId: "reviewer", match: { channel: "feishu", accountId: "reviewer" } },
    { agentId: "customer-support", match: { channel: "feishu", accountId: "customer-support" } }
  ]
}

改完后跑:

#
openclaw doctor --fix
openclaw gateway restart

重要安全提醒

你刚刚把 真实的 appSecret 贴在 Discord 里了。建议你现在就去飞书开放平台把这些 App Secret 全部重置/轮换,然后更新本地配置(否则等于泄露了 bot 的钥匙)。

如果你把修改后的(已打码)完整 channels.feishu + 顶层 bindings 再贴一次,我可以继续帮你确认括号层级/逗号位置有没有问题。

elder field
#

有个问题,这几个都是agent的,那么main的"appId": "...",
"appSecret": "..."配置到哪里

cobalt fieldBOT
#

appId/appSecret 不是配在 agent(main/code/…)上的,而是配在 飞书渠道的 bot 账号(account) 上。

也就是说:

  • agentId(main / code / writer …):是“脑子/工作区/人设”
  • channels.feishu.accounts.<accountId>:是“飞书上的某一个 bot 身份”(每个都有自己的 appId/appSecret

所以你问的 “main 的 appId/appSecret 配到哪里?”取决于你想不想要一个“主 bot 身份”:

情况 A:你想要一个「MainBot」在群里当总入口

那你就再建一个飞书 App(MainBot),然后在配置里加一个 account,比如叫 main

{
  channels: {
    feishu: {
#
      accounts: {
        main: { appId: "cli_MAIN", appSecret: "***", botName: "MainBot" },
        code: { appId: "cli_CODE", appSecret: "***", botName: "CodeBot" }
      }
    }
  },
  bindings: [
    { agentId: "main", match: { channel: "feishu", accountId: "main" } },
    { agentId: "code", match: { channel: "feishu", accountId: "code" } }
  ]
}

情况 B:你不需要 MainBot(只有这 5 个同事 bot)

main agent 可以完全不配 appId/appSecret(因为它不对应任何飞书 bot 身份)。
只有当你把某个 accountId 绑定到 agentId: "main" 时,main 才会在飞书里“出现”。

#

如果你想,我建议你直接把现在的 “code bot” 作为 main(通用入口),然后把编码专家变成另一个 bot(或者反过来)。你更想让哪个 bot 当“主 bot”?我可以按你的偏好给你整理一份最终的 accounts + agents + bindings

elder field
#

openclaw gateway restart

🦞 OpenClaw 2026.3.7 (42a1394) — WhatsApp automation without the "please accept our new privacy policy".


◇ Doctor changes ─────────────────────────────────────────────╮
│ │
│ Moved channels.feishu single-account top-level values into │
│ channels.feishu.accounts.default. │

◇ Doctor warnings ────────────────────────────────────────────────────────────────────────╮
│ │
│ - channels.feishu.accounts.default.groupPolicy is "allowlist" but groupAllowFrom (and │
│ allowFrom) is empty — all group messages will be silently dropped. Add sender IDs to │
│ channels.feishu.accounts.default.groupAllowFrom or │
│ channels.feishu.accounts.default.allowFrom, or set groupPolicy to "open". │

│ │
│ Run "openclaw doctor --fix" to apply these changes. │

Restarted systemd service: openclaw-gateway.service 这是啥意思?

cobalt fieldBOT
#

这段输出的意思是:网关服务确实重启了,但 OpenClaw 在重启前顺手跑了一遍“Doctor 检查”,发现你的飞书配置里还有 老格式/不完整的地方,它给了你“准备自动修复”和“会导致群消息被丢弃”的提示。

逐条翻译一下:

1) Doctor changes: Moved ... into channels.feishu.accounts.default

你当前配置里还有一些 单账号旧写法(比如 channels.feishu.appId/appSecret/groupPolicy 这类顶层字段)。
Doctor 认为你应该用 多账号结构,所以准备把这些旧字段搬到:

channels.feishu.accounts.default

但注意:它还没真正写回配置文件

所以它才提示你:

Run openclaw doctor --fix to apply these changes.

✅ 你需要跑:

#
openclaw doctor --fix

2) Doctor warnings: groupPolicy is "allowlist" but ... is empty

这条更关键:你现在(至少 default 账号)是:

  • groupPolicy: "allowlist"
  • groupAllowFrom / allowFrom 是空的

结果就是:所有群消息都会被静默丢掉(群里 @机器人也没用)。

✅ 测试阶段最省事的修法:把 groupPolicy 改成 open(允许所有群,仍然默认要 @ 才回复):

把下面加到你的配置里(channel 级或 default account 级都行;你这个 warning 指的是 default account,所以优先改那边):

#
channels: {
  feishu: {
    accounts: {
      default: {
        groupPolicy: "open"
      }
    }
  }
}

3) Restarted systemd service: openclaw-gateway.service

这句只是说:systemd 里的 openclaw-gateway.service 已经被重启了(动作成功)。

#

建议你现在的最短修复路径

  1. 先跑:
openclaw doctor --fix
  1. 然后把 groupPolicy 改成 "open"(至少 default account 那个)

  2. 再重启:

openclaw gateway restart

如果你愿意,把你当前 channels.feishu 那段(打码 appSecret)贴一下,我可以告诉你应该把 groupPolicy 放在 channel 级还是 accounts.default 级,以及怎么避免每次都被 doctor 迁移。

cobalt fieldBOT
#

从你贴的日志看,问题不是路由/绑定,而是 “群聊需要提及(mention required)” 的门禁

message in group ... skipped (mention required)

这句话的含义是:这个 bot 收到了群消息,但它没有检测到“自己被 @”,所以按默认规则直接跳过,不回复。

你现在的现象(@单个 bot 会回;@所有 bot 都不回)通常是因为:

  • 在飞书里 一次消息里 @多个机器人 时,发给每个机器人的事件里,“mentions 元数据/格式”可能不会像单独 @那样标记(或插件目前只识别“单一@”场景)
  • 结果就是每个 bot 都认为“没被 @”,所以全部 skipped (mention required)

解决办法(按推荐程度)

方案 1(最简单、最稳定):一次只 @一个机器人

#

你要“多个同事都回答”,就发 5 条消息分别 @5 个 bot(目前最可靠)。

方案 2(让“@所有机器人”也能工作):关掉这个群的 requireMention

在配置里对这个群 oc_9973... 设置:

channels: {
  feishu: {
    groups: {
      oc_99733824abd7ed1dcf9a34816f9d76a1: { requireMention: false }
    }
  }
}

然后 openclaw gateway restart

#

注意:这样做的副作用是 不 @ 也会触发(你群里有 5 个 bot 时,可能会一起回,变吵)。如果你只自己用还好;要更“像同事”一点,建议你再给每个 bot 的人设加一条规则:只有看到前缀才回答(比如 writer: 才 writer 回)。

方案 3(最爽的“问所有同事一次”):加一个“Panel/Dispatcher Bot”

保留你现在的 5 个同事 bot 负责单点回答;再加一个总控 bot(main/panel),你只需要 @它一次,它在后台把问题分发给 writer/idea/code/reviewer/support,最后汇总成一条回复。(这个不依赖飞书多重@是否可靠。)


你更想要哪种体验?

  • A)我就接受“一次只@一个”
  • B)我希望不@也能触发,但用前缀控制谁回
  • C)我想要一个“问所有同事一次”的 Panel bot(推荐)

你选一个,我给你对应的最小配置改法。

elder field
#

我这么配置了多个agent,那么skills是单独的还是共享workspace中的

cobalt fieldBOT
#

skills 既不是“全都独立”也不是“全都共享”,而是两层结构:

1) 每个 agent 的 workspace 里可以有“专属 skills”

每个 agent 有自己的 workspace(你用 openclaw agents add <id> 建出来的那个目录)。
你在某个 agent 的 workspace 里放的:

  • <该 agent workspace>/skills/

只会影响这个 agent(相当于“这个同事的私有技能包”)。

2) 也有“全局共享 skills”

OpenClaw 还有一个共享技能目录,所有 agent 都能用:

  • ~/.openclaw/skills

所以你想做“所有同事都共用的一套技能”,就放这里;想让 writer/idea 各自有不同技能,就放各自 workspace 的 skills/ 里。

#

这点在 Multi-Agent 文档里也写了:skills per-agent(workspace 的 skills)+ shared skills(~/.openclaw/skills)。

实战建议

  • 通用能力(比如通用的格式化、通用查询)→ 放 ~/.openclaw/skills
  • 角色专用(比如 reviewer 专用审查流程、customer-support 专用话术/RAG)→ 放对应 agent 的 workspace skills/

如果你把某个 skill 的路径结构(你现在放在哪)贴一下,我可以告诉你应该搬到“共享”还是“专属”更合理。

elder field
#

非常感谢我配置好了,怎么设置安全一点。虽然没有使用沙箱,但是我也不希望被恶意命令冲垮我的机器环境。高危命令怎么禁止

cobalt fieldBOT
#

不启用 sandbox 的情况下,要“安全一点”主要靠 两道闸

  1. 谁能触发你 bot(渠道/群/提及/白名单)
  2. 触发后 bot 能调用哪些工具(尤其 exec / 写文件) —— 高危命令本质上都是通过 exec(或写文件)实现的

你问“高危命令怎么禁止”,最靠谱的答案是:不要做黑名单(禁 rm 禁 curl… 很难做全),而是做白名单(allowlist)

下面给你一套实用做法(从强到弱):


A. 先把“非必要 agent”的高危工具直接关掉(最有效)

你有 writer / idea / reviewer / customer-support 这几个,其实都可以默认禁掉运行命令能力:

{
#
  agents: {
    list: [
      { id: "writer", tools: { deny: ["exec", "process"] } },
      { id: "idea", tools: { deny: ["exec", "process"] } },

      // reviewer:只读审查(能 read,但不能 exec/写)
      { id: "reviewer", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } },

      // customer-support:完全不碰本机
      { id: "customer-support", tools: { deny: ["group:runtime", "group:fs", "browser", "canvas", "nodes"] } }
    ]
  }
}

这样就算有人发恶意 prompt,这几个 bot 根本没有“动你机器”的能力

#

B. 让文件工具只能动 workspace(防止写爆系统目录)

全局加一个(很建议):

{
  tools: {
    fs: { workspaceOnly: true }
  }
}

这样 read/write/edit/apply_patch 默认只能在 workspace 范围内活动,降低“误删/误改系统文件”的风险。


#

C. 对“code bot”用 exec 白名单/审批(阻止高危命令的关键)

你肯定希望 code bot 还能跑测试/构建,所以不可能简单 deny exec。这时要上 Exec approvals(白名单 + 可选人工确认)

思路是:默认 deny,只允许你明确允许的二进制(比如 /usr/bin/git/usr/bin/pnpm…)。不要 allowlist bash/sh/python/node 这种“解释器”,否则等于又放开任意执行了。

你可以先看看当前 approvals 配置:

openclaw approvals get --gateway

然后只给 code agent 加允许的可执行文件(例子):

#
openclaw approvals allowlist add --agent code "/usr/bin/git"
openclaw approvals allowlist add --agent code "/usr/bin/pnpm"
openclaw approvals allowlist add --agent code "/usr/bin/rg"

这样 bot 就算被诱导去执行 rm -rf /,也需要它能跑到相应的二进制/链式命令;在 allowlist 模式下会被拦掉。


D. 再加一道“入口安全”(可选,但推荐)

  • 群里保持 requireMention: true(默认就是)
  • groupPolicy 如果不是你一个人用,务必收紧 allowlist + groupAllowFrom(否则任何人都能触发)
  • 定期跑一次:
openclaw security audit --fix
#

(文档: https://docs.openclaw.ai/gateway/security


你现在最想保护的是哪一类风险?

  1. 防止删库/乱改文件(优先做 B + reviewer 禁写)
  2. 防止执行危险命令(优先做 A + C)
  3. 以后要给别人用 customer-support(优先做入口 allowlist + 给它禁 runtime/fs)

你把你 code bot 目前需要哪些命令(git/pnpm/pytest/docker 等)列一下,我可以按“尽量少的白名单”给你一份 approvals allowlist 建议清单。

#

那条 t!cket 链接是典型的 钓鱼/诈骗垃圾信息(用 http:////\\\\@... 这种方式混淆真实域名)。

  • 别点、别在浏览器里打开,也别复制到任何地方解析
  • 用 Discord 的 “Report to moderators / 举报给管理员” 功能把这条消息上报
  • 顺手 拉黑/屏蔽 发送者,避免继续刷屏

如果你是群里管理员:直接删消息 + 封禁账号会更干净。

elder field
#

这种要处理吗 openclaw security audit

🦞 OpenClaw 2026.3.7 (42a1394) — I can run local, remote, or purely on vibes—results may vary with DNS.


◇ Doctor changes ─────────────────────────────────────────────╮
│ │
│ Moved channels.feishu single-account top-level values into │
│ channels.feishu.accounts.default. │
│ │
├──────────────────────────────────────────────────────────────╯

◇ Doctor ──────────────────────────────────────────────╮
│ │
│ Run "openclaw doctor --fix" to apply these changes. │
│ │
├───────────────────────────────────────────────────────╯
OpenClaw security audit
Summary: 0 critical · 2 warn · 1 info
Run deeper: openclaw security audit --deep

WARN
channels.feishu.doc_owner_open_id Feishu doc create can grant requester permissions
channels.feishu tools include "doc"; feishu_doc action "create" can grant document access to the trusted requesting Feishu user.
Fix: Disable channels.feishu.tools.doc when not needed, and restrict tool access for untrusted prompts.
plugins.installs_unpinned_npm_specs Plugin installs include unpinned npm specs
Unpinned plugin install records:

  • feishu (@m1heng-clawd/feishu)
  • wecom-openclaw-plugin (@wecom/wecom-openclaw-plugin)
    Fix: Pin install specs to exact versions (for example, @scope/pkg@1.2.3) for higher supply-chain stability.

INFO
summary.attack_surface Attack surface summary
groups: open=0, allowlist=1
tools.elevated: enabled
hooks.webhooks: disabled
hooks.internal: enabled
browser control: enabled
trust model: personal assistant (one trusted operator boundary), not hostile multi-tenant on one shared gateway

cobalt fieldBOT
#

要处理,但按优先级来:你现在是 0 critical,说明“不会立刻炸”,不过这几个 warn 都是在提醒你将来容易踩坑的点

我按你这份输出逐条解释 + 给最短处理办法:


0) 先处理 Doctor changes(不处理也能跑,但会一直提示)

它说你配置里还有飞书的“单账号旧字段”,准备迁移到 channels.feishu.accounts.default

✅ 直接跑一次:

openclaw doctor --fix
openclaw gateway restart

#

1) WARN: channels.feishu.doc_owner_open_id ...

意思:你启用了飞书渠道的 doc 工具(创建飞书文档)。这个工具在 create 时可能给“请求者”授予文档权限,所以 audit 提醒你“这属于可扩权能力”。

如果你根本不需要 bot 帮你创建飞书文档,最安全就是关掉它:

openclaw.json 里加(或设为 false):

channels: {
  feishu: {
    tools: { doc: false }
  }
}

2) WARN: plugins.installs_unpinned_npm_specs

#

意思:你装的插件记录是“未 pin 的版本”(供应链稳定性差一点,未来更新可能带来不兼容/风险)。

✅ 两种处理方式:

  • 不用的插件:卸载(最干净)
    • openclaw plugins list 看清楚插件 id
    • 然后 openclaw plugins uninstall <id>
  • 要用的插件:重新安装并 pin 到具体版本
    • 形式类似:openclaw plugins install @scope/pkg@1.2.3 --pin

你这里列了:

  • feishu (@m1heng-clawd/feishu)(如果你已经用官方 @openclaw/feishu 跑通了,这个第三方建议卸掉)
  • wecom-openclaw-plugin (@wecom/wecom-openclaw-plugin)(不用就卸,用就 pin)

3) INFO 里两个我建议你也顺手看一眼

tools.elevated: enabled

#

如果你现在不打算让 bot 有“突破限制在宿主机随便跑命令”的能力,建议关掉(尤其你不想被恶意命令冲垮环境):

tools: {
  elevated: { enabled: false }
}

browser control: enabled

如果你不需要 browser 工具(尤其是 customer-support 这种 bot),建议在对应 agent 上 deny 掉 browser(你之前已经在做了)。


你要我给你一个“最小安全基线”吗?

你现在是多 bot 多 agent 的结构,我可以按你这 5 个 bot(writer/idea/code/reviewer/customer-support)给一份最小安全配置(哪些 agent 禁 exec、哪些 agent 限 workspaceOnly、哪些 agent 禁 browser 等)。

你把 openclaw plugins list(只要插件那几行)贴一下,我也可以顺手告诉你哪些插件该卸、哪些该 pin。

elder field
#

Invalid config at /root/.openclaw/openclaw.json:\n- tools.exec: Unrecognized keys: "allowlist", "blocklist", "require_approval"
[openclaw] Failed to start CLI: Error: Invalid config at /root/.openclaw/openclaw.json:

  • tools.exec: Unrecognized keys: "allowlist", "blocklist", "require_approval" 这几个是不支持吗{
    "tools": {
    "exec": {
    "allowlist": [
    "^git ",
    "^npm ",
    "^python ",
    "^ls ",
    "^cat ",
    "^echo ",
    "^mkdir ",
    "^cd "
    ],
    "blocklist": [
    "rm ",
    "dd ",
    "mkfs ",
    "format ",
    "curl .\| bash",
    "> /dev/",
    "sudo "
    ],
    "require_approval": ["rm", "chmod", "chown", "mv .
    ~", "curl"]
    }
    }
    }
cobalt fieldBOT
#

对,这 3 个字段 现在不支持,所以才会报:

tools.exec: Unrecognized keys: "allowlist", "blocklist", "require_approval"

你写的这种“按命令字符串做 regex allow/blocklist”的方案(^git rm curl | bash)在 OpenClaw 的 openclaw.json没有对应配置项


你现在要先做的:把这三段删掉,不然 OpenClaw 起不来

tools.exec.allowlist / blocklist / require_approval 整块从配置里移除,先恢复可启动。


OpenClaw 里“禁止高危命令”的正确做法(两层)

1) Tool policy:直接禁用/限制 exec 工具(最硬的闸)

对不需要跑命令的 agent(writer/idea/reviewer/support)直接 deny exec

#
agents: {
  list: [
    { id: "writer", tools: { deny: ["exec", "process"] } },
    { id: "idea", tools: { deny: ["exec", "process"] } },
    { id: "reviewer", tools: { deny: ["exec", "process"] } },
    { id: "customer-support", tools: { deny: ["group:runtime"] } }
  ]
}

2) Exec approvals:对“需要 exec 的 code agent”做二进制白名单(推荐)

OpenClaw 的 allowlist/审批是在 Exec approvals 里做的(不是 openclaw.json),而且它的白名单是“可执行文件路径”级别,不是命令文本 regex:

#

例如只允许 code agent 跑 git / pnpm / rg 这类“明确的二进制路径”:

openclaw approvals allowlist add --agent code "/usr/bin/git"
openclaw approvals allowlist add --agent code "/usr/bin/pnpm"
openclaw approvals allowlist add --agent code "/usr/bin/rg"

几点重要差异(也是你那套 regex 在这里行不通的原因):

  • cd 这种是 shell 内置命令,不是一个独立二进制文件,所以没法被“可执行路径 allowlist”表达
  • 允许 /usr/bin/cat 其实很危险(可以读任何文件),更推荐用 OpenClaw 的 read 工具 + tools.fs.workspaceOnly: true 来做文件读取边界
  • OpenClaw 更推荐 白名单,而不是“列一堆 rm/dd/mkfs 黑名单”(黑名单很难覆盖全)

如果你告诉我:你 code bot 实际需要哪些命令

比如:git, pnpm, node, pytest, docker
我可以帮你给一份“尽量小、尽量安全”的 approvals allowlist(以及哪些千万别放进 allowlist,比如 bash/sh/python/node 这类解释器放进去就等于开了任意执行)。

elder field
cobalt fieldBOT
#

支持,但要用 OpenClaw 的插件安装方式,不是直接填 GitHub URL。

这个仓库的 README 里写的安装方式是(从 npm 装):

openclaw plugins install @knostic/openclaw-shield --pin
openclaw gateway restart

也可以 clone 下来本地装(适合测试):

git clone https://github.com/knostic/openclaw-shield
cd openclaw-shield
openclaw plugins install ./
openclaw gateway restart
#

你需要注意的几点(别踩坑)

  1. 这是“加一层防护”,不是替代硬限制
    README 自己也写了:有些层(例如 before_tool_call 的硬拦截)在某些版本/发布物里可能没接好;L5 gate 也偏“策略性/建议性”(依赖模型遵守),所以仍然建议你保留你已经在做的:
  • tool policy(哪些 agent 禁 exec / 禁写)
  • exec approvals allowlist(真正硬白名单)
  1. 装完后最好把插件加入 plugins.allow(更安全)
    你可以先 openclaw plugins list 看它的插件 id,然后在 openclaw.json 里加:
plugins: { allow: ["feishu", "<shield插件id>"] }
  1. 配置入口
    插件一般通过 plugins.entries.<id>.config 配置(具体字段以它的 manifest/schema 为准;README 里提到 mode: audit|enforce、layers 等)。

如果你把 openclaw plugins list 的那一行(shield 的 id)贴一下,我可以告诉你 plugins.allowplugins.entries.<id>.config 应该写成什么样。

elder field
#

我一共有6个agent。一个全能的。编写代码、代码审核、运维、头脑风暴、写作的

cobalt fieldBOT
#

6 个 agent 这种拆法很合理,而且越早把“工具权限边界”按角色划清楚,后面越安全也越稳定。给你一个我会推荐的“默认安全分工”(不启用 sandbox 也能挺稳):

推荐角色分工(按权限从大到小)

  1. 全能/前台(general)
    • 目标:理解需求、给方案、路由到合适“同事”
    • 建议:默认 不允许 exec/写文件(避免被一句话诱导把机器干坏)
  2. 编写代码(code)
    • 需要:read + write/edit/apply_patch + exec/process(权限最大)
  3. 代码审核(reviewer)
    • 需要:read 为主(最好禁写、禁 exec),输出 review 建议即可
  4. 运维(ops)
    • 需要:exec/process,但最好配 Exec approvals allowlist(白名单命令),并且禁写文件
  5. 头脑风暴(idea)
    • 纯文本:禁 exec、禁写文件
  6. 写作(writer)
    • 纯文本:禁 exec、禁写文件(如果你要它写到本地文件,再单独开 write)
#

一个可直接用的 per-agent tools 模板(按你这些角色)

你把 agentId 对应改成你实际的即可:

{
  tools: {
    fs: { workspaceOnly: true },
    elevated: { enabled: false }
  },
  agents: {
    list: [
      { id: "general", tools: { deny: ["group:runtime", "group:fs", "browser", "canvas", "nodes"] } },

      { id: "code" }, // 权限最大:别给陌生人用

      { id: "reviewer", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } },
#

      { id: "ops", tools: { deny: ["write", "edit", "apply_patch"] } },

      { id: "idea", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } },
      { id: "writer", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } }
    ]
  }
}

关键点:deny 是硬闸。你运维/编码就算要 exec,也尽量只让对应 agent 具备;其它 agent 直接没有“动你机器”的能力。

运维(ops)那条建议再补一句

如果你真的担心“高危命令冲垮机器”,对 ops / code 这两个 agent,我强烈建议配 exec approvals allowlist(只允许你明确允许的二进制路径),这是最像“硬防火墙”的办法。


#

如果你把你 6 个 agent 的 id 列表贴一下(openclaw agents list --bindings 或直接贴 id),我可以把上面模板按你的实际 id 改成一份最终可粘贴的版本。

elder field
#

这是我的配置 "agents": {
"defaults": {
"model": {
"primary": "minimax-cn/MiniMax-M2.5"
},
"models": {
"minimax-cn/MiniMax-M2.5": {
"alias": "Minimax"
}
},
"workspace": "/root/.openclaw/workspace",
"compaction": {
"mode": "safeguard"
},
"maxConcurrent": 4,
"subagents": {
"maxConcurrent": 8
}
},
"list": [
{
"id": "main"
},
{
"id": "code",
"name": "code",
"workspace": "/root/.openclaw/workspace-code",
"agentDir": "/root/.openclaw/agents/code/agent"
},
{
"id": "writer",
"name": "writer",
"workspace": "/root/.openclaw/workspace-writer",
"agentDir": "/root/.openclaw/agents/writer/agent"
},
{
"id": "idea",
"name": "idea",
"workspace": "/root/.openclaw/workspace-idea",
"agentDir": "/root/.openclaw/agents/idea/agent"
},
{
"id": "reviewer",
"name": "reviewer",
"workspace": "/root/.openclaw/workspace-reviewer",
"agentDir": "/root/.openclaw/agents/reviewer/agent"
},
{
"id": "customer-support",
"name": "customer-support",
"workspace": "/root/.openclaw/workspace-customer-support",
"agentDir": "/root/.openclaw/agents/customer-support/agent"
},
{
"id": "ops",
"name": "ops",
"workspace": "/root/.openclaw/workspace-ops",
"agentDir": "/root/.openclaw/agents/ops/agent"
}
]
}

cobalt fieldBOT
#

你这套 agent 拆分已经很好了(main + 6 个专精)。接下来要“安全一点”(不启用 sandbox),我建议你做 两件事

  1. 全局把文件工具限制在各自 workspace(防止读/写到系统目录)
  2. 按 agent把高危工具(exec/写文件/浏览器/节点)分层关掉,只给 code/ops 留必要的

下面是按你这 7 个 agentId(你说 6 个,但列表里加上 main 一共 7 个)给的一份推荐模板,你可以直接合并进 openclaw.json


1) 全局:限制 FS + 关 elevated(强烈建议)

{
  tools: {
    fs: { workspaceOnly: true },
    elevated: { enabled: false }
  }
#
}

workspaceOnly: true 会让 read/write/edit/apply_patch 只在 workspace 范围内生效。你每个 agent 都有独立 workspace,这个隔离非常有用。


2) 按 agent 分层禁用高危工具(exec/写入/浏览器等)

把这些加到你的 agents.list[] 对应条目里(只展示 tools 部分):

{
  agents: {
    list: [
      // main:全能/前台 —— 默认别让它 exec、别让它写文件
#
      { id: "main", tools: { deny: ["group:runtime", "write", "edit", "apply_patch", "browser", "canvas", "nodes"] } },

      // code:需要最大权限(留空或按需 deny 一点点)
      { id: "code" },

      // writer / idea:纯文本,禁 exec + 禁写文件
      { id: "writer", tools: { deny: ["group:runtime", "write", "edit", "apply_patch"] } },
      { id: "idea", tools: { deny: ["group:runtime", "write", "edit", "apply_patch"] } },

      // reviewer:只读审查(能 read,但不能 exec/写)
      { id: "reviewer", tools: { deny: ["group:runtime", "write", "edit", "apply_patch"] } },

      // customer-support:尽量别碰本机(仍允许它读自己 workspace 里的FAQ/话术)
      { id: "customer-support", tools: { deny: ["group:runtime", "write", "edit", "apply_patch", "browser", "canvas", "nodes"] } },
#
      // ops:允许 exec,但禁写文件(配合 exec approvals 白名单更稳)
      { id: "ops", tools: { deny: ["write", "edit", "apply_patch"] } }
    ]
  }
}

3) 最关键的“防恶意命令”:给 code/ops 开 Exec approvals 白名单

因为你不启用 sandbox,真正能“冲垮机器”的基本都是 exec
最可靠的办法不是黑名单 rm/dd,而是 allowlist 二进制路径(Exec approvals)。

你先确认你 code/ops 实际需要跑哪些命令(git/pnpm/docker/pytest…),我可以帮你列一个“尽量小”的 allowlist。


#

如果你愿意,把你现在的顶层 toolsagents.list 这两段贴一下(打码 secret),我可以按你现有结构把上面改动“最小化合并”,避免 doctor 再帮你搬来搬去。

elder field
#

ops 用来运维系统部署与处理故障的,权限是不是有问题

cobalt fieldBOT
#

看你 ops 的定位(“系统部署 + 故障处理”),权限一定是最敏感的:它基本等价于“把你的机器交给模型去操作”。所以我会把它的权限设计成 够用,但尽量可控,而不是一上来全开。

你问“权限是不是有问题”,取决于你 ops 具体要做什么——我给你一个判断框架:


1) 如果 ops 主要是“查状态/看日志/跑诊断命令”

那我之前建议的策略是合理的:
允许 exec/process/read
禁止 write/edit/apply_patch(避免它随手改文件)

这样它能跑 systemctl/journalctl/docker logs/ps/top/df 等诊断,但不会直接改你的文件。


2) 如果 ops 需要“改部署文件/改配置/改脚本(在 repo 里)”

那你就需要给 ops 开写权限,但要把风险压在可控范围内:

#
  • 只在 ops 的 workspace 里改(配合你已经加的 tools.fs.workspaceOnly: true
  • 把 ops 的 workspace 指向你的部署仓库目录(而不是整个 /root)

✅ 做法:对 ops 去掉 deny 里的 write/edit/apply_patch(或只开你需要的那几个)。


3) 如果 ops 需要“改系统级文件 /etc、重启服务、改防火墙”

这就不是“权限有问题”,而是风险模型变了
在你当前是 root 用户 跑 OpenClaw 的情况下,ops 一旦能 exec,就几乎是“无限权限”。

这种场景我更建议你选一个更安全的落点:

最推荐的硬化(不启用 sandbox 也能明显变安全)

  • 别用 root 跑 OpenClaw:换普通用户运行,这样即使 ops 被注入,也默认没有权限改系统;需要提权时再走人工 sudo(而且可以不配免密 sudo)。
  • 给 ops 配 exec approvals allowlist:只允许你明确允许的二进制(例如 docker, systemctl, journalctl),不要允许 bash/sh/python/node 这种解释器。
#

(Exec approvals 是目前最接近“高危命令禁止”的硬闸)


给你一个我会推荐的 ops 最小权限配置(通用)

  • 允许 exec/process(它能运维)
  • 禁止 write/edit/apply_patch(它不随便改文件)
  • 然后用 approvals allowlist 控制它能跑哪些命令
{ id: "ops", tools: { deny: ["write", "edit", "apply_patch"] } }

你 ops 现在最常用的 10 个命令是哪些?(比如:docker, systemctl, journalctl, pm2, nginx, tail, grep…)
你列一下,我帮你把 approvals allowlist 规划成“够用但不放飞”的版本。

elder field
#

docker docker compose tail 这一类

cobalt fieldBOT
#

OK,这三个命令很好配 exec approvals allowlist,但我先提醒一句:docker 基本等价于“半个 root 权限”(尤其如果能访问 /var/run/docker.sock),所以只建议给 ops 这个 bot 开,并且确保只有你能触发它。


1) 先确认二进制真实路径(很重要)

在 WSL 里跑:

command -v docker
command -v docker-compose || true
command -v tail

常见结果是:

  • docker:/usr/bin/docker
  • docker-compose(老版):/usr/bin/docker-compose
  • tail:/usr/bin/tail
#

2) 把它们加入 ops agent 的 allowlist

把上一步输出的路径填进去(下面假设是 /usr/bin/...):

openclaw approvals allowlist add --agent ops "/usr/bin/docker"
openclaw approvals allowlist add --agent ops "/usr/bin/tail"

docker compose 要不要单独加?

  • 如果你用的是 docker compose ...(Compose v2 子命令):✅ 只 allowlist docker 就够了
  • 如果你用的是 docker-compose ...(老的独立二进制):再加一条:
    openclaw approvals allowlist add --agent ops "/usr/bin/docker-compose"
    
#

3) 确保 exec 真的在“allowlist 模式”跑

openclaw.json 里建议把 exec 默认设成 gateway + allowlist(这是“硬拦截”的关键):

tools: {
  exec: {
    host: "gateway",
    security: "allowlist",
    ask: "off" // 不走弹窗审批;allowlist 没命中就直接拒绝
  }
}

#

如果你愿意,把 command -v dockercommand -v tail 的输出贴一下,我可以帮你确认路径对不对(有些环境 docker 在 /snap/bin 或 /usr/local/bin)。

elder field
#

Log file: /tmp/openclaw/openclaw-2026-03-10.log
16:00:36 warn tools {"subsystem":"tools"} tools.profile (coding) allowlist contains unknown entries (apply_patch, memory_search, memory_get, cron, image). These entries won't match any tool unless the plugin is enabled.
16:02:01 warn tools {"subsystem":"tools"} tools.profile (coding) allowlist contains unknown entries (apply_patch, memory_search, memory_get, cron, image). These entries won't match any tool unless the plugin is enabled.
16:02:35 error Missing subcommand. Try: "openclaw browser status"
16:03:02 info browser/service {"subsystem":"browser/service"} Browser control service ready (profiles=2)
16:03:02 info profile: openclaw
enabled: true
running: false
cdpPort: 18800
cdpUrl: http://127.0.0.1:18800
browser: unknown
detectedBrowser: chrome
detectedPath: /usr/bin/google-chrome
profileColor: #FF4500
16:03:17 info browser/chrome {"subsystem":"browser/chrome"} 🦞 openclaw browser profile decorated (#FF4500)
16:03:32 error Error: Error: Failed to start Chrome CDP on port 18800 for profile "openclaw".
Hint: If running in a container or as root, try setting browser.noSandbox: true in config.
Chrome stderr:
[3094178:3094178:0310/000317.537227:ERROR:content/browser/zygote_host/zygote_host_impl_linux.cc:101] Running as root without --no-sandbox is
16:05:51 warn tools {"subsystem":"tools"} tools.profile (coding) allowlist contains unknown entries (apply_patch, memory_search, memory_get, cron, image). These entries won't match any tool unless the plugin is enabled.
我是wsl部署的,这个是什么原因

cobalt fieldBOT
#

这个报错跟 WSL 本身关系不大,核心原因是日志里这一句:

Running as root without --no-sandbox is …

也就是:你现在的 gateway/CLI 是 root 用户在跑,Chrome/Chromium 在 Linux 下默认不允许 root 直接启动(除非加 --no-sandbox)。

所以 OpenClaw 尝试启动 CDP 浏览器失败。


解决办法(按推荐顺序)

方案 1(推荐):别用 root 跑 OpenClaw

用普通用户跑 gateway(最安全、最省后续坑)。
你之前很多路径都是 /root/.openclaw/...,说明一直是 root 在跑,这个本身也会放大“exec/ops”的风险。

方案 2(快速但没那么安全):给浏览器加 noSandbox

#

~/.openclaw/openclaw.json 里加:

{
  browser: {
    enabled: true,
    noSandbox: true
  }
}

然后:

openclaw gateway restart

这会给 Chrome 追加 --no-sandbox / --disable-setuid-sandbox,能启动起来,但浏览器隔离会变弱(只建议你自用测试环境)。

#

方案 3:你根本不需要 browser 工具

那最简单:直接关掉浏览器控制,避免它启动:

{ browser: { enabled: false } }

另外那几条 warn(coding profile unknown entries)

tools.profile (coding) allowlist contains unknown entries (apply_patch, memory_search, ...)警告:你的 tools profile 里写了一些工具名,但对应插件/工具没启用,所以不会生效。先不影响你这次 Chrome 启动问题。


你现在更倾向哪种?

  • 想长期稳定安全:我建议你迁移到普通用户跑(方案 1)
  • 先把 browser 跑起来:直接加 browser.noSandbox: true(方案 2)
#

如果你贴一下 whoamiopenclaw gateway status,我可以告诉你当前服务到底是哪个用户在跑,以及怎么最小改动迁移。

elder field
#

那直接创建一个非root用户把,用什么命令

cobalt fieldBOT
#

在 WSL(Ubuntu/Debian)里创建一个非 root 用户,最常用就是这几条:

# 你现在是 root 的话直接跑:
adduser claw

# 让这个用户能 sudo(可选,但一般需要)
usermod -aG sudo claw

# 如果你要让这个用户直接用 docker(可选)
usermod -aG docker claw

然后切换到新用户:

su - claw
#

让组权限生效(尤其是 docker 组),通常需要重新登录一次;最简单就是退出 susu - claw,或者重开 WSL。

(可选)让 WSL 默认用这个用户登录

编辑 /etc/wsl.conf

[user]
default=claw

然后在 Windows 里执行:

wsl --shutdown

再重新打开 WSL 就会默认进 claw 用户。

#

你现在用的发行版是 Ubuntu 吗?如果不是(比如 Alpine/Arch),创建用户命令会略有不同。

elder field
#

我发现家配置了权限,让打开网页分析的能力都没有了,工具不会使用了

cobalt fieldBOT
#

这基本就是你把工具权限收紧收过头了导致的(不是 bug)。OpenClaw 一旦被 tool policy 限制,模型就算“想用工具”,也会被系统直接拦住,所以看起来像“不会用工具/不会打开网页”。

先确认两个点:

  1. 你是 @哪个 bot 发现“打不开网页”?(writer/idea/reviewer/support 这些如果你按安全建议禁了 browser/web_fetch,那它们就本来不会用网页工具)
  2. 你说的“打开网页分析”是指:
    • browser(真正控制浏览器)
    • 还是 web_fetch/web_search(抓网页内容/搜索,不需要启动 Chrome)

最常见原因(你很可能踩了其中一个)

A) 你给某个 agent 配了 tools.allow,但没把 web 工具加进去

规则是:allow 非空 = 只允许 allow 里的工具,其它一律禁用。
所以如果你只 allow 了 read 之类,web_fetch/browser 就全没了。

B) 你在 agent 的 tools.deny 里禁了 browser / web_fetch / web_search

#

这会直接让“网页分析”能力消失(这是预期行为)。

C) 你在 WSL 里还是 root 跑 gateway,Chrome 起不来

这种情况下 browser 工具会失败(但 web_fetch 通常还能用)。你之前日志里就出现过 root + Chrome sandbox 的问题。


推荐的“安全但还能网页分析”的分工(实用)

  • writer / idea / reviewer / customer-support:继续禁 exec,但可以允许 web_fetch/web_search(它们只是拉网页文本,不执行命令)
  • code / ops:需要 exec 的,另走 exec approvals allowlist

例如(只用 deny,不用 allow,避免误伤):

{ id: "writer", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } }
// 不要 deny browser/web_fetch/web_search,就还能做网页分析
#

你把下面两段贴一下(打码即可),我就能直接指出是哪一条把 web 工具禁掉了:

  1. 顶层 tools: { ... }(如果有)
  2. 你“打不开网页”的那个 agent 的配置段(比如 agents.list 里对应的 writermain 那一段)

另外告诉我:你是想用 browser 还是只要 web_fetch/web_search?我会给你最小改动方案。

elder field
#

22:48:06 info gateway/channels/feishu {"subsystem":"gateway/channels/feishu"} feishu[main]: dispatching to agent (session=agent:main:feishu:direct:ou_b04c96e4c8d8f3a7d65cd8c9525f57d2)
22:48:06 warn tools {"subsystem":"tools"} tools.profile (coding) allowlist contains unknown entries (apply_patch, memory_search, memory_get, cron, image). These entries won't match any tool unless the plugin is enabled.
22:48:06 warn tools {"subsystem":"tools"} agents.main.tools.allow allowlist contains unknown entries (web_search_with_snippets, browse_page, x_keyword_search, x_semantic_search, x_user_search, x_thread_fetch, conversation_search, search_images, view_image, view_x_video). These entries won't match any tool unless the plugin is enabled.

22:48:11 info gateway/channels/feishu {"subsystem":"gateway/channels/feishu"} feishu[main]: dispatch complete (queuedFinal=false, replies=0)
22:48:25 info gateway/channels/feishu {"subsystem":"gateway/channels/feishu"} feishu: skipping duplicate message om_x100b55c0ac94b534c269c0445b00475 为啥

cobalt fieldBOT
#

这两条 warn 基本把原因说出来了:你现在 allow 了一堆“并不存在的工具名”,结果等于把真正的工具都给封死了。

1) 这条最关键

agents.main.tools.allow allowlist contains unknown entries (...)

在 OpenClaw 里规则是:

  • tools.allow / agents.<id>.tools.allow 只要是非空,就会进入“白名单模式”
  • 白名单里没匹配到的工具 = 全部不可用
  • 你列的这些(browse_page, web_search_with_snippets, x_*, search_images…)不是 OpenClaw 内置工具名,也没有对应插件启用,所以全部是 unknown
  • 于是 main 这个 agent 实际上就变成:几乎没工具可用(你想要的网页分析自然就没了)

✅ 修法(推荐最简单的):

  • agents.main.tools.allow 这一整段删掉(或设成空数组 []
  • agents.main.tools.deny 做限制(deny exec / 写文件之类),不要用 allow
#

比如:

{ id: "main", tools: { deny: ["exec", "process", "write", "edit", "apply_patch"] } }

这样网页工具(web_fetch/web_search/browser)会恢复可用。


2) 这条 warning 可以先忽略

tools.profile (coding) allowlist contains unknown entries (apply_patch, memory_search, ...)

这是说你的 coding profile 里也包含一些当前没启用/不可用的工具名(warning 级别,不一定致命)。优先先把 agents.main.tools.allow 修掉。


#

3) 为什么 “replies=0”

dispatch complete ... replies=0

通常就是 agent 这次运行没有产出可发送的回复(很常见的原因就是:工具/策略配置导致它卡在“想用工具但工具不可用”的状态,最后没有正常回复)。


4) “skipping duplicate message …” 不用管

飞书会有重复事件投递,adapter 做去重而已。


你现在做两步就能验证:

  1. 删掉 agents.main.tools.allow(或清空)
  2. openclaw gateway restart
#

然后用 main bot 再发一句“帮我分析这个网页:<url>”(或 /web_fetch 类需求),看日志里还会不会出现 unknown allowlist 的 warn。

elder field
#

1、怎么配置多个模型。2、创建多个agent,但是需要指定一个目录作为共享。

cobalt fieldBOT
#

1) 多个模型怎么配?

OpenClaw 里模型配置分两层:

  • 默认模型选择 + 兜底(fallbacks)agents.defaults.model.primary + agents.defaults.model.fallbacks
  • 模型目录/白名单 + 别名(alias)agents.defaults.models

    只要你设置了 agents.defaults.models,它就同时是 /model 可切换的 allowlist(不在里面的模型选不了)。

示例(把你的 provider/model 换成你自己的):

{
  agents: {
    defaults: {
      model: {
        primary: "providerA/model1",
#
        fallbacks: ["providerB/model2", "providerC/model3"]
      },
      models: {
        "providerA/model1": { alias: "Fast" },
        "providerB/model2": { alias: "Smart" },
        "providerC/model3": { alias: "Cheap" }
      }
    },

    // 每个 agent 也可以覆盖默认模型(按角色配不同模型)
    list: [
      { id: "code", model: { primary: "providerA/model1" } },
      { id: "writer", model: { primary: "providerB/model2" } }
    ]
  }
#
}

常用命令:


2) 多个 agent 但想“共享一个目录”怎么弄?

这里要先明确你说的“共享”是哪种:

A) 共享技能(skills)——官方就支持“共享目录”

  • 共享 skills~/.openclaw/skills(所有 agent 都能用)
  • 每个 agent 私有 skills<agent workspace>/skills/
#

(你之前问 skills,我给的就是这一套)

B) 共享文件/知识库/项目目录(让 file 工具能读到同一套文件)

OpenClaw 没有一个单独的“sharedWorkspaceDir”开关,本质上你有两种现实选择:

方案 1(最简单):所有 agent 的 workspace 都指向同一个目录

  • 直接共享文件、共享上下文(但隔离性最弱)

方案 2(更推荐):用“一个共同根目录 + 子目录”
比如你建一个根目录:

/data/openclaw/
  shared/             # 公共资料
  code/               # code agent 工作区
  writer/
#
  ops/

然后:

  • 要么把每个 agent workspace 都设成 /data/openclaw(它们都能读 shared,但也能互相看到彼此子目录)
  • 要么保持每个 agent workspace 各自独立,但你就需要:
    • 不启用 tools.fs.workspaceOnly(风险更高),或
    • 启用 sandbox,用 bind mount 把 /data/openclaw/shared 挂进每个 sandbox(最干净的隔离方案)

参考:


#

你说的“共享目录”更像哪种?

  1. 共享一套 skills
  2. 共享一套文件(比如共享一个知识库/项目 repo 给多个 agent read)
  3. 共享文件但还要隔离(想让只有 shared 可见、其它互不见)

你选一个,我给你对应的最小配置模板(按你现在的 /root/.openclaw/workspace-* 结构来改)。

elder field
#

我不会配置多模型。第一次部署使用了minimax。现在想添加一个kimi2.5。让不同的agent来调用

cobalt fieldBOT
#

你现在卡住的点主要有两个:

  1. Kimi 2.5 的“模型引用/Provider”要写对
  2. 把它加进 agents.defaults.models(否则 /model 和会话选择会被 allowlist 拦住),然后给某些 agent 覆盖默认模型

先确认:你要的是哪种 “Kimi 2.5”?

OpenClaw 里常见有两条路(文档明确区分):

  • Moonshot Kimi API(通用)moonshot/kimi-k2.5(用 MOONSHOT_API_KEY
    文档:https://docs.openclaw.ai/providers/moonshot
  • Kimi Coding(偏 coding)kimi-coding/k2p5(用 KIMI_API_KEY
    (同一页也有)

你说“第一次部署用了 minimax,现在想加 kimi2.5 给不同 agent 调用”,我猜你要的是 Moonshot 那条:moonshot/kimi-k2.5

#

配置方法(最稳:按官方 moonshot 文档来)

1) 配 Moonshot 的 key(不要在 Discord 里贴)

~/.openclaw/openclaw.json 里加(或用 onboard 向导写入也行):

{
  env: { MOONSHOT_API_KEY: "sk-..." }
}

2) 把 Kimi 加进模型目录/白名单(models catalog)

在你现有的:

agents.defaults.models

#

里加入一条(alias 随便起):

{
  agents: {
    defaults: {
      models: {
        "minimax-cn/MiniMax-M2.5": { alias: "Minimax" },
        "moonshot/kimi-k2.5": { alias: "Kimi2.5" }
      }
    }
  }
}

3) 给不同 agent 指定不同默认模型

在对应 agent 下面加 model.primary 覆盖即可:

#
{
  agents: {
    list: [
      { id: "writer", model: { primary: "moonshot/kimi-k2.5" } },
      { id: "idea", model: { primary: "moonshot/kimi-k2.5" } },

      // code/reviewer/ops 你想继续用 minimax 就不用写;或者也能写成 minimax
      { id: "code", model: { primary: "minimax-cn/MiniMax-M2.5" } }
    ]
  }
}

4) 验证

#
openclaw models status

最容易忽略的坑

  • 只要你设置了 agents.defaults.models,它就是白名单:没加进去的模型会出现 “Model … is not allowed” 或者表现为“不回复/不切换”。
  • Moonshot Kimi(moonshot/...)和 Kimi Coding(kimi-coding/...不是同一个 provider,key 也不通用。

你想让哪些 agent 用 Kimi 2.5?(比如 writer/idea 用 Kimi,code/ops 继续 minimax?)
你把你的目标分配表发我,我给你一段“可直接粘贴”的 agents.defaults.models + agents.list[].model 合并版(不会动你其它配置)。

elder field
#

我又回到了创建agent,和绑定agent的难题了。怎么创建的。

cobalt fieldBOT
#

创建 agent + 绑定 agent,最省心的做法是用 CLI 向导命令,别手写 bindings(手写最容易犯你之前那种 channels.bindings 的错)。

文档在这:https://docs.openclaw.ai/cli/agents


0)前提:Feishu 账号(bot)先配置好

也就是你的 openclaw.json 里已经有类似:

channels: {
  feishu: {
    accounts: {
      writer: { appId: "...", appSecret: "...", botName: "WriterBot" },
      // ...
    }
#
  }
}

这里的 writer 就是后面要用的 accountId


1)创建 agent(会生成 workspace + agentDir + 写入配置)

例如创建 writer

openclaw agents add writer --workspace ~/.openclaw/workspace-writer

其它同理:

#
openclaw agents add idea --workspace ~/.openclaw/workspace-idea
openclaw agents add reviewer --workspace ~/.openclaw/workspace-reviewer
openclaw agents add ops --workspace ~/.openclaw/workspace-ops

查看是否创建成功:

openclaw agents list

2)绑定:把某个 Feishu bot(accountId) 的消息路由到某个 agentId

feishu:writer 绑定到 writer agent:

#
openclaw agents bind --agent writer --bind feishu:writer

其它同理:

openclaw agents bind --agent idea --bind feishu:idea
openclaw agents bind --agent reviewer --bind feishu:reviewer
openclaw agents bind --agent ops --bind feishu:ops

查看当前所有绑定:

openclaw agents bindings
# 或只看某个 agent:
openclaw agents bindings --agent writer
#

3)重启网关(建议做一次,少玄学)

openclaw gateway restart

如果你把你现在的 Feishu accountId 列表(code/writer/idea/...)和你想绑定到的 agentId 发我,我可以给你一份“一条条可直接复制粘贴的命令清单”。

elder field
#

新的问题,我配置了coder 、reviews 并且是沙箱运行。怎么配置git仓库地址。

cobalt fieldBOT
#

OpenClaw 里没有一个专门的“git 仓库地址”配置项(不会像 CI 一样填个 repo URL 就自动工作)。你要做的是:让 sandbox 里的工具能看到你的仓库目录,然后在那个目录里 git clone/git pull/编辑。

你现在已经是 coder / reviews 都在沙箱里跑,常用有两种做法:


方案 A(推荐):宿主机已有 repo → bind mount 进 sandbox(coder 可写、review 只读)

1) 确认你宿主机 repo 的路径

例如:/home/you/Projects/myrepo

2) 给 agent 的 sandbox 加 bind(挂到容器里)

关键点:如果你开了 tools.fs.workspaceOnly: true,最好把 repo 挂到 workspace 里面(比如 /workspace/repo),这样 read/write 工具能访问。

示意(写到对应 agent 的 sandbox 配置里):

#
{
  agents: {
    list: [
      {
        id: "coder",
        sandbox: {
          mode: "all",
          scope: "agent",
          workspaceAccess: "rw",
          docker: {
            binds: ["/home/you/Projects/myrepo:/workspace/repo:rw"]
          }
        }
      },
      {
#
        id: "reviews",
        sandbox: {
          mode: "all",
          scope: "agent",
          workspaceAccess: "rw",
          docker: {
            binds: ["/home/you/Projects/myrepo:/workspace/repo:ro"]
          }
        }
      }
    ]
  }
}

然后在对话里让 coder 在 /workspace/repo 里做事就行。

#

文档(bind mounts / workspaceAccess):https://docs.openclaw.ai/gateway/sandboxing


方案 B:只有远程 repo URL → 让 sandbox 自己 clone

前提:

  • sandbox 镜像里要有 git
  • sandbox 要能出网(默认 docker.networknone,会导致 clone 失败)

然后让 coder 在沙箱里跑:

git clone <你的repo-url> /workspace/repo

(如果你需要我给你一个“最小能 clone 的 sandbox 配置”,你贴一下你现在 sandbox 的 docker.network / 镜像名。)


#

你现在先回答我一个问题,我就能给你最精确的配置

你希望操作的是哪种情况?

  1. 我在宿主机已经有 repo 路径(只需要挂进去)
  2. 我只有远程 URL(需要在沙箱里 clone)

如果是 1),把宿主机 repo 的绝对路径发我(不用包含敏感信息),我就按你现有的 coder/reviews agentId 给你一段可直接粘贴的 binds 配置(coder rw、reviews ro)。

elder field
#

1、我在共享目录已经下载了代码。那种配置更安全一些呢

#

⚠️ Agent failed before reply: Sandbox security: bind mount "/data/shared:/workspace/repo:rw" targets reserved container path "/workspace" (resolved target: "/workspace/repo"). This can shadow OpenClaw sandbox mounts. Use a dangerous override only when you fully trust this runtime.
Logs: openclaw logs --follow 为啥报错

#

:true,"requestedModelMatched":true,"fallbackConfigured":true} model fallback decision
14:32:15 warn [model-fallback/decision] model fallback decision: decision=candidate_failed requested=moonshot/kimi-k2.5 candidate=moonshot/kimi-k2.5 reason=unknown next=minimax/MiniMax-M2.5
14:32:15 error diagnostic {"subsystem":"diagnostic"} lane task error: lane=main durationMs=54 error="Error: Sandbox security: bind mount "/data/shared:/workspace/repo:rw" targets reserved container path "/workspace" (resolved target: "/workspace/repo"). This can shadow OpenClaw sandbox mounts. Use a dangerous override only when you fully trust this runtime."
14:32:15 error [diagnostic] lane task error: lane=main durationMs=54 error="Error: Sandbox security: bind mount "/data/shared:/workspace/repo:rw" targets reserved container path "/workspace" (resolved target: "/workspace/repo"). This can shadow OpenClaw sandbox mounts. Use a dangerous override only when you fully trust this runtime."

cobalt fieldBOT
#

400 Item 'rs_06c39b0fea20e9a80069b814b74dc8819aa147fa5839b35b4f' of type 'reasoning' was provided without its required following item.