Added for OpenClaw 2026.4.15. Covers Task Brain, introduced in v2026.3.31-beta.1 and hardened across the 2026.4.x line in response to the March 2026 CVE wave.
Read this if you're on OpenClaw v2026.3.31-beta.1 or later (you are, if you're up to date), run sub-agents, use approvals, or do anything in production. Skip if you're on a pre-Task-Brain build — but in that case you should upgrade first (see Part 26).
Before 2026.3.31-beta.1, OpenClaw had four separate ways to run something:
- Your interactive agent session
- ACP (Agent-Callable Procedure) invocations
- Cron jobs (v4.0 built-in cron)
- Sub-agent spawns
Each had its own execution path, its own audit trail (or lack of one), and its own approval semantics. Getting a complete picture of "what is this OpenClaw instance actually doing right now?" meant grepping four different log locations.
Task Brain unified all of it onto a SQLite-backed task ledger. Every non-trivial action in OpenClaw — regardless of who kicked it off — is now a task/flow in one ledger. Current CLI docs expose the ledger through the openclaw tasks command family:
openclaw tasks list
openclaw tasks show <task-id>
openclaw tasks cancel <task-id>
openclaw tasks flow list
openclaw tasks flow show <flow-id>Older 2026.4.15-era notes and screenshots used
openclaw flows. If your installed binary still has that alias, it is the same ledger. Preferopenclaw tasks --helpin new docs/runbooks.
Think of it as the Kubernetes control plane, but for AI agent actions: unified lifecycle, heartbeat monitoring with automatic recovery of lost tasks, parent-record tracking so subtask results trace back to the originating conversation, and blocked-state persistence so tasks retry on the same flow instead of fragmenting.
May update: spawned sub-agent events now carry spawnedBy routing metadata, and current Control UI builds show sub-agent sessions nested under their parent. Combine that with active-run steering (covered in Part 33) and humans can correct a running agent at the next model boundary instead of starting a competing thread.
Task Brain wasn't a gentle roadmap item. It shipped as the structural response to a cluster of CVEs disclosed against OpenClaw over February–March 2026. Headline entries included CVE-2026-25253 (one-click RCE), CVE-2026-25157 (command injection), CVE-2026-25158 (path traversal), plus a WebSocket shared-auth scope escalation at CVSS 9.9 (nine CVEs in four days in mid-March alone). Peter Steinberger's official release post described the v2026.3.31-beta.1 drop as "primarily about security hardening." The common thread across most of those CVEs:
- Name-based allowlisting is not a security boundary. The old approvals model let users write
approvals: { allow: ["bash", "exec"] }. A malicious skill could register a new tool namedbash_v2that did whatever it wanted — the allowlist matched on name, not intent. - No cross-surface enforcement. A tool blocked in an interactive session was often still runnable via cron or sub-agent spawn, because each surface enforced approvals independently.
- Approval prompts leaked credentials. Covered in Part 15 — 2026.4.15 redacts these now.
Task Brain replaces name-based allowlisting with semantic approval categories and enforces them at a single choke point every surface goes through.
Version accuracy (verify against your binary). The semantic-category model below describes how Task Brain reasons about approvals at the control-plane choke point. Depending on your installed version, you may not find a literal
agents.*.approvalsblock ofread-only.*/execution.*/control-plane.*string tokens, and you may not find anopenclaw flowscommand — both surfaced in the v2026.3.31-beta.1 control-plane release post but renamed/reshaped across the 4.x line. As of 2026.4.15 stable / 2026.4.19-beta.2, inspect and set policy with the shipping knobs instead, then confirm withopenclaw tasks --helpandopenclaw exec-policy show:
Guide concept (semantic model) Verified shipping knob (2026.4.15+) execution.shell/execution.codeallow vs asktools.exec.security(full/allowlist/none) andtools.exec.ask(always/on-miss/off)write.fs.outside-workspacedenytools.fs.workspaceOnly(bool)Per-channel tool profile tools.profile(e.g.messaging) andtools.toolsBySender(see below)Read the live policy / audit it openclaw exec-policy show,openclaw exec-policy preset <yolo|cautious|deny-all>,ocplatform security audit [--deep]Treat the per-category
approvalsJSON in this part as the intended control-plane model (and the shape the Control UI exposes), not as a guaranteed config-file key in every build. Thanks to #8 for the field report.
Every tool invocation is now classified into one of a small fixed set of categories. The canonical ones:
| Category | Meaning | Examples |
|---|---|---|
read-only.filesystem |
Reads from disk, no writes | read_file, grep, memory_search |
read-only.network |
Read-only network calls | web.search, web.fetch, API GETs |
execution.shell |
Runs shell commands | exec, bash, powershell |
execution.code |
Runs interpreter code | python, node, REPL tools |
write.filesystem |
Modifies files | write_file, edit, patch |
write.network |
Non-trivial network writes | API POST/PUT/DELETE, webhooks, email, tweet |
control-plane.secrets |
Reads/writes secrets | secrets.get, secrets.set, secrets.reload |
control-plane.tasks |
Controls other Task Brain tasks | spawn, cancel, approve, deny |
control-plane.skills |
Installs/removes/updates skills | ClawHub operations, see Part 23 |
Categories are assigned by the tool's declared intent, not by name. A skill can't sidestep execution.shell by registering a tool called totally_not_bash — it still runs through the shell executor, so Task Brain categorizes it as execution.shell regardless of the display name.
{
"approvals": {
"read-only.*": "allow", // frictionless
"execution.shell": "ask", // per-call approval
"execution.code": "ask",
"write.filesystem": "allow", // inside repo scope; narrow if needed
"write.network": "ask",
"control-plane.*": "ask", // never silent
"control-plane.skills": "deny" // explicitly install from CLI only
}
}Rules of thumb:
read-only.*\u2192 allow. Agents need to read to be useful. Logging is fine, approval prompts on every file read are not.execution.*\u2192 ask (at least on first use, or by command signature). This is the one you'll actually approve/deny hundreds of times — the core agent behavior loop.write.network\u2192 ask. Tweeting, emailing, posting webhooks, API DELETEs. Asymmetric blast radius — one silent approve can send a message you can't recall.control-plane.*\u2192 neverallow. This is the key structural change. If a skill is installing other skills, rotating secrets, or cancelling tasks on its own, that's the shape of a privilege-escalation attack. Keep these approval-required even if it's annoying.control-plane.skills\u2192 deny. Install skills from the CLI with a human in the loop. Don't let an agent install its own toolbelt autonomously.
You can set different approval policies per agent. The pattern we use on our 14-agent deployment:
{
"agents": {
"main-orchestrator": {
"approvals": {
"read-only.*": "allow",
"execution.*": "ask",
"write.network": "ask",
"control-plane.*": "ask"
}
},
"coding-worker": {
"approvals": {
"read-only.*": "allow",
"execution.shell": "allow", // spawn trusted, needs to run tests
"execution.code": "allow",
"write.filesystem": "allow",
"write.network": "deny", // workers should never post
"control-plane.*": "deny"
}
},
"research-worker": {
"approvals": {
"read-only.*": "allow",
"write.*": "deny", // research only
"execution.*": "deny",
"control-plane.*": "deny"
}
}
}
}Narrow-scope workers get frictionless autonomy inside their scope and hard walls outside it. The orchestrator keeps humans in the loop on anything destructive. This is the CEO/COO/Worker model from Part 5 but with enforcement, not honor system.
May 2026 adds a second axis: requester identity. tools.toolsBySender restricts the tool schema for a channel/user even when the agent itself is trusted. Use it for public Discord/Telegram/Slack users, guest DMs, or shared support inboxes where you want the same agent personality but not the same filesystem/runtime permissions.
{
"tools": {
"toolsBySender": {
"*": {
"deny": ["exec", "process", "write", "edit", "apply_patch"]
},
"id:guest-user-id": {
"deny": ["group:runtime", "group:fs"]
},
"channel:discord:1234567890123": {
"alsoAllow": ["group:fs"]
}
}
}
}Rules:
- Sender keys must come from the channel adapter, not from message text.
- Use explicit prefixes (
channel:<platform>:<id>,id:<id>,e164:<phone>,username:<handle>,name:<display-name>, or*). - Deny runtime and filesystem mutation for wildcard/public senders.
- Per-agent
agents.list[].tools.toolsBySendercan override the global sender match when needed.
2026.5.22 removed the old sender-owner tool gating path. Do not assume a legacy owner flag protects channel users. Test the real sender identity from each adapter and verify the restricted schema actually strips runtime, filesystem, Codex, MCP, dynamic, and app-default tools for wildcard/public senders.
Task Brain decides whether an action is allowed. The 2026.5.20 Policy plugin checks whether shared channel policy is configured sanely before actions are requested. Run it before opening Discord/Telegram/Slack/iMessage surfaces to more users:
openclaw policy check
openclaw doctorLook for channel conformance findings, accepted-attestation drift, and repair suggestions. Treat opt-in repair like a config migration: review the diff, back up config, then apply deliberately.
Task Brain added the inverse of the approval flow: an agent can now refuse to do something you asked it to do and have that refusal be a first-class event.
[agent] I've been asked to rm -rf ~/.openclaw/. I'm denying this because
it would destroy the auth profiles. Flagging as task 9a3f-....
[you] openclaw tasks show 9a3f
[you] # confirm context, re-issue the request with explicit approval
This matters because:
- Prompt injection attacks can come from anywhere — a compromised vault file, a malicious skill, a poisoned memory entry. An agent that's allowed to refuse is an agent that has a chance to push back on an injected instruction.
- The refusal is logged. You get to see "the agent almost did X, but stopped." That's a signal you used to miss entirely.
Don't punish agent denies. If your agent is refusing too often, tighten your prompts / approvals — don't try to suppress the deny behavior itself.
Another 2026.3.31-beta.1 hardening: plugins now default to fail-closed. Pre-Task-Brain, an unconfigured plugin might do "whatever the author thought reasonable." Now:
- An unconfigured approval policy \u2192 treated as
ask, notallow. - A plugin that can't reach its backend \u2192 the task is held, not silently run without protection.
- A category Task Brain doesn't recognize \u2192
ask, not pass-through.
This trades a bit of friction for "we don't have unintended silent bypasses." It's the right trade for a production setup.
Late-May hardening removed the old cat SKILL.md && printf ... && <exec> allowlist compatibility path. Load skill files with the read tool and approve the actual executable, not a shell prelude that happens to mention the skill file.
2026.5.22 narrows default delegated worker context to AGENTS.md and TOOLS.md. Persona, identity, user, memory, heartbeat, and setup files are no longer injected into sub-agent sessions by default.
That is good for cost and privacy, but it changes orchestration prompts. If a worker needs customer context, project memory, or a persona constraint, pass a bounded summary in the spawn task instead of assuming inherited bootstrap. Treat sub-agent prompts as self-contained work orders.
openclaw tasks maintenance --json also now explains stale-running maintenance decisions, including backing-session, cron, CLI, and wedged-subagent state. Put it in weekly ops review.
A weekly habit worth building:
# What's running right now? (stuck cron, forgotten spawn)
openclaw tasks list --status running
# Dig into anything that looks odd
openclaw tasks show <task-id>
# Cancel runaway or orphaned flows
openclaw tasks cancel <task-id>For longer-horizon auditing (7-day window, category filters, denied/approved breakdowns), subcommand flags have moved between betas — run openclaw tasks --help against your installed version for the exact set. Current docs expose tasks list/show/cancel/audit/maintenance and tasks flow list/show/cancel. Run openclaw tasks maintenance --json when a task looks stale; recent builds include retained/reconcile reasons for backing sessions, cron, CLI, and wedged sub-agents. Category filtering and denied-flow rollups are primarily visible through the Control UI task/flow panels, not via CLI flags.
You'll find:
- Cron jobs that haven't done anything useful in weeks (delete them)
- Skills making network calls you didn't realize (revisit Part 23)
control-plane.*events clustered on a single skill (investigate hard)- Denied tasks with interesting reasons (that's your agent catching prompt injection — good)
Callout added in the April 2026 refresh. Two YC-backed services that launched on cloud-sandbox agent delegation landed this week:
- Twill.ai (YC S25, HN thread Apr 11, 2026) — run the agent on their sandbox instead of your laptop. Their pitch: agents shouldn't have shell access to your primary environment; delegate the whole session to an ephemeral cloud VM.
- Amika (Apr 13, 2026, YouTube walkthrough) — similar model, different operator experience. Focuses on "give the agent a container, not your dev box."
This is a real architectural choice. Here's the positioning an OpenClaw operator should know:
| Dimension | OpenClaw + Task Brain | Twill / Amika (cloud sandbox) |
|---|---|---|
| Where the agent runs | On-prem, your box / server / worktree | Their cloud, ephemeral VM per session |
| Data residency | Yours. Everything stays local. | Theirs. Your code/secrets transit their infrastructure. |
| Setup cost | Configure approvals, hooks, memory. This guide. | pip install + credit card. |
| Trust model | You enforce approvals + hooks; agent has full local blast radius | They enforce sandbox boundaries; agent blast radius = their VM |
| Cost model | Your infra + your model tokens | Their infra markup + your model tokens |
| Audit trail | openclaw tasks list, your logs |
Their dashboard. You may or may not get the raw log. |
| Customizability | Full — every part of this guide | Fixed to what their UI exposes |
| Offline / air-gapped | Works | Does not |
The OpenClaw answer to cloud-sandbox delegation: Task Brain's semantic approval categories + the Part 29 hook catalog + Part 15 worktrees give you the same blast-radius containment without shipping your codebase to a third party. If you need harder isolation than worktrees (container-per-agent, VM-per-agent), pair with Docker/Firecracker — the hooks and approvals still apply unchanged.
When cloud sandboxes genuinely win: one-off workloads where you don't want to stand up local infrastructure at all, or environments where "agent on dev laptop" is a compliance non-starter. For a team running OpenClaw seriously, the on-prem path is the one this guide is written for.
- Running OpenClaw 2026.3.31-beta.1 or later (Task Brain is mandatory from here)
- Approval policy set at the root with
read-only.* \u2192 allow,control-plane.* \u2192 ask or deny - No
execution.*policies wider than the agent actually needs - Per-agent scopes configured for worker agents (narrower than the orchestrator)
-
tools.toolsBySenderdenies runtime/filesystem mutation for wildcard/public senders -
control-plane.skillsexplicitlydenyfor all agents (install from CLI only) -
openclaw tasks listreviewed weekly — watch for stuck, denied, or orphaned flows (Control UI task/flow panels give the richer view) - Approval prompts show redacted secrets (2026.4.15 — see Part 15)
- Agents are not punished for denying — denies are logged and used as signal
- Unused plugins removed (fail-closed defaults apply, but unused surface is still surface)
Task Brain doesn't make OpenClaw bulletproof. It makes it auditable and enforceable, which is the minimum a multi-agent deployment needs. If you're running more than one agent, or letting any agent do anything in production that isn't read-only, you want this configured deliberately — not left at defaults.