Skip to content

fix(agents): refuse unsupported managed mode and unlisted tool actions at save - #3810

Merged
freeqaz merged 3 commits into
mainfrom
fix/2982-save-time-refusals
Oct 27, 2026
Merged

freeqaz merged 3 commits into
mainfrom
fix/2982-save-time-refusals

Conversation

@freeqaz

@freeqaz freeqaz commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Follow-up to #2982 and #2633 (post-land review findings 2676 and 2679). Both are settings that Agent save accepted and that then failed later, against the fail-early rule (refuse at save or preflight, not at deploy or at run time).

  • 2676 (fail-early half): a new Agent always defaulted to gatewayManagedMode: true. On a Compute Driver that cannot apply managed mode (SSH, Kubernetes without a configured Gateway runtime, plugin Drivers that do not declare supportsGatewayManagedMode), the Agent saved fine and its first deploy was refused. The only fix was an Installation administrator turning the setting off.
  • 2679: a Gateway tool policy that allows a tool whose schema has a top-level action field (for example dashboard) without tools.gatewayPolicy.actions.<tool> was accepted at save and at Gateway start. The pinned OpenClaw (cee236c9, src/agents/gateway-tool-policy.ts applyGatewayToolPolicy) then throws Gateway tool policy requires tools.gatewayPolicy.actions.<tool> on every tool assembly, so every model turn failed.

Change

Managed mode (packages/occ/src/index.ts, Kubernetes Compute):

  • I chose default to what the Driver supports, not refusing the default. Refusing the default would break every Console create on SSH, because the Console create form sends no gatewayManagedMode.
    • A new Agent defaults to on when the selected Compute Driver declares supportsGatewayManagedMode, and to off otherwise. With no Compute Driver selected it stays on.
    • The off default needs no Installation administer, because there is no enforcement to opt out of. An explicit gatewayManagedMode: false still needs it, as before.
  • An explicit gatewayManagedMode: true on a Driver without support is now refused at Agent create, at the create preflight (/agents/validate) and at update. The 400 uses deploy's existing message: Agent setting gatewayManagedMode is not supported by the selected Compute Driver. (now one constant).
  • KubernetesComputeDriver declares supportsGatewayManagedMode only when runtime is configured, matching its existing validateGatewayManagedMode. This uses the existing optional contract member; no Driver contract change.
  • Not changed: migration 0064, existing Agents (an upgraded SSH Agent saved with true is still refused at deploy until an administrator turns it off; the test now covers that path explicitly), and the guided provisioning default (only Kubernetes with a runtime provisions today).

Tool policy (apps/controller/src/drivers/compute/gateway-tool-policy.ts):

  • GATEWAY_ACTION_TOOLS lists the core tools in the pinned OpenClaw src/agents/tools that declare a top-level action field and are outside the baseline and the administrative list: computer, dashboard, github_publish, image_generate, mobile_ui, music_generate, personal_instructions, portal, screen, skill_workshop, theme, transcripts, video_generate.
  • An allowed tool from this list with no actions is refused with the baseline's message: Configuration setting tools.gatewayPolicy.actions.<tool> must list the permitted actions. The same function runs in the Gateway wrappers, so a revision admitted earlier now holds the Gateway unready with the tool-policy error instead of failing every turn.
  • Plugin tools are not listed. OCE cannot read a plugin tool's schema before deployment. Requiring actions for every non-baseline tool does not work either: OpenClaw also throws when actions are listed for a tool without an action field, so diffs, the documented example, could not be allowed. The docs say plugin tools still need actions when they declare an action field.

Docs: the managed-mode reference, native admin and Configuration tool-policy pages, plus the gatewayManagedMode API description (OpenAPI and docs/reference/api.md regenerated).

