For installed third-party OpenClaw plugins, are plugin tools expected to require tools.alsoAllow, or is there a supported way for the plugin/install flow to expose them automatically? I need the correct current pattern for a plugin that registers tools successfully but whose tools are not visible in chat unless I manually add the plugin id to tools.alsoAllow.
#third-party OpenClaw plugins and `tools.alsoAllow`,
1 messages · Page 1 of 1 (latest)
Short version, yes, what you’re seeing is expected with current defaults.
- Plugin install/enable loads the plugin, but it does not automatically widen chat tool policy.
- With modern local configs,
tools.profile: "coding"is commonly set by default, and those profiles only include built-in tool groups, not third-party plugin tools. - So a third-party plugin tool usually stays hidden in chat until you explicitly allow it.
Current pattern
- If the plugin tool is registered with
{ optional: true }, explicit opt-in is required. - The recommended opt-in is usually:
{
tools: {
alsoAllow: ["your-plugin-id"]
}
}
or per-agent:
{
agents: {
list: [
{
id: "main",
tools: {
alsoAllow: ["your-plugin-id"]
}
}
]
}
}
You can also allow the specific tool name instead of the plugin id.
When it works automatically
A plugin tool is automatically visible only if:
- the tool is not optional, and
- your effective tool policy is permissive enough, for example
tools.profile: "full"or no restrictive allowlist/profile blocking it.
If you keep tools.profile: "coding" or another restrictive profile, even non-optional plugin tools may need alsoAllow.
So, is there an install-flow auto-expose mechanism?
Not really, no.
There is support for auto-enabling/loading plugins in some config-driven cases, but not for silently auto-exposing third-party tools into chat policy. Explicit tool policy is still the supported path.
Docs/source to check
- Plugins: https://docs.openclaw.ai/tools/plugin
- Building plugins, optional tools: https://docs.openclaw.ai/plugins/building-plugins#registering-agent-tools
- Tool profiles: https://docs.openclaw.ai/gateway/configuration-reference#tools
- Example of additive enablement for an optional plugin tool: https://docs.openclaw.ai/tools/lobster
So, the safest answer is: yes, using tools.alsoAllow for the plugin id is currently the right pattern when you want plugin tools exposed without replacing your existing profile.
Does openclaw config support appending to an array like tools.alsoAllow without overwriting the existing list? If yes, what is the exact command syntax on current OpenClaw? If no, what is the recommended way to safely add openclaw-gws to tools.alsoAllow without clobbering existing entries?
I don’t see a native append operation in openclaw config right now.
openclaw config set supports setting a path, bracket notation for indexes, and batch mode, but not a +=/--append style merge. So the safe pattern is read → merge → set.
If tools.alsoAllow is not set yet, this works without clobbering existing entries:
openclaw config set tools.alsoAllow "$(
(openclaw config get tools.alsoAllow --json 2>/dev/null || echo '[]') \
| jq -c '. + ["openclaw-gws"] | unique'
)" --strict-json
If you want to validate first:
openclaw config set tools.alsoAllow "$(
(openclaw config get tools.alsoAllow --json 2>/dev/null || echo '[]') \
| jq -c '. + ["openclaw-gws"] | unique'
)" --strict-json --dry-run
Two important gotchas:
- If
tools.allowis already set in the same scope, don’t addtools.alsoAllowthere. Current config validation rejectsallow+alsoAllowtogether in one scope. - In that case, merge into
tools.allowinstead.
Docs: https://docs.openclaw.ai/cli/config
If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution. That helps Answer Overflow index it for future users. 🎉
Are skills shipped inside an installed OpenClaw plugin automatically available to the agent in chat, or is there an extra step required? I have skills/gws/SKILL.md present in the installed plugin, but the agent does not seem to use it.
They’re automatic once the plugin skill is actually eligible, but there are a few gates.
So, no tools.alsoAllow-style extra step for skills. If a plugin ships skills, they should be available when the plugin is enabled.
The common reasons a plugin skill does not show up / get used are:
-
The plugin manifest doesn’t declare the skills dir
For a native plugin,openclaw.plugin.jsonneeds something like:{ "id": "openclaw-gws", "skills": ["./skills"] }Just having
skills/gws/SKILL.mdon disk is not enough by itself.
-
The plugin isn’t effectively enabled/allowed
Plugin skills only load when the plugin is enabled. -
Agent skill allowlists exclude it
agents.defaults.skills/agents.list[].skillscan filter it out. -
The skill frontmatter gates it out
metadata.openclaw.requires.*can hide it if required config/env/bins are missing. -
disable-model-invocation: trueis set
Then it can still exist, but it won’t be shown to the model in<available_skills>.
Also, even when loaded, the model still has to choose to read/use the skill. It’s not guaranteed to proactively use it unless the description clearly matches the task.
Best checks
openclaw skills list --eligible
openclaw skills info gws
If gws is missing from --eligible, it’s being filtered somewhere.
Docs:
If you want, I can help narrow it down to the exact failing gate if you paste:
- the plugin’s
openclaw.plugin.json - the
skills/gws/SKILL.mdfrontmatter - the relevant
plugins/agents.*.skillsconfig bits
Need help debugging plugin-packaged skill discovery in OpenClaw 2026.4.10.
I have a native plugin openclaw-gws installed successfully at ~/.openclaw/extensions/openclaw-gws. The plugin itself loads and runs correctly.
Files on disk:
~/.openclaw/extensions/openclaw-gws/openclaw.plugin.json~/.openclaw/extensions/openclaw-gws/skills/gws/SKILL.md
Manifest includes:
json
{
"id": "openclaw-gws",
"skills": ["./skills"]
}
SKILL.md exists and has normal content, no frontmatter.
But:
openclaw skills list --eligible does NOT show gws
openclaw skills info gws says Skill "gws" not found
Question:
For native plugins, are plugin-packaged skills supposed to appear in openclaw skills list --eligible? If yes, what exact requirements am I missing here?
Please answer concretely:
Is "skills": ["./skills"] in openclaw.plugin.json the correct manifest format?
Does SKILL.md need frontmatter/metadata or a different layout/name?
Are there any plugin enable/allowlist/config gates that affect plugin skill discovery separately from plugin loading?
Based on this repro, what is the most likely reason the skill is not being discovered?
Yep, they are supposed to appear in openclaw skills list --eligible when everything is wired correctly.
Based on your repro, the most likely reason is simply this:
SKILL.mdwith no frontmatter is not a valid discovered skill.
The loader requires at least adescriptionin frontmatter.namecan fall back to the folder name (gws), butdescriptionis required.
Direct answers
1. Is "skills": ["./skills"] correct in openclaw.plugin.json?
Yes. That is the correct native-plugin manifest shape.
2. Does SKILL.md need frontmatter / different layout / name?
Yes, it needs frontmatter. Minimum is:
---
name: gws
description: Use Google Workspace helper flows for Gmail, Calendar, Drive, etc.
---
# GWS
...
Layout skills/gws/SKILL.md is correct.
metadata is optional.
name is effectively optional because it can fall back to the directory name, but description is not.
3. Are there plugin enable / allowlist / config gates?
Yes, but mostly the normal ones:
- the plugin must be effectively enabled/allowed
- normal agent skill filters can hide it:
agents.defaults.skillsagents.list[].skills
- skill frontmatter gates can hide it:
metadata.openclaw.requires.*disable-model-invocation: true
There isn’t a separate tools.alsoAllow-style step for skills.
4. Most likely reason in your exact repro?
Missing frontmatter, specifically missing description.
The loader drops skills that do not parse to a valid skill object, and a no-frontmatter SKILL.md ends up with no description, so it never gets registered. That matches:
skills list --eligiblenot showing itskills info gwssaying not found
What I’d try
Add this to skills/gws/SKILL.md:
---
name: gws
description: Use Google Workspace tools and workflows for Gmail, Calendar, Drive, and Docs.
---
When the task involves Google Workspace, read this skill first.
Then rerun:
openclaw skills list --eligible
openclaw skills info gws
Docs:
If that fixes it, please mark the solution so Answer Overflow can index it. 🎉
For an installed native plugin like openclaw-gws, what is the best supported way for an agent to manage it without first-class plugin tools?
Current state:
- plugin tools were removed
- plugin skill
gwsis now discovered and eligible - but in this chat surface the agent says it lacks file/shell tools, so the skill cannot actually edit config or inspect logs
Question:
Is there a supported non-tool path for plugin management in chat, such as plugin commands, slash commands, CLI registration, or some other mechanism that does not depend on tools.alsoAllow or shell/file tools?
I’m specifically looking for the recommended OpenClaw pattern for simple plugin controls like pause/resume/status when plugin tools are undesirable and skill guidance alone is insufficient.
Yes, there is a supported non-tool path, but it’s commands, not skills.
Recommended pattern
1. Generic plugin lifecycle in chat: use built-in /plugins
Enable:
{
commands: {
plugins: true
}
}
Then use things like:
/plugins list/plugins inspect openclaw-gws/plugins enable openclaw-gws/plugins disable openclaw-gws
That is the supported chat-native path for install/enable/disable/status of plugins.
2. Plugin-specific controls like pause/resume/status: use api.registerCommand()
That’s the best OpenClaw-native pattern when you do not want agent tools.
Example shape:
/gws status/gws pause/gws resume
Plugin commands bypass the LLM and do not depend on tools.alsoAllow, read, exec, or write.
What not to use for this
- Skills: good for guidance/discovery, not a control plane.
registerCli(): good for terminal commands, not the primary chat control surface.- Natural-language “agent decides and does it”: if you want that, you still need a tool. There is no hidden non-tool capability path for model-driven actions.
So the clean split is:
- User-driven chat control →
/pluginsor pluginregisterCommand() - Model-driven action from normal conversation → tool
My recommendation for openclaw-gws
If you want simple runtime controls without tool exposure, I’d implement plugin commands for:
statuspauseresume
and use built-in /plugins only for coarse lifecycle (enable/disable/install/inspect).
Docs:
- Plugins: https://docs.openclaw.ai/tools/plugin
- Slash commands: https://docs.openclaw.ai/tools/slash-commands
- SDK overview (
registerCommand): https://docs.openclaw.ai/plugins/sdk-overview
If this solved it, please mark the solution so Answer Overflow can pick it up. 🎉
In recent OpenClaw releases, did the default tool exposure or trusted surface for normal chat sessions change in a way that would remove local file/shell tools from sessions that previously had them? I’m seeing a session that now has a reduced toolset even though older sessions on this machine used to have broad file access. Please explain which config/runtime/profile settings now control that.
Short version: yes, the effective tool surface can be narrower now, but it’s mostly policy-driven, not “plugin install auto-exposes tools.”
For plugin tools specifically
Third-party plugin tools are not auto-granted just because the plugin loads.
What controls visibility/callability is the tool policy:
tools.profiletools.allow/tools.denytools.alsoAllowtools.byProvider[...]- per-agent overrides under
agents.list[].tools.* - sandbox tool policy under
tools.sandbox.tools.*
For plugin tools, the supported additive pattern is:
{
tools: {
alsoAllow: ["your-plugin-id"]
}
}
or specific tool names.
That matches the current docs pretty closely: plugin authors can register tools, but users still opt them into the effective policy. Plugin install/loading does not bypass tool policy.
Why a session may now have fewer local file/shell tools
The main knobs are:
tools.profile
Baseline profile:
fullor unset = broadestcoding= includesgroup:fs+group:runtimemessaging= no local file/shell toolsminimal= basically none
Docs note: newer local onboarding defaults unset configs to:
tools.profile: "coding"
So that can reduce some tools versus old “effectively full” setups, though coding still keeps file/shell.
- Any non-empty
tools.allowputs you in allowlist mode
This is the big gotcha.
If you have:
tools: { allow: ["group:fs"] }
then everything else is blocked unless also listed.
So plugin tools, exec, etc. disappear unless explicitly allowed.
-
tools.alsoAllowis additive
Use this when you want to keep the existing profile/allowlist and just add a plugin or extra tool. -
Provider/model-specific restrictions
These can silently narrow one session if it’s using a different model:
tools.byProvider["openai/gpt-5.4"]
agents.list[].tools.byProvider[...]
- Per-agent overrides
These override global tool policy for that agent:
agents.list[].tools.profile
agents.list[].tools.allow
agents.list[].tools.alsoAllow
agents.list[].tools.deny
- Sandbox tool policy
Even if a tool is globally allowed, sandbox policy can still block it:
tools.sandbox.tools.allow/deny
agents.list[].tools.sandbox.tools.*
- Node-originated trust hardening
There was a recent breaking change here, but it’s specifically for node-originated runs:
node-triggered/session events now stay on a reduced trusted surface.
That is not the general rule for ordinary chat messages, but it can explain regressions if the session is being resumed/triggered from a node flow.
Important non-causes / easy confusion
tools.elevateddoes not grantexec. It only changes howexecruns ifexecis already allowed.tools.fs.workspaceOnlydoes not removeread/write/edit; it only narrows accessible paths.gateway.tools.allowis for the HTTP tool invoke API, not normal chat sessions.
Practical rule of thumb
If a session unexpectedly lost local file/shell access, check in this order:
tools.profiletools.allowtools.alsoAllowtools.byProvider[...]agents.list[].tools.*tools.sandbox.tools.*- whether the run is node-originated
So yes, a newer config/runtime can absolutely make a new session look “reduced” compared with older ones, especially if:
- you moved from implicit broad access to a profile,
- added any
tools.allow, - or now hit a per-agent / per-provider / sandbox restriction.
Docs:
- Config reference: https://docs.openclaw.ai/gateway/configuration-reference
- Sandbox vs tool policy: https://docs.openclaw.ai/gateway/sandbox-vs-tool-policy-vs-elevated
- Plugin authoring: https://docs.openclaw.ai/plugins/building-plugins
- Pairing / node hardening: https://docs.openclaw.ai/gateway/pairing
If you want, I can help map a specific openclaw.json snippet to the exact effective tool surface.
my agent used to have full file read access even our openclaw.json and since i upgraded it says its sandboxed and can't do local file edits or shell changes
That sounds like sandbox mode, not a plugin regression.
First, check:
openclaw --version
openclaw sandbox explain
Most likely after the upgrade you now have something like:
agents: {
defaults: {
sandbox: {
mode: "non-main"
}
}
}
and this Discord thread is a non-main group/channel session, so it runs sandboxed.
Why it lost local file/shell access
In current OpenClaw:
- DM/main session can stay on-host
- group/channel/thread sessions are often non-main
- with
sandbox.mode: "non-main", those non-main sessions run in Docker/sandbox
Docs call this out directly: group/channel keys are not main, so in non-main mode they get sandboxed.
That also means:
openclaw.jsonon the host is not readable/editable unless mounted/bound inexecmay exist but only runs inside the sandbox- if
tools.sandbox.toolsdeniesgroup:fsorgroup:runtime, file/shell tools disappear too
The settings that matter
Check these in openclaw.json:
agents.defaults.sandbox.modeagents.list[].sandbox.modetools.sandbox.tools.allowtools.sandbox.tools.denyagents.defaults.sandbox.workspaceAccess- any Docker
bindsif you expect host files inside sandbox
If you want the old behavior back
Pick one:
- Disable sandbox entirely
agents: { defaults: { sandbox: { mode: "off" } } }
-
Keep
non-main, but use the main/DM session for host-level file + shell access -
Keep sandbox, but loosen sandbox policy
Allowgroup:fs/group:runtime, and mount the paths you actually need.
Otherwise the sandbox still won’t see host files likeopenclaw.json.
Docs:
If you paste the output of openclaw sandbox explain, I can tell you the exact key that’s blocking it. Glad we caught the likely cause quickly. 🦐
If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it.
🦞 OpenClaw 2026.4.10 (44e5b62) — The lobster in your shell. 🦞
Effective sandbox:
agentId: main
sessionKey: agent:main:main
mainSessionKey: agent:main:main
runtime: direct
mode: off scope: agent
workspaceAccess: none workspaceRoot: /Users/theclaw/.openclaw/sandboxes
Sandbox tool policy:
allow (default): exec, process, read, write, edit, apply_patch, image, sessions_list, sessions_history, sessions_send, sessions_spawn, sessions_yield, subagents, session_status
deny (default): browser, canvas, nodes, cron, gateway, feishu, googlechat, nostr, msteams, mattermost, nextcloud-talk, matrix, bluebubbles, line, zalo, zalouser, synology-chat, tlon, qa-channel, discord, imessage, irc, qqbot, signal, slack, telegram, twitch, whatsapp
Elevated:
enabled: true
channel: (unknown)
allowedByConfig: false
Fix-it:
- tools.sandbox.tools.allow
- tools.sandbox.tools.alsoAllow
- tools.sandbox.tools.deny
- agents.list[].tools.sandbox.tools.allow
- agents.list[].tools.sandbox.tools.alsoAllow
- agents.list[].tools.sandbox.tools.deny
- tools.elevated.enabled
Ah, this is the key detail:
the output you pasted is for
sessionKey: agent:main:main
and it saysruntime: direct/mode: off
So that session is not sandboxed.
What this means
Your problem is likely one of these:
-
You checked the wrong session
agent:main:mainis the main session.
The session that complained may be a different agent or a non-main chat/thread session. -
A per-agent override is sandboxing the actual agent
Checkagents.list[].sandbox.mode.
- It is not sandbox at all, it is tool policy
Sincemode: off, the remaining likely blocker is:tools.profiletools.allowtools.byProvideragents.list[].tools.*
Important nuance
The “Sandbox tool policy” section in that output is just the sandbox policy config.
Because your effective mode is off, that policy is not the active reason for a block in agent:main:main.
What I’d check next
Run these:
openclaw config get tools.profile
openclaw config get tools.allow
openclaw config get tools.alsoAllow
openclaw config get tools.byProvider
openclaw config get agents.list
What to look for
- If
tools.profileismessagingorminimal, that would remove local file/shell tools. - If
tools.allowis non-empty, you are in allowlist mode.
Thengroup:fsandgroup:runtimemust be explicitly present. - If a specific agent has:
agents.list[].tools.profileagents.list[].tools.allowagents.list[].tools.byProvider
that can override the global behavior.
One more likely gotcha
Plugin tools needing tools.alsoAllow is normal if you’re using a non-full profile.
For example, tools.profile: "coding" still allows built-in file/shell tools, but does not auto-allow plugin tools.
So at this point I’d say:
- plugin tools missing = likely expected policy behavior
- built-in file/shell missing = probably
tools.profile/tools.allow/ per-agent override, not sandbox, based on the output you posted
If you paste the output of those openclaw config get ... commands, I can narrow it down fast.
tools.allow = coding
tools.alsoallow = clawnet
{
"id": "main",
"heartbeat": {
"every": "60m"
},
"subagents": {
"allowAgents": [
"beacon",
"vesper"
]
},
"tools": {
"allow": [
"clawnet"
]
}
},
Yep, that explains it.
The breaking bit is this:
{
"id": "main",
"tools": {
"allow": ["clawnet"]
}
}
That puts the main agent into allowlist mode with only clawnet allowed.
So read, write, edit, apply_patch, exec, process, etc. all get stripped out for that agent.
Correct mental model
tools.profile: "coding"= baseline built-in coding toolstools.alsoAllow: ["clawnet"]= additive, goodagents.list[].tools.allow: ["clawnet"]= restrictive, bad for your use case
So the fix is
Remove this:
agents.list[].tools.allow
or change it to additive instead:
{
"id": "main",
"tools": {
"alsoAllow": ["clawnet"]
}
}
If you want the whole main agent to have normal coding tools + the plugin, the clean config is:
{
tools: {
profile: "coding",
alsoAllow: ["clawnet"]
},
agents: {
list: [
{
id: "main"
}
]
}
}
One more thing
If you literally set:
tools.allow = coding
that is wrong shape. It should be:
tools.profile = "coding"
and alsoAllow must be camelCase:
tools.alsoAllow = ["clawnet"]
So, short answer: it’s not sandbox.
It’s the per-agent allow: ["clawnet"] override choking off everything else.
Docs:
If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow picks it up.
so our plugin install uses tools.allow and it worked previously but it sounds like this has changed and we need to adopt our plugin. here's what claude said:
our plugin sets this during openclaw clawnet setup. Look at lines 496 and 500-502:
- Line 496: When creating a new agent entry, it sets tools: { allow: ["clawnet"] } — this means if the agent didn't exist before, the only allowed tool is clawnet.
- Lines 500-502: For existing agents, it pushes "clawnet" into tools.allow — this is additive and fine.
The problem is line 496. For new agents, we're creating tools.allow with only ["clawnet"], which in newer OpenClaw versions means "only allow clawnet, block everything
else." We should be using tools.alsoAllow (like we do at the global level on line 487-488) instead of tools.allow at the agent level, or we should not set tools.allow at
all and just rely on the global alsoAllow.
Want me to fix this? The fix would be to stop setting tools.allow on the agent entry and instead only use the global tools.alsoAllow (which we're already setting
correctly on line 487-488), or switch the agent-level config to use alsoAllow as well.
Claude is basically right, with one important correction:
pushing
"clawnet"intotools.allowis not inherently “fine”
unless that allowlist already contains everything else the agent needs.
tools.allow is the restrictive allowlist.
So these both narrow the tool surface:
tools.allow = ["clawnet"]
tools.allow = ["group:fs", "group:runtime", "clawnet"]
The second one is fine only because it’s a complete allowlist.
So the safe current pattern is
For plugin install/setup that wants to add plugin tools without shrinking the agent:
tools.alsoAllow = ["clawnet"]
or per-agent:
agents.list[].tools.alsoAllow = ["clawnet"]
I would not use this in an installer
agents.list[].tools.allow = ["clawnet"]
unless you are intentionally replacing the whole tool policy for that agent.
So, did OpenClaw “change”?
I would phrase it as:
- the current/official semantics are that
allowmeans allowlist mode - installers that used
allowas if it were additive were relying on a fragile assumption - the safer adoption path now is to switch plugin setup to
alsoAllowfor additive exposure
My recommendation for your plugin
- New installs: use
alsoAllow, notallow - Existing installs: migrate any agent entry that has only
["clawnet"]intools.allow - only keep
tools.allowif you are deliberately managing a full explicit allowlist
So yes, I’d fix the plugin. That sounds like the right move.
If this fixed it, please right-click the solution message → Apps → ✅ Mark Solution so Answer Overflow can index it.
do we need to read alsoAllow and then append?
Yes, exactly.
If your setup flow is being additive, it should:
- read existing
tools.alsoAllow - append
"clawnet"if missing - write back the deduped array
Same idea for agents.list[].tools.alsoAllow if you’re doing it per-agent.
Good behavior
- preserve existing user entries
- append only if missing
- do not replace the whole array
- do not write
tools.allowunless you mean “this is the full allowlist”
In practice
If you already set global:
tools: {
alsoAllow: ["clawnet"]
}
then you usually do not need agent-level alsoAllow too, unless you want it only on specific agents.
So the simplest fix is probably:
- stop writing
agents.list[].tools.allow - merge
"clawnet"into globaltools.alsoAllow