fix(agents): subagent hard-deny list cannot be overridden by allow config (#120025)

* fix(agents): make subagent hard-deny list non-overridable and deny message tool

The always-deny list for subagent sessions (gateway, cron, message, sessions_send,
conversations_*) could be overridden by ordinary allow/alsoAllow config entries,
letting a configured subagent profile re-enable direct user delivery outside the
announce chain. The hard-deny layer now applies unconditionally; message joins the
list so resumed/visible subagent sessions cannot send directly either (hidden
launches already disabled it at spawn time).

* chore: re-fire CI

* chore: re-fire CI against fixed main baseline

* test(agents): workspace authority reflects non-overridable subagent deny list

The delegating-worker rejection case relied on alsoAllow bypassing the
subagent hard-deny list; with the bypass closed the policy owner blocks
sessions_spawn and the worker stays confined, so the guard has nothing to
reject.
This commit is contained in:
Peter Steinberger
2026-08-07 03:58:02 -07:00
committed by GitHub
parent e910324f10
commit 8994c7799b
5 changed files with 112 additions and 21 deletions
+10 -8
View File
@@ -573,14 +573,16 @@ Sub-agents use the same profile and tool-policy pipeline as the parent or
target agent first. After that, OpenClaw applies the sub-agent restriction
layer.
Sub-agents always lose `gateway`, `agents_list`, `session_status`, and
`cron` regardless of depth or role (system-level/interactive tools, or
tools the main agent should coordinate). Leaf sub-agents (default depth-1
behavior, and always at depth 2) additionally lose `subagents`,
`sessions_list`, `sessions_history`, and `sessions_spawn`. Sub-agents never
get the `message` tool — it is disabled at spawn time, not filtered by
this deny list — and `sessions_send` stays denied so sub-agents
communicate only through the announce chain.
Sub-agents always lose `gateway`, `agents_list`, `session_status`, `cron`,
`message`, `sessions_send`, and the `conversations_*` tools regardless of
depth or role (system-level/interactive tools, direct delivery surfaces, or
tools the main agent should coordinate). This hard-deny layer is derived from
the persisted sub-agent session envelope on every turn, including resumed and
visible dashboard sessions; ordinary `allow`/`alsoAllow` entries cannot override
it. Hidden launches also disable `message` before tool construction as defense in
depth. Leaf sub-agents (default depth-1 behavior, and always at depth 2)
additionally lose `subagents`, `sessions_list`, `sessions_history`, and
`sessions_spawn`, so sub-agent communication stays on the announce chain.
`sessions_history` remains a bounded, sanitized recall view here too — it
is not a raw transcript dump.