Verification

  • New and updated tests:
    • configuration-occ.test.mjs "a new Agent's Gateway managed mode defaults to what the selected Compute Driver enforces": Kubernetes without a runtime defaults off for a member without Installation administer; explicit true is refused at create, preflight and update; Kubernetes with a runtime defaults on.
    • occ-api.test.mjs SSH test: over HTTP, create defaults off; POST, /validate and PATCH with true get 400 with the message; an Agent stored with true (the 0064 upgrade state) is still refused at deploy and recovers after PATCH false.
    • kubernetes-compute.test.mjs admission test: allow: ["dashboard"] is refused and actions.dashboard: ["read"] is accepted, for both Harnesses.
  • Each test fails without its change:
    • reverting the Kubernetes declaration alone fails the default test;
    • reverting the controller change alone fails it too;
    • removing the refusal at create, at preflight or at update fails it (three separate mutants);
    • reverting the tool-policy change fails the admission test.
  • Touched test files pinned 10/10 at 2 CPUs on a remote test VM: configuration-occ, kubernetes-compute, occ-api.
  • GitHub CI on 04168cd67a: CI Required and First Agent Smoke green.
  • Full CI gate on a remote test VM at f6ba89c67e: 19/22 jobs passed, including First Agent Smoke, every checks-baseline, checks-browser, postgres and k3d-fixture lane, and images-runtime-startup and -3. The three failures:
    • static: the Configuration page was 6 words over the 2,500-word limit; fixed in 04168cd67a (GitHub Static Checks green);
    • images-runtime-startup-2 runtime-image-gateway-unclean-restart: fails the same way on that VM on main and is green on GitHub here;
    • repository-credentials-container: a BuildKit "layer does not exist" error on the VM while preparing the job; green on GitHub.

Risks

  • An Installation that switches from a non-supporting Compute Driver to Docker or Kubernetes with a runtime keeps the off value on Agents created before the switch. Switching Compute is itself an Installation administrator action.
  • A deployed revision whose policy allows a listed core tool without actions now stays unready on its next Gateway start, instead of starting and failing every turn.
  • kubernetes/index.ts change is two lines; Move OpenShell attachment status and withdrawal to the paired Sandbox #3808 also edits that file elsewhere.

…s at save

Gateway managed mode: a new Agent defaults to on only when the selected
Compute Driver declares support; on SSH, Kubernetes without a Gateway
runtime and plugin Drivers without the declaration it defaults to off, so
the Agent is deployable. An explicit gatewayManagedMode=true on such a
Driver is refused at Agent create, create preflight and update with
deploy's message instead of at the next deploy. Kubernetes declares
support only when its Gateway runtime is configured. Existing Agents and
migration 0064 are unchanged.

Gateway tool policy: Agent save refuses a core OpenClaw tool that declares
a top-level action field (dashboard, screen, computer, github_publish and
others in the pinned source) when the policy allows it without
tools.gatewayPolicy.actions.<tool>. The pinned OpenClaw throws while
assembling such a tool, so every model turn failed after a clean deploy.
@freeqaz
freeqaz requested a review from a team as a code owner October 27, 2026 01:33
@clawsweeper

clawsweeper Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

@clawsweeper clawsweeper Bot added clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed clawsweeper:intake:bug Preliminary submission classification; full source review pending. clawsweeper:intake:needs-repro Preliminary submission classification; full source review pending. labels Oct 27, 2026
@clawsweeper

clawsweeper Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge.

What this changes

This PR defaults new Agents to supported Gateway managed mode and rejects unsupported managed mode or missing core-tool action lists during admission.

Example: Create an SSH Agent named Runtime Agent without specifying gatewayManagedMode.

  • Before: The Agent saves with gatewayManagedMode=true, then deployment rejects the unsupported setting.
  • After: The Agent saves with gatewayManagedMode=false; explicitly requesting true is rejected at save.

Review scores

Measure Result What it means
Overall readiness 🧂 unranked krab (1/6) The repair is useful and focused, but final-effect authority and existing-state upgrade evidence are insufficient for landing.
Proof confidence 🧂 unranked krab (1/6) Real behavior proof is necessary before merge. See Before merge.
Patch quality 🦐 gold shrimp (3/6) Security review found an item that needs attention.

Product

