#Agents in discord have lost the ability to SSH or execute shell
1 messages · Page 1 of 1 (latest)
This is almost always one of these three things:
- Tool policy changed (exec got removed via
tools.profile/tools.allow/tools.deny) - Exec host/sandbox mismatch (exec defaults to
host=sandbox, but if sandboxing is off it now fails closed) - Exec approvals/allowlist started denying (especially if you’re running host=gateway/node from a sandboxed session)
Can you paste (a) the exact error text your agent says when you ask it to run a command, and (b) your version?
openclaw --version
Then run these and paste output:
openclaw config get tools.profile
openclaw config get tools.allow
openclaw config get tools.deny
openclaw config get tools.byProvider
openclaw config get tools.exec.host
openclaw config get agents.defaults.sandbox.mode
The two most common “fix it immediately” cases
A) tools.profile is set to messaging / minimal (or tools.allow doesn’t include runtime tools)
Make sure runtime tools are allowed. exec lives in group:runtime (exec, bash, process).
Config idea (JSON5) — add/append group:runtime:
{
tools: {
allow: ["group:runtime"],
},
}
Docs: https://docs.openclaw.ai/tools (see tool profiles + group:runtime)
B) tools.exec.host is sandbox but agents.defaults.sandbox.mode is off
This matches the “worked before, now exec/ssh dead” symptom after an update: exec won’t silently run on the host anymore.
Either enable sandboxing, or set exec to run on the gateway host:
{
tools: {
exec: { host: "gateway" },
},
}
Docs: https://docs.openclaw.ai/tools/exec (note about “fails closed” when sandbox is off)
If exec is allowed but commands are being denied
That’s usually exec approvals (host=gateway/node is gated). Check:
openclaw approvals get --gateway
…and/or add an allowlist entry for your ssh binary (path depends on OS; check which ssh on the gateway host):
openclaw approvals allowlist add --gateway --agent "*" "/usr/bin/ssh"
Docs: https://docs.openclaw.ai/tools/exec-approvals and https://docs.openclaw.ai/cli/approvals
Paste the outputs and the exact error line and I’ll tell you which of the above you hit and the smallest config change to restore it.
this is the error I just tested my available tools again — and no, I still cannot execute SSH from this session.
I only have messaging/session tools here, not terminal tools (exec/SSH/tmux). So I can’t even run a test command myself in this chat context.
If you want, I can give you a single SSH smoke test command now and once you paste output I’ll continue immediately:
this is the version: 2026.3.7. output of tools openclaw config get tools.allow
openclaw config get tools.deny
openclaw config get tools.byProvider
openclaw config get tools.exec.host
openclaw config get agents.defaults.sandbox.mode
That error message is basically a dead giveaway: your config has put the agent into a messaging-only tool profile (or an equivalent tools.allow allowlist), so exec never even makes it into the toolset for Discord sessions.
On 2026.3.7, the built-in profiles are (from config ref):
messaging⇒ noexec/processcoding⇒ includesgroup:runtime(soexec+process)full⇒ no restriction
So the fix is in tool policy (tools.profile / tools.allow / tools.byProvider and possibly per-agent overrides).
What to edit (most common fixes)
Option A (simple): switch back to coding/full globally
In ~/.openclaw/openclaw.json:
{
tools: { profile: "coding" }, // or "full"
}
Option B (keep messaging profile, but add runtime tools explicitly)
{
tools: {
profile: "messaging",
allow: ["group:runtime"], // adds exec + process
},
}
Option C (you accidentally restricted only the provider you’re using)
If tools.byProvider pins your model/provider to profile: "messaging"/"minimal", remove that entry or add runtime there too.
Docs: https://docs.openclaw.ai/gateway/configuration-reference (Tools → Tool profiles / byProvider)
One thing I still need from you
You listed the commands you ran, but not the actual outputs. Can you paste these outputs (wrap in a code block) so I can point to the exact line causing it?
openclaw config get tools.profile
openclaw config get tools.allow
openclaw config get tools.deny
openclaw config get tools.byProvider
openclaw config get agents.list
(If agents.list is huge, paste just the parts that mention tools.profile, tools.allow, tools.deny, or tools.byProvider.)
Once exec shows up again, if SSH still fails we’ll move to step 2 (exec host + approvals/allowlist), but right now you’re blocked earlier: the runtime tools aren’t even enabled.
do I need to add that for each agent, because I'm seeing a lot of these "tools": {}
No — you only need to set it per agent if you want that agent to behave differently from the global default.
In OpenClaw, tool policy is inherited like this:
- Global:
tools.profile/tools.allow/tools.deny - Per-agent override (optional):
agents.list[].tools.*
So when you see lots of:
"tools": {}
that just means “this agent doesn’t override anything” → it inherits whatever you set at the top-level tools.
If you want all agents to get terminal tools
Set it once globally:
{
tools: { profile: "coding" } // (includes exec/process via group:runtime)
}
(or profile: "full" if you really want everything)
If you only want some agents to get terminal tools
Keep global restrictive, and override only the ops/coding agent(s):
{
tools: { profile: "messaging" },
agents: {
list: [
{ id: "ops", tools: { allow: ["group:runtime"] } }
]
}
}
If you paste your current tools.profile + the top-level tools.allow/tools.deny, I can tell you the smallest change to get exec back without accidentally opening up every agent.
I see it below the agents like this "tools": {
"profile": "messaging",
"web": {
Yep — that’s the line that’s removing exec.
If an agent has:
tools: {
profile: "messaging",
web: { ... }
}
…then that agent is explicitly pinned to the messaging tool profile, which (by design) does not include exec / process (aka terminal/SSH/tmux capability).
Fix options (pick one)
Option 1: Change that agent to a runtime-capable profile
Change profile: "messaging" → profile: "coding" (or "full"):
tools: {
profile: "coding",
web: { ... } // keep this as-is
}
Option 2: Keep “messaging” but add runtime tools
tools: {
profile: "messaging",
allow: ["group:runtime"],
web: { ... }
}
Option 3: Remove the per-agent tools.profile entirely
Then the agent will inherit whatever you set globally under top-level tools.profile.
If you want all your Discord agents to be able to run SSH, you’ll need to apply this to each agent that currently has profile: "messaging" (or remove that override so they inherit).
After editing, restart (or let hot-reload apply it), then re-test in Discord. If exec shows up but SSH is still blocked, we’ll move to the next layer (exec host + approvals/allowlist).
this is what it looks like "tools": {
"profile": "coding",
"web": {
"search": {
"provider": "brave",
"apiKey": "REDACTED"
}
},
"exec": {
"security": "full",
"ask": "off"
}
That config block should make exec available again (since profile: "coding" includes group:runtime).
If it still won’t actually run commands, the next gotcha is: exec defaults to host: "sandbox". If you don’t have sandboxing enabled, recent builds will fail closed instead of silently running on the gateway host.
Do this next (pick one)
1) Run exec on the gateway host (simplest)
Add host: "gateway":
"exec": {
"host": "gateway",
"security": "full",
"ask": "off"
}
2) Or enable sandboxing
Set agents.defaults.sandbox.mode to "all" (or "non-main" depending on what you want), and keep host: "sandbox".
Also: start a fresh session after config changes
In the Discord chat/thread where you’re testing, send:
/new(or restart the gateway)
One more important check
Make sure you don’t have a tools.byProvider rule that’s narrowing tools back down (it applies after the base profile and can still remove exec).
Can you paste:
openclaw config get tools.byProvider
openclaw config get agents.defaults.sandbox.mode