#Exec Allowlist Not Working
1 messages · Page 1 of 1 (latest)
That config snippet is a bit of a trap: safeBins is not “the list of allowed commands”.
What’s going on:
-
safeBins= exceptions, not an allowlist
tools.exec.safeBinsis a list of stdin-only binaries that are allowed to run in allowlist mode without being in the allowlist (and they can’t take file/path args). It’s meant for things likejq,grep, etc.
Docs: https://docs.openclaw.ai/tools/exec-approvals#safe-bins-stdin-only -
The actual exec allowlist lives in exec-approvals, not in
tools.execconfig
The allowlisted binaries/patterns are stored in:~/.openclaw/exec-approvals.json(or edited via Control UI → Nodes → Exec approvals).
Docs: https://docs.openclaw.ai/tools/exec-approvals#allowlist-per-agent -
Allowlist/approvals only apply to host exec (
host=gatewayorhost=node)
By defaultexecruns withhost=sandbox. If you’re not actually runninghost=gateway/node, you won’t be hitting the approvals/allowlist gate you think you configured.
Docs: https://docs.openclaw.ai/tools/exec (seehost+ the “Important: sandboxing is off by default…” note)
What to do if you want “only cat is allowed” on the real machine:
-
Set exec to run on the host:
tools: { exec: { host: "gateway", security: "allowlist" } }(or in chat:
/exec host=gateway security=allowlist) -
Then add an allowlist entry in Exec approvals for the resolved binary path (basename-only entries are ignored), e.g.
/usr/bin/cat(Linux) or whereverwhich catpoints.
If you want it super strict, setsafeBins: []so only explicit allowlist entries work.
Debug tip: in the chat, run /exec to see the current session’s effective host/security/ask (session overrides can surprise you).
Thanks for the help — I managed to fix the issue based on your suggestion.
However, now every time a command that is not in the allowlist is triggered, it pops up an authorization message.
Is there a way to disable this prompt?
Appreciate your help!
Yep — that popup is controlled by the ask setting.
Right now you’re effectively in:
security: "allowlist"(block anything not allowlisted)ask: "on-miss"(…and prompt whenever it’s not allowlisted)
To disable the prompt and just have non-allowlisted commands get denied automatically, set:
Option A) Per-session (quick test)
In chat:
/exec ask=off
Option B) In config (persistent)
{
tools: {
exec: {
ask: "off",
security: "allowlist",
host: "gateway" // or "node" if that’s what you’re using
}
}
}
Option C) In Exec Approvals (the thing that’s actually popping up)
Control UI → Nodes → Exec approvals → set Ask = off (either Defaults or the specific agent).
(Or edit ~/.openclaw/exec-approvals.json and set defaults.ask / agents.main.ask to "off".)
Docs:
With ask=off + security=allowlist, anything not allowlisted will just fail with an “exec denied” style error — no authorization prompt.
Hi, I set ask=off, but the authorization prompt still appears.
The popup message even shows the ask mode as on-miss.
Why isn’t the setting taking effect?
That’s expected given how ask is resolved: you can’t “turn prompts down” from the tool call / /exec if something stricter is configured underneath. OpenClaw takes the more strict ask mode.
Two common reasons you still see ask=on-miss in the popup:
1) You changed /exec ask=off, but your configured defaults are still on-miss
Internally it does ask = max(configuredAsk, requestedAsk) — so if the Gateway (or node) is configured as on-miss, requesting off won’t reduce it.
Fix: set ask: "off" in the config that the running Gateway service is actually using.
Quick check:
openclaw gateway status
If it shows Config (cli) and Config (service) pointing to different configs, you probably edited the wrong one.
2) Exec approvals on the execution host still have ask: "on-miss" (this overrides)
Prompts usually come from exec approvals (~/.openclaw/exec-approvals.json) on the machine that’s executing:
- if
host=gateway→ approvals file on the gateway host - if
host=node→ approvals file on that node (macOS app / headless node host)
Fix it in Control UI → Nodes → Exec approvals (make sure you’re editing the right target: Gateway vs the specific Node, and the right agent), set Ask = off there.
Docs: https://docs.openclaw.ai/tools/exec-approvals#ask-execask
If you paste the output of:
/exec(so we can see your currenthost/security/ask)openclaw gateway status(just the Config lines)
…I can tell you exactly which layer is still forcing on-miss.
this is exec-approvals.json
{
"version": 1,
"defaults": {
"security": "allowlist",
"ask": "off"
}
}
That exec-approvals.json is fine — the reason you still see prompts (and it says ask=on-miss) is that ask is “clamped” to the stricter value.
In other words, OpenClaw effectively does:
effectiveAsk = max(tools.exec.ask, exec-approvals.ask, /exec ask=...)
…and the default for tools.exec.ask is "on-miss".
So even if approvals say "off", if your Gateway config still has tools.exec.ask unset (=> defaults to on-miss), the prompt will keep happening.
Fix
Set this in your actual Gateway config (and make sure you’re editing the config the service is using):
{
tools: {
exec: {
host: "gateway", // or "node"
security: "allowlist",
ask: "off"
}
}
}
If you have per-agent overrides, also check:
agents.list[].tools.exec.ask
Verify what the Gateway thinks
Run:
openclaw config get tools.exec.ask
openclaw gateway status
gateway status will also tell you if Config (service) is pointing at a different file than what you edited (super common).
If you paste just those two outputs (redact tokens), I can point to the exact layer still forcing on-miss.
You were right — it was caused by tools.exec.ask being set to on-miss.
Thanks for helping me resolve all the issues.
By the way, are you an AI or a mix of AI and human?
I’m fully AI — no human-in-the-loop on my replies here.
Sometimes I’ll suggest commands or checks that you run (or that a maintainer/community member confirms), but the writing/help you’re getting from me is automated.
Hi, I have a few questions about agent configuration and permissions:
- If I set the agent’s skill level to minimal, will it affect the agent’s behavior or capabilities in any significant way?
- During execution, can the agent modify files such as
AGENTS.md,SOUL.md,TOOLS.md,BOOTSTRAP.md,IDENTITY.md, orUSER.md? - If I remove the file write permission from the skill, will the agent still be able to write to
memory.md? - How can I make the agent automatically load a specific skill on startup?
- How can I restrict the agent so it only reads its own workspace and cannot be tricked or authorized into accessing other directories?
Thanks!
Here are clear answers to each (and the exact knobs involved):
- “minimal” skill level — what does it change?
There are two different “minimal” concepts people mix up:
- Tool profile =
minimal(tools.profile: "minimal"oragents.list[].tools.profile) → major capability change: it effectively gives the agent onlysession_status(noread/write/edit/exec/browser/...). It can still chat, but it can’t do actions.
Docs: https://docs.openclaw.ai/tools#tool-profiles-base-allowlist - Thinking level =
minimal(/think minimal) → only changes reasoning budget/style for supported models, not permissions.
Docs: https://docs.openclaw.ai/tools/thinking
-
Can the agent modify
AGENTS.md,SOUL.md,TOOLS.md,BOOTSTRAP.md,IDENTITY.md,USER.md?
Yes if it has file tools (write/edit/apply_patch) and it’s running with workspace write access (not sandboxed, or sandbox withworkspaceAccess: "rw"). Those files are just normal files in the workspace.
To prevent changes: denywrite/edit/apply_patch, or sandbox withworkspaceAccess: "ro"/"none".
Docs (bootstrap injection): https://docs.openclaw.ai/concepts/system-prompt#workspace-bootstrap-injection
Docs (sandbox workspace access): https://docs.openclaw.ai/gateway/sandboxing#workspace-access -
If I remove file-write permission, can it still write
memory.md?
No.memory.md/MEMORY.mdare still just files. If you denywrite/edit(and also denyexecso it can’t modify via shell), then it can’t update memory files.
Also: memory_search / memory_get are read-only tools; there is no separate “memory write” tool.
Docs: https://docs.openclaw.ai/concepts/memory (see the “Tools” section)
- How to make the agent automatically load a specific skill on startup?
There isn’t a “skills autoload at startup” config knob. Skills are meant to be loaded on-demand when relevant.
Practical workarounds:
- Put the important instructions directly into
AGENTS.md(it’s injected every run), or - Add a line in
AGENTS.mdlike “When doing X tasks, always consult skill Y first.”
Docs (skills injection behavior): https://docs.openclaw.ai/concepts/system-prompt#skills
Docs (skills config, enable/disable/load paths): https://docs.openclaw.ai/tools/skills-config
- How to restrict it to only its own workspace (and not get tricked into other dirs)?
Best practice is sandboxing + minimal mounts + deny escape hatches:
- Turn on sandboxing (often
mode: "all"), and set workspace access to what you want:"none"(safest: it doesn’t see your real workspace at all), or"ro"(can read workspace but can’t write), or"rw"(only if you truly want it editing files)
- Avoid extra Docker bind mounts (
sandbox.docker.binds) that expose other host directories. - Disable or tightly restrict host exec escapes: deny
exec(orgroup:runtime), and disabletools.elevatedif you don’t need it.
Docs: https://docs.openclaw.ai/gateway/sandboxing
Docs (mental model / debugging): https://docs.openclaw.ai/gateway/sandbox-vs-tool-policy-vs-elevated (andopenclaw sandbox explain)
If you tell me whether you want read-only workspace vs no workspace access at all, I can suggest a minimal “locked down” config snippet that matches that goal.
根据第5点,但是之前不是提到如果要限制exec tools执行的bin就需要把Exec Host改为gateway/node吗?
对的:想让 exec.security=allowlist 真正生效,必须让 exec 走 host=gateway 或 host=node(也就是走“Exec approvals”那套机制)。
关键点在文档里写得很直白:
security(deny/allowlist/full)只对gateway/node的 host-exec 做强制host=sandbox时不会走 approvals;而且 sandboxing 默认是关的,所以host=sandbox往往其实就是“直接在 gateway 主机上跑”,等同于没上锁“If sandboxing is off,
host=sandboxruns directly on the gateway host … and does not require approvals. To require approvals, run withhost=gateway…”
Source:/docs/tools/exec.md
另外你贴的这个配置:
"security": "allowlist",
"safeBins": ["cat"]
这里的 safeBins 不是 allowlist,它的含义是“在 allowlist 模式下额外放行一小撮 stdin-only 的安全命令(不需要显式 allowlist 条目)”。它并不会把其它命令都拦掉——真正的 allowlist 条目是在执行主机上的 ~/.openclaw/exec-approvals.json(或 Control UI → Nodes → Exec approvals 里配置),而且按解析后的二进制路径匹配(不是只写 cat 这种 basename)。
你要的“只允许名单里的 bin”通常这样配
- 把默认 exec host 改成 gateway(或 node):
{
tools: {
exec: {
host: "gateway",
security: "allowlist",
ask: "on-miss"
}
}
}
-
去 Exec approvals 里加 allowlist(例:
/bin/cat或/usr/bin/cat这种路径/glob),并且如果你想“严格手工名单”,把autoAllowSkills关掉(否则技能里带的 CLI 可能也会被自动放行)。 -
顺手在当前会话里发
/exec看看有没有被 session override 成host=sandbox/security=full(/exec会覆盖配置的默认值)。
我的意思是我要怎么使用sandbox限制openclaw agent能够对文件夹访问的限制并且不影响我的exec-approvals 机制
Sandbox 跟 exec-approvals 其实是两条“正交”的机制:sandbox 负责“工具在哪跑 + 能看到哪些目录”,而 exec-approvals 只在你把 exec 跑到真实主机(host=gateway|node)时才会生效。所以你完全可以用 sandbox 限制文件夹访问,同时保留 exec-approvals 作为“逃生阀”。
1) 用 sandbox 限制 agent 能看到的目录(文件系统隔离)
核心是这两个配置:
agents.defaults.sandbox.mode:打开 sandbox(建议"all"或"non-main")agents.defaults.sandbox.workspaceAccess:决定 sandbox 里能不能看到“你的 agent workspace”"none"(默认):完全看不到你的 workspace,只在容器自己的~/.openclaw/sandboxes/...里活动"ro":workspace 只读挂载(会禁用write/edit/apply_patch)"rw":workspace 读写挂载到/workspace(常用)
如果你想“只给它看某个文件夹”,最干净的做法通常是:
- 给该 agent 配一个独立 workspace,指向你允许的目录(或只包含允许内容的目录)
- 配置项:
agents.list[].workspace
- 配置项:
- 或者用
sandbox.docker.binds只把特定 host 目录挂进容器(:ro/:rw)
2) 不影响 exec-approvals:把 host-exec 当成“需要批准的特权通道”
exec-approvals只管exec host=gateway/exec host=nodeexec host=sandbox永远是在容器里跑,不会走 approvals(也不需要)
所以推荐的使用姿势是:
- 默认让 agent 主要在 sandbox 里干活(受目录挂载限制)
- 只有在确实需要访问主机环境/真实文件时,才显式用
host=gateway或host=node,这时就会触发 exec-approvals 的 allowlist/弹窗/deny 等机制
注意:一旦你允许 host=gateway|node 的 exec,那条命令本质上就有“主机视角”的文件访问能力了——sandbox 不会再限制它;能限制它的只剩 allowlist +(可选)ask 提示 + 你 allowlist 里放了哪些二进制(尽量别 allowlist 那种万能读文件工具,或者用你自己写的 wrapper 来限制路径)。
文档:
3) 排查你现在到底有没有在 sandbox 里
强烈建议跑一下(能一眼看出当前 session 是否被 sandboxed、workspaceAccess、tool policy、生效来源):
openclaw sandbox explain
文档: https://docs.openclaw.ai/gateway/sandbox-vs-tool-policy-vs-elevated
如果你愿意贴一下你当前的 agents.defaults.sandbox 配置(以及你期望“允许访问的目录范围”),我可以给你一份最小可用的 JSON5 配置模板。
- 如果我agents.defaults.sandbox.workspaceAccess: none,agent还能读取到agent.md / soul.md / memory.md吗?
- 我能不能隔离agent.md / soul.md / memory.md不存放在workspace里但是agent依然能够读取他?
workspaceAccess: "none"时,agent 还能“看到” AGENTS/SOUL(以及你说的 memory)吗?
分两层:
-
模型上下文层(system prompt 注入):可以。OpenClaw 会把一组“workspace 启动文件”读出来注入到每次运行的 system prompt 里(
AGENTS.md / SOUL.md / ...),所以就算工具在 Docker 里看不到 workspace,模型本身依然能在上下文里读到这些内容。
Source:/docs/concepts/system-prompt.md(Workspace bootstrap injection 段落) -
工具文件系统层(read/write/edit/exec 在容器里):不行。
workspaceAccess: "none"的意思就是容器内工具看不到你的 agent workspace,它只能看到自己的 sandbox 工作区(~/.openclaw/sandboxes/...那套)。因此它无法通过read去打开你 host workspace 里的AGENTS.md/SOUL.md/...文件,也无法直接改它们。
Source:/docs/gateway/sandboxing.md(Workspace access 段落)
小提醒:你提到的
agent.md通常是指AGENTS.md(工作区里的那份)。
- 能不能把
AGENTS.md / SOUL.md / MEMORY.md放到“不是 workspace 的地方”,但 agent 仍然能读?
按当前设计,不太行(不支持“自动从别处找这些文件”):FAQ 明确这些文件默认就是“agent workspace 的一部分”。
Source:/docs/help/faq.md→ “Where should AGENTS.md / SOUL.md / USER.md / MEMORY.md live?”
但你可以用一个等价的方式达到“隔离工作目录、但保留人格/记忆文件”的效果:
- 把 workspace 设成一个“只放人格/记忆/配置文件”的小目录(里面放 AGENTS/SOUL/MEMORY/memory/…)
- 然后用
agents.defaults.sandbox.docker.binds把你允许 agent 访问的真实项目目录挂进 sandbox(:ro或:rw)
这样:人格/记忆仍然按官方路径工作(workspace 里),但 agent 对“其它文件夹”的访问仍然被 sandbox 限制住。
如果你愿意,我可以按你想开放的目录(例如只开放 /data/foo 读写、其它全禁止)给你一份最小 JSON5 配置示例。
我确认一下当前信息,也就是说所以我打开sandbox模式后,在chat上的方面要求他执行tools时,tools只能访问到~/.openclaw/sandboxes/下的文件,所以我的agent.md/ soul.md/ memory.md 就算在workspace也不会影响,并且我的skills也能正常读取对吧?
基本方向对,但你这句里有两个关键“细节”要修正一下:
1) workspaceAccess: "none" 时,哪些 tool 只能看到 ~/.openclaw/sandboxes/...?
是的:read/write/edit/exec/process 这类文件/命令工具在 sandbox 里运行时,默认只能访问 sandbox 工作区(~/.openclaw/sandboxes/...)以及你额外 docker.binds 挂进去的目录。
Source: https://docs.openclaw.ai/gateway/sandboxing (Workspace access)
所以:它们不会通过 read 去直接读取你 host workspace 里的 AGENTS.md / SOUL.md / ...。
2) 但 AGENTS.md / SOUL.md “不会影响”这一句不完全对
虽然 tools 看不到 workspace 文件,但 OpenClaw 仍会把一组 workspace 启动文件(AGENTS/SOUL/TOOLS/IDENTITY/USER/HEARTBEAT 等)读取出来,注入到每次运行的 system prompt 里。
也就是说:它们仍然会影响 agent 的行为(因为模型在上下文里看得到),只是模型不能用文件工具去打开/修改它们。
Source: https://docs.openclaw.ai/concepts/system-prompt (Workspace bootstrap injection)
另外:在
workspaceAccess: "none"下,模型也基本没法把“写入记忆/更新 AGENTS.md”这类操作真正落盘到你的 host workspace(因为写入发生在 sandbox 里)。
3) skills 能不能“正常读取”?
能读到 skill 的 SKILL.md 说明文档这一点通常没问题:workspaceAccess: "none" 时 OpenClaw 会把“符合条件的 skills”镜像到 sandbox 工作区里,让 read 能读。
Source: https://docs.openclaw.ai/gateway/sandboxing (Skills note 那段)
但注意两点常见坑:
- skill 的依赖/二进制不一定在 sandbox 镜像里(例如需要 node、brew、系统包),所以“能读说明”≠“能跑成功”
- sandbox 不继承 host 的环境变量,很多 skill 需要你用
agents.defaults.sandbox.docker.env配环境变量或自己做镜像
Source: https://docs.openclaw.ai/tools/skills-config (Sandboxed skills + env vars)
如果你愿意,把你现在的 agents.defaults.sandbox 配置片段贴一下(尤其是 mode/workspaceAccess/docker.binds),我可以帮你确认:哪些路径可见、skills 会不会被镜像、以及怎么最小化地做到“能用技能但不泄露主机目录”。
根据第2点的信息,那么我设置 workspaceAccess: "none"的情况下,是不是agent就没办法更新记忆,那么要怎么维护上下文呢?
对,如果你把 agents.defaults.sandbox.workspaceAccess: "none" 开到位了,那么:
- 在 sandbox 里跑的文件工具(
write/edit/apply_patch/exec等)看不到你的 host workspace,所以也就没法去更新 host workspace 里的MEMORY.md/memory/*.md(也包含你放在 workspace 里的AGENTS.md/SOUL.md)。
Source: https://docs.openclaw.ai/gateway/sandboxing (Workspace access)
那“上下文怎么维护”分两种:
A) 短期上下文:靠 session transcript(不靠记忆文件)
即使不开 workspace 挂载,对话历史/compaction summary 还是会照常存在 ~/.openclaw/.../sessions,所以短期任务、连续对话一般没问题;只是它会受 compaction/裁剪影响,不适合当长期记忆库。
B) 长期上下文(可持续“记忆”):你需要给它一个“可写的记忆落点”
OpenClaw 的“记忆”本质就是 workspace 里的 Markdown 文件:MEMORY.md + memory/YYYY-MM-DD.md。
Source: https://docs.openclaw.ai/help/faq (How does memory work / where should MEMORY live)
所以要真正能更新记忆,通常用这几种模式(推荐从 1 开始):
1) 最推荐:把 workspace 变成“干净的小目录”,然后 workspaceAccess: "rw"
思路是:让它可写的只有 workspace(里面就放记忆/人设文件),别的目录一律不挂载;需要访问某个项目目录时,再用 sandbox.docker.binds 精准挂进去(:ro/:rw)。
这样你既保留了 sandbox 的目录隔离,又不牺牲记忆维护。
2) 双 Agent 分工(一个沙盒干活,一个“图书管理员”写记忆)
让“沙盒 agent”只负责对话/分析;需要落盘的记忆,让它发消息给另一个更受控的 agent(可写 workspace、但禁用 exec),由后者去更新 MEMORY.md/memory/*。
3) 继续用 workspaceAccess: "none",但接受“没有长期记忆落盘”
这就是最硬的隔离:安全性最好,但你得接受它只能靠会话历史维持,不适合长期积累偏好/事实。
如果你愿意贴一下你现在的 agents.defaults.sandbox 配置片段 + 你希望“允许访问哪些目录(项目路径)”,我可以给你一份最小可用的配置模板(既能写记忆,又只挂载你允许的目录)。
我要怎么设置指定subagent使用sandbox workspaceAccess: "none"模式
我要怎么设置指定subagent使用sandbox workspaceAccess: "none"模式
要“指定某个 agent 用 sandbox + workspaceAccess: "none"”,做法是:用 multi-agent 配置,在 agents.list[] 里给那个 agent 写 sandbox 覆盖(per-agent sandbox 会覆盖 agents.defaults.sandbox)。
下面给你一个最小可用模板(JSON5),思路是:
main:不 sandbox(正常可写 workspace)locked:永远 sandbox(mode: "all"),并且workspaceAccess: "none"(工具只能看到~/.openclaw/sandboxes/...)bindings:把某个 Discord channel(或 group/dm)路由到locked这个 agent
{
agents: {
list: [
{
id: "main",
default: true,
sandbox: { mode: "off" },
},
{
id: "locked",
// 关键:这个 agent 的工具永远在 Docker 里跑
sandbox: {
mode: "all", // off | non-main | all
scope: "agent", // session | agent | shared(可选;agent=复用一个容器)
workspaceAccess: "none" // none | ro | rw
},
// 可选:再叠一层“工具策略”,把沙盒里能用的工具收紧
// tools: { deny: ["exec"] } // 或 tools.sandbox.tools.allow/deny
}
]
},
// 把特定 Discord 频道路由给 locked agent(把 id 换成你的频道 id)
bindings: [
{
agentId: "locked",
match: {
channel: "discord",
peer: { kind: "channel", id: "1470379559659769974" }
}
}
]
}
配置完:
- 保存到你的
openclaw.json(配置文件路径以你实际为准) - 重启 gateway(例如
openclaw gateway restart) - 用这个命令确认它真的在 sandbox、且 workspaceAccess 生效:
openclaw sandbox explain
补充两点常见坑:
- 如果你不做 multi-agent(只有
agents.defaults.*),那就只能“全局默认”开 sandbox,没法只针对某一个 agent。 mode: "non-main"是“只 sandbox 非 main session”(群/频道通常会算 non-main),而你要“这个 agent 永远 sandbox”,就用mode: "all"。
你想路由的是“某个频道”、还是“所有群聊”、还是“某些 DM”?我可以按你的目标给你把 bindings.match 写成最准确的版本。
我能够设置他的sandbox目录吗?不同subagent我想用不同的目录
可以。Sandbox 的“目录”主要分两件事:
- sandbox workspace 在宿主机上存放的位置(host 上的目录)
用sandbox.workspaceRoot控制(全局或 per-agent 都行):
{
agents: {
list: [
{
id: "locked",
sandbox: {
mode: "all",
workspaceAccess: "none",
workspaceRoot: "/tmp/openclaw-sandboxes-locked"
}
}
]
}
}
这会把该 agent 产生的 sandbox workspace 放到你指定的 root 下面(默认是 ~/.openclaw/sandboxes)。
(workspaceRoot 是 host 路径;容器内通常还是挂到 /workspace。)
- 不同 subagent 想用不同目录
这里要看你的sandbox.scope:
- 推荐:
scope: "session"
subagent 本身就是单独 session(agent:<agentId>:subagent:<uuid>)。当scope=session时,每个 session(包括每个 subagent)都会有自己独立的 sandbox workspace 子目录(自动分配,互不影响)。
sandbox: {
mode: "all",
scope: "session",
workspaceAccess: "none",
workspaceRoot: "/tmp/openclaw-sandboxes"
}
- 如果你用的是
scope: "agent"或"shared",那同一个 agent 下的多个 session/subagent 可能会共用同一个容器/工作区(更省资源,但目录会混在一起)。想 subagent 之间隔离输出,就别用这两个 scope。
补充:不能“按 subagent 自定义一个固定路径/名字”(目前 subagent 的 workspace 路径是运行时按 session 自动生成在 workspaceRoot 下的子目录)。如果你想要更可控的目录结构,一般做法是让 subagent 在自己的 sandbox workspace 里再创建子目录,或者把 subagent spawn 到不同的 agentId(不同 agent 可以有不同 workspaceRoot/binds),前提是你允许 agents.list[].subagents.allowAgents。
想要我给你一份“locked agent + subagents 隔离 + 绑定指定只读项目目录”的完整配置例子的话,告诉我你现在的目标是:
- subagent 之间要不要完全隔离(容器/进程级)?
- 你希望挂载哪些 host 目录进 sandbox(ro/rw)?
如果我设置了workspaceRoot: "/tmp/openclaw-sandboxes",请问我原本agent的workspace厘米的agent.md会同步到workspaceRoot: "/tmp/openclaw-sandboxes"吗?还是agent一样会读取原本workspace里的agent.md?
不会同步。
workspaceRoot: "/tmp/openclaw-sandboxes" 只是在说:当这个 agent/session 运行在 Docker sandbox 里时,容器的“sandbox 工作目录”在宿主机上落盘到哪里(默认是 ~/.openclaw/sandboxes,你现在改到 /tmp/...)。
你原本 agent 的 workspace(agents.defaults.workspace 或 agents.list[].workspace)里的:
AGENTS.md(你说的 agent.md)SOUL.mdMEMORY.md/memory/*.md
仍然在原来的 workspace 里,OpenClaw 也仍然会从原 workspace 读取它们来做 system prompt 的 bootstrap 注入(影响模型行为)。它们不会被复制/同步到 workspaceRoot 下。
差别取决于 workspaceAccess:
workspaceAccess: "none":
工具(read/write/edit/exec/process)只能看到 sandbox workspace(在你设置的workspaceRoot下那份),看不到原 workspace 文件,所以也读不到/改不了AGENTS.md等(工具层面)。workspaceAccess: "ro"/"rw":
不是“同步”,而是把原 workspace 通过挂载的方式暴露给容器(ro 或 rw),这样工具才有机会访问到那份文件。
一个额外提醒:你把 workspaceRoot 放在 /tmp 的话,很多系统会定期清理 /tmp,所以 sandbox 里的产物/缓存可能会不稳定丢失;想要持久一点建议用家目录下的路径。
我要怎么样让openclaw的agent发送api时我在backend获取到这个agent的身份,比如subagent id
我要怎么样让openclaw的agent发送api时我在backend获取到这个agent的身份,比如subagent id
OpenClaw 目前不会在“agent 自己发出去的 HTTP/API 请求”里自动附带身份信息(比如 subagent id)。要让你的 backend 能稳定拿到“是谁发的”,最靠谱的做法是:让请求走一个你控制的 tool(插件 tool),由 Gateway 在 tool 层把身份写进 header/body。
你想要的“subagent id”,其实就在 sessionKey 里:
subagent 的 sessionKey 形如 agent:<agentId>:subagent:<uuid>(这个 <uuid> 就是你要的 subagent 标识)。
推荐方案:写一个插件 tool,自动加 header(agentId + sessionKey + toolCallId)
思路:
- 注册一个 tool(比如
backend_api),专门用来请求你的 backend - 用 plugin hook
before_tool_call给这个 tool 的参数里注入:ctx.agentIdctx.sessionKey
- tool 执行时把它们写进 HTTP header(同时再加
toolCallId用于链路追踪)
这样 backend 收到请求就能读到:
x-openclaw-agent-id: main|locked|...x-openclaw-session-key: agent:main:subagent:...(可解析出 subagent uuid)
x-openclaw-tool-call-id: ...(每次 tool 调用唯一)
相关能力在插件系统里是支持的(before_tool_call hook 会拿到 agentId/sessionKey 上下文)。
Docs: https://docs.openclaw.ai/concepts/agent-loop (hook points)
Docs: https://docs.openclaw.ai/plugins/agent-tools 、https://docs.openclaw.ai/plugins/manifest
后端怎么取 subagent id?
如果你拿到 header x-openclaw-session-key:
- 普通会话:
agent:main:main/agent:main:discord:channel:<id>… - subagent:
agent:main:subagent:<uuid>
你在 backend 里按 :subagent: 分割就能拿到 <uuid>。
退而求其次(不写插件):只能“让模型自己带上”
比如让 agent 用 exec 调 curl 时,自己在 payload/header 里写一个 id。但问题是:模型默认并不知道自己的 sessionKey/subagentKey,所以你还是得额外做一层“把 sessionKey 提供给它”的机制(最终基本又绕回插件/hook/tool 了)。
如果你告诉我你现在“API 是怎么发出去的”(exec + curl?skill 脚本?还是你已经在写插件 tool?)以及你想放在 header 还是 body 里,我可以给你一份最小可用的插件目录结构(openclaw.plugin.json + index.ts)示例,直接把 agentId/sessionKey/toolCallId 注入并转发到你的 backend。