Kind: Bug fix · Worth it: Yes · Fix scope: Complete
User problem: Agent settings can save successfully and then prevent deployment or make every model turn fail.
Reason: The failures are source-confirmed, and the collaborator-authored PR records the default choice and its limited operator tradeoffs.

Merge readiness

⛔ Blocked before merge - 5 items remain

Keep this maintainer-authored PR open: it addresses source-confirmed admission failures still present on main, with authorization and upgrade verification remaining before merge.

Priority: P2
Reviewed head: 04168cd67a13de010ab9ba8e7a0effdfa35c4f3f

Before merge

  • Add real behavior proof - Authority-chain proof required: show a member creating with the omitted setting on unsupported Compute, and show that a member cannot explicitly disable managed mode on supporting Compute or change a protected saved value before deployment effects. The supplied tests exercise real admission owners in process, but no current-head production-path result establishes those final effects. The inspected image is earlier simulated Storybook evidence, and the manifest reports ffprobe ENOENT for its earlier walkthrough video. Existing-state coverage seeds true directly in memory; it does not demonstrate an upgrade preserving saved settings and exercising the stricter policy startup path. Redacted terminal output or logs are suitable evidence; remove credentials and non-public endpoints. After adding proof, update the PR body, then request a new review with @clawsweeper re-review. The PR author or someone with repository write access can request it.
  • Update the owning flow for the new admission decisions (P3) - Creating an Agent on unsupported Compute now persists a different default and follows a different Installation-authorization path, while missing core-tool actions gain a new admission and startup failure path. No docs/flows file changes with these decisions. Root AGENTS.md and local-dev require a source-backed flow update for changes to authorization or consequential failure handling. Extend the existing harness-execution-topology and agent-plugins flows with these decisions and their source owners.
  • Resolve security review attention item - The persisted managed-mode default changes an administration boundary whose final deployment effect still needs verification.
  • Resolve merge risk - The new default persists false without Installation administration, so its authorization safety depends on the selected Compute Driver's support declaration matching actual enforcement through deployment.
  • Add data-model compatibility proof - The review found that existing stored data may not work after upgrade. Show that existing data still loads and works with this change.

Findings

  • [P3] Update the owning flow for the new admission decisions — packages/occ/src/index.ts:9184-9185

Tests

  • Missing end-to-end proof: Supply target-native save-to-deployment authorization evidence and a latest-stable upgrade retaining saved mode and policy state; the reported mutant results support the regressions but are not shipped-entry-point proof.
Agent review details

How this fits together

OCC authorizes and saves Agent drafts, snapshots them into deployment revisions, and delegates runtime enforcement to the selected Compute Driver and packaged OpenClaw Gateway.

flowchart TD
  A[Agent create or update] --> B[OCC authorization]
  B --> C[Compute capability and policy validation]
  C --> D[Saved Agent draft]
  D --> E[Deployment revision]
  E --> F[Compute runtime launcher]
  F --> G[OpenClaw Gateway]
Loading

Technical review

Best possible solution:

Keep the repair in the existing OCC admission and shared Gateway policy owners, with documented lifecycle decisions and verified authorization and upgrade behavior.

Do we have a high-confidence way to reproduce the issue?

Current-main admission accepts the unsupported default, and the pinned OpenClaw implementation explicitly throws for missing action lists; no target code was executed during this read-only review.

Is this the best way to solve the issue?

The focused checks use the existing capability contract and shared policy parser, avoiding a new configuration option or parallel enforcement path.

Full review comments:

  • [P3] Update the owning flow for the new admission decisions — packages/occ/src/index.ts:9184-9185
    Creating an Agent on unsupported Compute now persists a different default and follows a different Installation-authorization path, while missing core-tool actions gain a new admission and startup failure path. No docs/flows file changes with these decisions. Root AGENTS.md and local-dev require a source-backed flow update for changes to authorization or consequential failure handling. Extend the existing harness-execution-topology and agent-plugins flows with these decisions and their source owners.
    Confidence: 0.98

Overall correctness: patch is correct
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against afc47d3cdeb7.

Merge-risk options

