OpenClaw EnterpriseDOCSGitHub

Agent deployment diagnostics flow

Overview

An admin requests fresh runtime checks for one saved version through a bodyless API call. OpenClaw Control Plane (OCC) authorizes the exact target, asks the selected Compute Driver for runtime checks with time and size limits, and returns that observation. The call ends at the API response; it does not change deployment work or select a live version.

Entry Points

Flow

graph TD
  A["POST diagnostics for this version"] --> B["OCC resolves and authorizes version and Agent"]
  B -->|denied or missing| C["Return 403 or 404"]
  B -->|authorized| D["Select matching Compute Driver"]
  D -->|unsupported| E["Return 503"]
  D -->|supported| F["Kubernetes resolves owned Namespace and version Pods"]
  F -->|Pod absent| G["Return unknown check for that container"]
  F -->|one Pod| H["Read private runtime diagnostics and status through Pod proxy"]
  H --> I["Recheck Pod UID and container identity"]
  I -->|changed| G
  I -->|same| J["Validate checks for the requested version"]
  J -->|invalid| E
  J -->|valid| K["Return current observation"]
  G --> K

Execution Trace

1. Authorize the exact deployment

packages/contracts/src/api/routes.ts:occApiRoutes declares a bodyless POST. apps/controller/src/index.ts:requiredPermissions requires exact Agent operate and read plus Agent revision read. packages/occ/src/index.ts:OpenClawController.diagnoseAgentDeployment resolves the version under the supplied Namespace and Agent, authorizes the same resources, and selects the Compute Driver recorded in that version.

2. Read the current runtime

apps/controller/src/drivers/compute/kubernetes/index.ts:KubernetesComputeDriver.diagnoseAgentDeployment checks the binding and owned Namespace. deployment-diagnostics.ts:collectDeploymentChecks reads diagnostics and startup status concurrently for each runtime role under a shared ten-second deadline. In a two-cluster installation, dedicated Gateways use their managed Gateway namespace and dedicated Harnesses use the tenant namespace.

apps/controller/src/drivers/compute/kubernetes/private-status-proxy.ts:readPrivateStatusProxy reads and decodes the private endpoint with a 64 KiB limit. A 404 or 503 means the endpoint is unavailable for this observation. A redirect fails the read and the Driver requests body cancellation without retrying. The Driver checks the Pod name, UID, and container ID again before using the decoded evidence. Missing or replaced Pods produce unknown checks. Invalid diagnostics data fails the request. When concurrent reads reach the shared deadline, the Driver can still classify a rejected Gateway diagnostics request before reporting a generic timeout.

Before it generates the runtime programs, the Kubernetes renderer loads the shared failure vocabulary. runtime-entrypoints.ts:isStringArray requires a string at each position in the diagnostic check, code, and startup failure lists. An empty position or a value of another type stops the renderer from loading with Invalid runtime failure vocabulary.

apps/controller/src/drivers/compute/kubernetes/runtime-entrypoints.ts:PLUGIN_RUNTIME_HELPERS calls channels.status through OpenClaw's public Gateway SDK on demand in the Gateway container. It maps live configuration, authentication, and connectivity to safe codes without sending a message. The call cancels after six seconds or when the HTTP caller disconnects. OpenClaw loads the Slack plugin only for a Configuration with a Slack channel, so for an Agent without one the Gateway refuses the call as an unknown channel; that refusal maps to configuration failed with NOT_CONFIGURED. The probe code is part of the Gateway Pod specification, so a version deployed by an earlier controller keeps the earlier mapping (three unknown PROBE_FAILED checks) until the Agent is redeployed. Transport failures return UNAVAILABLE; other RPC failures return PROBE_FAILED. Both produce unknown checks; local configuration is not substituted for the live response. The Agent container currently returns no channel checks.

KubernetesComputeDriver.heldRuntimeFailureCheck also reads each Pod's private runtime status. A runtime that held startup, such as a Gateway with an unusable peer configuration record or an Agent whose model check failed, reports its failure there. The Driver lists it first as a failed check named after the startup step, with the failure code; diagnostics do not rerun that step. The private boundary accepts only real UTC timestamps, normalizing a valid whole-second value to the public millisecond form. A failed, impossible-date, or otherwise invalid status read adds nothing.

The Driver skips Harness Pod proxy reads when the revision's selected Sandbox Driver provisions the Harness. An OpenShell Harness listens inside its own Sandbox network namespace. Its agent runtime-status check is unknown with code UNAVAILABLE. The Gateway can still report a held failure.

Beside Compute's checks, OpenClawController.diagnoseAgentDeployment asks the version's Sandbox Driver for its record of a dedicated Harness Sandbox (observeHarness, with a ten-second timeout signal). The result leads the list as an agent sandbox check: succeeded while the Sandbox runs, failed with a code such as SANDBOX_FAILED or HARNESS_EXITED once it can no longer serve the version, failed with HARNESS_RESTARTING while OpenShell restarts a Harness process that exited, and unknown on a first start (code STARTING), when the record is unreadable (UNAVAILABLE), or when a version that is not selected for the running Agent has no Sandbox, such as a stopped Agent's.

3. Return validated evidence

packages/occ/src/deployment-diagnostics.ts:deploymentDiagnostics requires the requested Agent revision ID, valid timestamps, and at most 32 checks with component, check, and code values of 1 to 64 allowed characters. A component, check or code outside packages/contracts/src/runtime-failure.ts reads UNRECOGNIZED. Native Driver errors become DEPENDENCY_UNAVAILABLE without messages. A rejected private Gateway diagnostics Pod-proxy request instead retains the fixed RuntimeDiagnosticsTransportError class and message in the request-ID-correlated http.dependency_unavailable operator log. OCC reconstructs this error without supplier text or causes. The public response remains generic 503 DEPENDENCY_UNAVAILABLE. This category identifies collection transport; it does not establish a channel failure or its network cause. Pod discovery, invalid endpoint data, redirects, and normal not-serving responses keep their existing handling. Stored deployment status, startup evidence, plugin warnings and Agent state stay unchanged.

Guarded first admission

The Configuration persistence flow traces first-deployment admission and receipt recovery. That path ends when OCC commits an Agent revision and queues reconciliation. Diagnostics observes runtime state after admission.

Debugging and Verification

Search documentation