OpenClaw EnterpriseDOCSGitHub

Agent Plugin Deployment Flow

Overview

OCC validates selections against the Harness catalog and snapshots the Driver and policy at deployment. The Harness owns tools and approvals.

Entry Points

apps/controller/src/index.ts:createFastifyApp

Flow

graph TD
  D0["Request discovery"] -->|Create| D1["Authorize Agent create"]
  D0 -->|Saved| E0["Authorize Agent read/update"]
  E0 -->|no credential| D6
  E0 -->|bound| E1["Caller and Agent operate"] --> D6
  E0 -->|managed MCP| M0["Check credential and discover server tools"] --> D5
  E0 -->|credentialSource| D2
  D1 -->|stored source| D2["Caller source operate"] --> D6["Select Harness catalog"]
  D1 -->|token or none| D6
  D6 -->|unsupported| D7["Unsupported"]
  D6 -->|token or none| D4["Call PluginDriver"]
  D6 -->|Secret| D3["Read and recheck"] --> D4
  D6 -->|CredentialSource| D9["Check source and exact Gateway owner; read unless canceled"]
  D9 -->|success| D10["Recheck authority, source and catalog"]
  D10 -->|allowed and connected| D4
  D9 -->|canceled or failed| D12["Stop"]
  D10 -->|denied or disconnected| D12
  D4 -->|disconnect| D8["Cancel hosted reads"]
  D4 --> D5["Return safe metadata"]
  A["Authorize and validate policy"] -->|valid| S["Save Agent selections"]
  A -->|unsupported| Y["Reject write"]
  S --> B["Revalidate and snapshot version"]
  B -->|managed MCP| K["Project worker MCP and Gateway tool selections"]
  K --> L["Sandbox applies account and tool request policy"]
  L --> I
  B --> C["Validate native metadata; grant selected plugins"]
  C --> D["Attempt selected installs"]
  D -->|install rejection or auth required| E["Disable failed selections; collect warnings"]
  D -->|success| T["Resolve owned tools; translate final app policy"]
  E --> T
  T --> F["Verify native identity and effective policy"]
  F -->|invalid or unsafe| X["Keep runtime unready"]
  F -->|verified| G["Publish current startup status"]
  G --> H["Apply matching gateway configuration"]
  H -->|dedicated| P["Apply Gateway tool policy"]
  P -->|incompatible| X
  P -->|valid| I
  H -->|embedded| I["Compute returns readiness and warnings"]
  I --> J["Worker completes deployment under live claim"]
  G -->|runtime restart| C

Execution Trace

Credential-scoped discovery

Create discovery requires a Harness, Agent create, and caller operate on stored sources. Wrong Namespace: 400; missing Secret: 404; unavailable explicit CredentialSource: 409.

Saved discovery requires a dedicated Agent and caller read/update. Bound sources require caller and Agent operate; explicit sources require caller operate. Missing or unready bound sources return 404. Hosted catalogs require credentials; curated catalogs do not.

The OpenShell Backend reads metadata and exports through operator mTLS. External Gateways retain optional withSourceToken. OCC checks source/Gateway ownership, then rechecks authority, attachment and catalog before dispatch. Cancellation discards late credentials; refresh stays with its owner.

packages/occ/src/index.ts:OpenClawController.discoverManagedMcpTools

Managed MCP uses Secret Driver, rechecking before tools/list. driverPolicy.toolNames pins upstream names across runtimes.

Closing cancels; account changes clear results; Harness changes clear selections/approvers. Hosted reads bound size/time, reject redirects and credential echoes, and return safe metadata with Cache-Control: no-store. apps/controller/src/drivers/plugin/hosted-catalog.ts:catalogEntry accepts omitted requires_local_executor; explicit true without skills remains unavailable. Details reject unmatched MCP/scheduled tasks. Optional stdio NativeCodexPluginCatalogReader rejects invalid plugin/list results and stops its child.

1. Validate desired state under exact-Agent authority

apps/controller/src/index.ts:createFastifyApp

HTTP validates input. OCC checks the exact Namespace and Agent (read for reads). Create/PATCH saves plugins and Driver identity. Updates atomically save state and audit evidence. Omitted selections persist, {} clears them, and nonempty maps replace them. Clear selections with unknown or different owners before changing catalogs.

validateAgentPlugins checks policy and Configuration against the Harness catalog on Agent/provisioning writes. Deployment rechecks Configuration. OpenClaw refuses selections blocked by tools.deny, the sole agents.entries tool list, the primary provider's byProvider lists, or their combination. It also refuses selections beside an entry denying * or hidden under a profile by the sole entry's alsoAllow. openClawPluginSettingConflict checks Gateway-rejected settings first for OpenClaw Harnesses. Unsupported controls or incompatible selections return 400 INVALID_REQUEST.

validatePolicies detects conflicting enablement defaults. BundledPluginDriverBase.validate allowlists it for OCC's fixed PluginPolicyValidationError advice. Unrecognized refusals stay generic. The Console preserves rejected drafts.

Save keeps out-of-range Plugin selections JSON text and skips Agent GET/PATCH. Picker edits stop. Available catalogs remain browsable.

Read capabilities from GET /installation or GET .../plugins/capabilities (Agent read/update).

2. Admit an immutable plugin deployment

packages/occ/src/index.ts:OpenClawController.deployAgent

OCC snapshots the Configuration, Driver and selections. Before cutover the worker checks the pinned Driver against the Harness. Gateway and worker each verify their assets from Compute’s package descriptors.

Withdrawal removes credential injection. Recovery preserves other attachments.

3. Deliver requested state through Compute preparation

apps/controller/src/drivers/compute/plugin-runtime.ts:pluginRuntimeSpecForRevision

Compute validates admitted state, Driver, and Harness. Kubernetes projects the nonsecret request; Docker uses environment delivery with a 64 KiB size limit. For Codex, Compute writes the policy the Gateway runs into native approval_policy before startup validation: the configured appServer.approvalPolicy, with on-failure as on-request. Omission preserves native defaults; incompatible explicit policies remain subject to reviewer checks. At Agent save, provisioning and deployment, the Codex PluginDriver refuses an automatic reviewer unless the policy is on-request or on-failure, because an omitted policy lets the Gateway pick one the startup check cannot see. Configuration save and Compute Drivers refuse policies the Gateway refuses at load, such as untrusted.

The Kubernetes ConfigMap is immutable and per version. A version prepared by an earlier controller keeps its earlier config.toml (without [plugins._default] (#508), without approval_policy (#1995), or with on-failure as written) until the Agent is deployed again; KubernetesComputeDriver.reconcilePluginRuntimeConfigMap refuses any other difference. OpenShell dedicated Codex has no such allowance and needs a new deployment after that upgrade.

SSH Compute rejects nonempty plugin maps and Agent default plugin approver policies before host effects.

Initial embedded Kubernetes gateway preparation applies exact-Agent HTTPS egress before installation. For existing gateways, prepareRevision avoids duplicate Agent database access. activateRevision uses Recreate, stopping the old gateway before installation. Version files stay private and the native registry stays in the Agent-owned database. Docker keeps native state in the container's private temporary home.

4. Prepare native runtime state and hand off readiness

apps/controller/src/drivers/compute/kubernetes/runtime-entrypoints.ts:installOpenClawPlugins

Embedded OpenClaw validates selections against its bundled catalog and policy. Grants enter nonempty tools.allow, otherwise tools.alsoAllow; denies and profiles remain. Tool enabled overrides toolDefaults.enabled; disabled tools emit denies. Master disable and operator denies prevail. The supported modes provider_default and none add no plugin review. Version-private installs use --pin --force --no-enable, preserving enablement and tool policy. Preparation refreshes the registry and verifies configuration, plugin/package identity, versions, integrity and source containment within the install path. Verification failures keep the Gateway unready. Confirmed install rejection disables the optional selection and removes its tool allowance before startup.

Dedicated launchers capture the Gateway tool policy from the saved Agent revision before plugin grants. Startup and peer respawn enforce it; failures keep the Gateway unready. Changes require deployment replacement after affected old work ends. Human permissions stay unchanged. An embedded Gateway applies a policy that the Configuration sets without this composition, so Compute checks it at Configuration save and deployment admission with the same rules (gateway-tool-policy.ts:validateGatewayToolPolicy), not on maintenance passes.

Dedicated Codex uses isolated CODEX_HOME, disabling app/plugin defaults. Selections enable apps, plugins and remote plugins; disabled entries cannot execute. The native policy mappings describe the generated bridge.

Startup enables experimental APIs and resolves selected IDs through plugin/search. codex-plugin-stdio.ts:withCodexPluginStdio retains fixed nativeErrorType/nativeSubErrorType values, discarding other stderr/RPC content and lines over 64 KiB while draining. RPC errors alone do not prove backend installation.

runtime-entrypoints.ts:readCodexPluginDetails reads up to four selections concurrently before and after installs. Batches preserve order and drain before retries and final verification; writes stay sequential. codexRuntimeArtifact uses detail.apps, excluding appTemplates. codexInstallPlan validates policy and component support, then grants selected plugin IDs through config/batchWrite before plugin/install can report authentication requirements. App/tool grants follow; plugin defaults stay off. Bundled skills need the compatible runtime below for selected-only activation. Install rejections or missing app authentication warn. Explicit tool policies require mcpServerStatus/list's codex_apps inventory; codexAppToolSettings binds catalog action IDs through _meta._codex_apps.resource_uri. Native IDs work. Unknown, unowned, ambiguous, or duplicate IDs fail startup.

After installation, startup rechecks catalog identity, version, apps and components before final app/tool grants; plugin/read cannot inspect bundles. writeCodexPluginConfiguration replaces owned plugin/app tables, enables successful selections, disables failed/disabled plugins and unselected apps, and writes inherited tool/account approvals from merged workspace settings. Lower-layer descendants remain. Unspecified enablement stays unset; requirements still apply. Failed-only apps stay disabled; disabled selections skip installation/status.

Workspace-aware readback rejects policy conflicts before readiness. Disabled apps may retain inherited fields. Categories resolve app → global → native true; equivalent values/nulls pass. Tool enablement cannot bypass categories. verifyCodexPluginConfiguration rejects explicit enablement of unselected plugins; approval-only or MCP-policy-only entries inherit the verified plugin default-off setting. Source/account-disabled plugins remain disabled.

runtime-entrypoints.ts:startAuthenticatedCodex passes the admitted Harness model, without its provider prefix, to the app-server after the authentication probe succeeds. Native configuration readback therefore exposes the model used for startup policy validation.

runtime-entrypoints.ts:verifyCodexReviewerConfiguration checks app/link reviewers and configRequirements/read. Forbidden reviewers, incompatible automatic-review settings or conflicting model requirements block startup. Checks exclude later workspace/session/model changes and strict review. Codex 0.156 readback omits execution-time managed app/tool requirements; effective-policy proof remains necessary.

runtime-entrypoints.ts:disableCodexSelectionsWithoutChatGptLogin disables enabled selections and app/plugin features for API-key logins when best-effort preparation allows authentication warnings. API-key logins cannot install remote plugins. Startup verifies both default-off tables before handing off readiness.

For Compute-owned Kubernetes workloads, only an admitted {pluginId, code} warning results from a selected OpenClaw install's normal nonzero exit, a matching Codex plugin/install error, or a successful Codex install needing app authentication. Transport loss, timeouts, signals, malformed responses, discovery failures, and policy failures retain ordinary startup failure behavior. Provider-owned Harnesses keep their existing startup path.

Kubernetes Compute streams private startup status with a 65,536-byte limit. Overflow cancels the response without retry, even for a 404/503; within the limit those codes mean not serving. Readiness verifies workload, version, startup instance, selection keys and warnings. Docker Codex healthchecks fail on interrupted status bodies, preserving the transport code or original reason.

With the tool proxy enabled, dedicated Codex reads bundled skills at /home/node/.codex/skills/.system without a repository broker or neighboring credentials. Startup links /home/node/.openclaw/plugin-skills to /home/node/openclaw-runtime-assets/plugin-skills, keeping gateway state private.

Gateway blocks failed bridges before serving and retry during turns. Startup changes refresh effective configuration; untrusted status cannot establish readiness or change version selections.

Compute installs status NetworkPolicies before the first dedicated gateway and creates it only when the Agent and plugin status are ready and its Service selects the version. Existing gateways and full runtime policies retain their activation boundary.

The Agent and gateway derive an app-server credential from the transport Secret, Agent revision ID, and Agent startup ID. The gateway receives it after matching status and rendering exclusions. After a Harness restart, the old credential cannot open a new authenticated app-server WebSocket to the replacement Harness. It does not revoke access to a still-running old Harness or an established connection. For a changed peer, the supervisor publishes non-ready, restarts only OpenClaw and rechecks peer startup, Pod, successes and failures after it serves. Changed or unavailable peers trigger container restart. The supervisor repeats a stop signal that OpenClaw ignored during its own in-place restart, seen as readiness returning after its server closed. For writable native-admin configuration, recovery reads the bridge baseline from the read-only managed snapshot. A Pod-local record binds the last and pending generated bridges to the version and snapshot hash before configuration writes. Process and same-Pod container restarts rebuild only a matching generated bridge. Other native edits survive; conflicting bridge edits retain the existing refusal. An unreadable or mismatched record holds startup unready, reporting runtime failure peer-bridge-record (UNAVAILABLE), and logs the remedy: replace the Pod, which restores the snapshot and clears this private record. During an outage, the supervisor reports unready. Kubernetes propagates that state asynchronously, so the signal alone is not a per-request traffic fence. If OpenClaw exits while the supervisor waits for its peer, the wrapper exits for container recovery.

5. Complete version reconciliation

apps/controller/src/worker.ts:finalizeRevision

Before the worker commits activeRevisionId, preparation failure leaves the prior pointer unchanged. After commit, activation/finalization failure retains the candidate pointer and records REVISION_FINALIZATION_INCOMPLETE for retry. Embedded Kubernetes replacement runs after commit; the old gateway may already be stopped. The previous version remains stored, without pointer rollback or an availability guarantee during cutover. See the controller worker flow.

Successful completion reports REVISION_ACTIVATED or REVISION_ALREADY_ACTIVE. A candidate pointer alone is not readiness evidence. Agent turns use native policy; the workspace and gateway database remain Agent-owned.

The worker saves plugin warnings with successful work under its live claim; the worker flow covers persistence and deployment status. Claim loss blocks stale completion; later workers recheck readiness. No receipt acknowledgment, failed-plugin shutdown, or permanent failure latch exists. Warnings describe deployment completion, not ongoing health.

Debugging and Verification

The OpenClaw model probe's CPU-based deadline cannot exceed 600 seconds. CPU wait is the larger PSI or throttled delta, capped by throttled periods; missing, nonfinite or reset samples cannot establish starvation. An OpenClaw timeout is starved only if over a quarter of its last 15 s is CPU wait and no 5 s stretch is idle (timeoutWindowMs, timeoutWindowCpuWaitMs, timeoutWindowIdleMs).

Search documentation