Maintainer options:

  1. Verify the administration boundary (recommended)
    The PR owner should exercise ordinary-member default creation and forbidden explicit opt-out through save and deployment, showing the resulting Gateway restrictions on supporting Compute.
  2. Hold landing
    Keep the PR open until the authorization boundary can be exercised in an authorized target-native environment.

Provenance checked

  • Agent managed-mode default and save authorization changes intended behavior with a stated reason (110aea3: Managed mode defaulted on, with Installation administration required for opt-out and deployers applying the saved setting.)
  • Kubernetes managed-mode capability declaration keeps the original intent (110aea3: Kubernetes declared managed-mode enforcement, while its existing validator required a configured Gateway runtime.)
  • Gateway action-list validation keeps the original intent (36fb718: Dedicated launchers enforce explicit Gateway tool and action policy against the pinned OpenClaw implementation.)

Testing

Proof path: in-process harness.

Security

Needs attention: The persisted managed-mode default changes an administration boundary whose final deployment effect still needs verification.

Evidence

What I checked:

  • Pinned PR edits: The introduced diff changes existing OCC admission, Kubernetes capability declaration, and the shared Gateway policy parser; it adds no migration or dependency. (packages/occ/src/index.ts:9169, 04168cd67a13)
  • Current main retains the reported default: Current main still defaults Agent creation to true independently of Compute support; Kubernetes still declares support unconditionally. (packages/occ/src/index.ts:9166, afc47d3cdeb7)
  • Regression coverage and its boundary: The added coverage exercises real controller admission and HTTP routes with in-memory state; the SSH test explicitly excludes transport and seeds the historical true value directly rather than running an upgrade. (tests/integration/occ-api.test.mjs:7874, 04168cd67a13)
  • Recorded direction and accepted tradeoffs: The collaborator-authored PR explicitly chooses capability-based defaults, preserves existing Agents and migration 0064, and accepts retained off values after an administrator changes Compute plus unready startup for newly rejected policies. (04168cd67a13)
  • Prior discussion establishes ownership and scope: The discussion on feat: add Gateway managed mode to Agent deployments #2982 records save-time Installation authorization and identifies unsupported-Compute admission as follow-up work; feat(runtime): apply Gateway tool policy to dedicated OCE deployments #2633 establishes the pinned Gateway policy boundary. (110aea3888bb)
  • Authoritative dependency contract: The OCE parser names this exact OpenClaw source pin as its runtime contract; applyGatewayToolPolicy throws when an allowed action-bearing tool lacks an action list, confirming the reported tool-assembly failure. (src/agents/gateway-tool-policy.ts, cee236c9e989)

Labels

Label changes:

  • add P2: This prevents delayed admission and model-turn failures in configured Agent workflows without evidence of an emergency.
  • add merge-risk: 🚨 compatibility: Defaults change for new Agents, and previously accepted policies can now hold a Gateway unready at startup; the PR author explicitly accepts those tradeoffs.
  • add merge-risk: 🚨 security-boundary: Capability-based defaulting changes when a caller can persist unmanaged mode without Installation administration.
  • add rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • add status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Label justifications:

  • P2: This prevents delayed admission and model-turn failures in configured Agent workflows without evidence of an emergency.
  • merge-risk: 🚨 security-boundary: Capability-based defaulting changes when a caller can persist unmanaged mode without Installation administration.
  • merge-risk: 🚨 compatibility: Defaults change for new Agents, and previously accepted policies can now hold a Gateway unready at startup; the PR author explicitly accepts those tradeoffs.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Add final-effect proof that an ordinary member cannot disable managed mode on supporting Compute before a Gateway launches.
  • Exercise an upgrade from the latest stable with saved settings intact, including the newly rejected action-policy startup case.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

Reviewed October 26, 2026, 9:51 PM ET / October 27, 2026, 01:51 UTC.

…fusals

# Conflicts:
#	tests/conformance/configuration-occ.test.mjs
@freeqaz
freeqaz merged commit 92cc1a8 into main Oct 27, 2026
38 checks passed
@freeqaz
freeqaz deleted the fix/2982-save-time-refusals branch October 27, 2026 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant