OpenClaw EnterpriseDOCSGitHub

Agent provisioning flow

Overview

Console saves Slack/model Secrets and submits inline Configuration, credential references and retained Preset bindings. OCC queues setup without placeholders. The worker creates Configuration/Agent, grants exact credential access and admits the first deployment. Its handle follows activation or failure; later deployments use separate handles. See worker reconciliation and Harness topology.

Entry Points

Flow

graph TD
  Console["<b>Console</b><br/>Save entered Secrets"] --> Secrets["<b>Existing Secrets API</b><br/>Return ordinary references"]
  Secrets --> API["<b>Provision API</b><br/>Inline config and references"]
  API --> Queue["<b>Existing work queue</b><br/>Return job handle"]
  Queue --> Claim["<b>Worker</b><br/>Claim and authorize"]
  Claim --> Config["<b>Configuration Driver</b><br/>Write or recover Configuration"]
  Config -->|Repository selections still valid| Agent["<b>Create Agent</b><br/>Grant exact credential access"]
  Config -->|Repository selections refused| RepoRefused["<b>Refuse provisioning</b><br/>No new Agent or revision"]
  Agent --> Transport["<b>Compute Driver</b><br/>Trusted-proxy credentials"]
  Transport --> Deploy["<b>Ordinary deploy</b><br/>Record first version"]
  Deploy --> Observe["<b>Same provisioning handle</b><br/>Observe saved version"]
  Observe -->|Pending; version readable| UI["<b>Agent deployment view</b><br/>Open the deploying version"]
  Observe -->|Pending; version refused or unavailable| Observe
  Observe -->|Success seen in Create| Settings["<b>Agent configuration view</b><br/>Open the activated version"]
  Observe -->|Superseded| Superseded["<b>Create stays open</b><br/>Newer deployment took over"]
  Observe -->|Malformed present ID| Unknown["<b>Outcome unknown</b><br/>Keep job; offer Retry"]
  Observe -->|Confirmed failure| Terminal["<b>Creation failed</b><br/>Keep Agent and version"]
  Claim -->|Failure| Failed["<b>Retain outputs</b><br/>Retry known failures"]
  Failed -->|Uncertain write| Recovery["<b>Recovery required</b><br/>Do not repeat blindly"]

  classDef state fill:#EDF2F7,stroke:#879AB0,color:#25364A,stroke-width:1px
  classDef operation fill:#EBF3F0,stroke:#7F9D93,color:#2B4038,stroke-width:1px
  classDef condition fill:#F7F1E5,stroke:#B3A078,color:#514532,stroke-width:1px
  class Console,Secrets,API,Queue state
  class Claim,Config,Agent,Transport,Deploy,Observe,UI,Settings operation
  class Failed,Recovery,Terminal,Superseded,RepoRefused,Unknown condition

Execution Trace

1. Console saves credentials and freezes a provisioning request

apps/controller/src/console/agents/create.mts:renderCreateAgent

Console keeps the configured Harness separate from execution mode: dedicated OpenClaw uses the same provisioning, retry, and deployment navigation as dedicated Codex. Preset restoration and Credentials read native model runtime policy through apps/controller/src/console/agents/harness-auth.mjs:configuredHarnessId.

The Slack modal immediately saves new tokens through POST /namespaces/:namespaceId/secrets, before an Agent exists, then clears entered values. Apply stages references and environment bindings; Cancel discards selections but retains created Secrets. Model discovery uses an API key or service account token without saving it. Create Agent runs its preflight, then saves it as a Namespace Secret, clears the input, and reuses the reference on retries. Bound Presets retain their credential/provider. A lost Secret-save response requires recovery, not automatic repetition.

A selected Credential Gateway's catalog directs Console to register the model Secret before source-backed provisioning. Console recovery reuses confirmed sources and safely retries uncertain registration. Installation discovery preserves catalog metadata.

Create Agent sends a stable request ID, inline Configuration, Secret and model-auth references, Agent options, and repository bindings with an explicit access profile. The worker grants Secret access, including Slack. After uncertain admission, Retry sends the same ID and inputs without saving Secrets again.

For a draft, Console creates the Configuration and Agent, then grants access to selected Slack Secrets. Retry credential access keeps that Agent.

2. OCC admits one job

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

apps/controller/src/http/agents.ts:createAgentHandlers receives schema-validated inputs after shared admission. It supplies the Namespace from the route and creates the audit event inside the controller transaction.

For Harness authentication from a credential source, OCC reads the catalog entry from the recorded Gateway. Compute validates that same entry and its login mode for this admission. A later provisioning request reads the catalog again.

OCC first authorizes Agent create, Configuration create, and Installation administer for the Namespace. Status and retry use the same grants; absence gives 403 regardless of the body. It validates Configuration, references, workspace inputs, execution mode, and current authority, then refuses a taken Agent name with 409. Reserved Secret destinations, cross-Namespace references, and missing or runtime Harness authentication return 400 INVALID_REQUEST naming the rule; an absent Secret remains 404. Before Compute planning, Secret bindings get Agent save's Harness authentication check and named 400.

A selected Credential Gateway requires a supported, ready model Credential Source the caller can operate, and OCC preserves its canonical binding. Unsupported authentication methods fail before a job or external resource is created.

After an Installation selects another Secret Driver, request, status and retry answer 503 for a Secret owned by the previous Driver, after authorization and lookup. The message asks the caller to save replacement Secrets and submit a new request. The worker fails that attempt with PROVISIONING_REJECTED; an unavailable Secret Driver still retries.

OCC applies Configuration rules before Channel credential validation. Its Secret callbacks recheck provisioning grants before storage and after I/O, then confirm current same-Namespace backend and selected-Driver ownership before provider use. Slack accepts whole ${NAME} environment references and checks token roles and bot authentication. This does not pin Secret versions or revalidate queued work. OCC validates Namespace repository selections before queueing. Undeliverable bindings, including Sandbox repositories, retain Agent create's 409 on admission and retry (Compute admission). Initial workspace files require the selected Sandbox's validateWorkspaceSetup; Compute delegates validation or refuses unsupported placement before staging. Deployment checks the Harness topology.

OCC stores the accepted request and deduplication fingerprint in agent_provisioning_work, then queues controller_work with work_kind = 'provisioning'. Configuration and Agent creation happen later. The same actor, Namespace and request ID return the existing work; changed input conflicts.

The 202 response contains data.provisioning, with the work ID and status URL. Public progress exposes result IDs and safe errors without input values or backend credentials.

3. The worker creates resources and credentials

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

Under its queue claim, the worker verifies ownership, Namespace readiness and authority before effects and result commits. Retries reuse completed outputs. It creates the Configuration from the accepted inline values and bindings, then creates a stopped Agent, records the auth, provider, plugin, repository and workspace selections, and grants its service principal the exact Secret permissions.

The bundled worker uses the Installation's selected repository policy for saved selections and first revision admission. A programmatic controller without this binding uses its registered repository Driver. After fencing the claim and checking that the Namespace is ready, the worker checks the saved selections before creating the Agent. The Configuration Driver may already have written the Configuration. If the check refuses, the worker creates no new Agent or revision and follows the existing Configuration recovery rules.

Source-backed provisioning records the canonical model source and grants only source operate. Admission, replay, retry and execution recheck caller authority, source readiness and Gateway ownership. Queued or running work prevents source deletion.

Compute prepares runtime credentials without loopback HTTP. Kubernetes apps/controller/src/drivers/compute/kubernetes/index.ts:provisionAgentRuntimeCredentials confirms complete owned Secrets after create-only provisioning. Failure retains them and blocks configured success or first revision admission. kubernetesGatewayConfigurationDocument defaults to machine-only trusted-proxy administration and preserves human identities/scopes. Provisioning and deploy admission reject an invalid allowUsers or malformed deviceAutoApprove (Configuration save also refuses both), unknown or padded operator scopes, blank or padded identity keys, grants for identities outside allowUsers, malformed requiredHeaders, and human admission with admin device scopes, including whitespace; human allowlists render x-openclaw-scopes as required. With private status, validateConfiguration also refuses a Codex Configuration without gateway.auth.password, which the workspace node check signs in with. These refusals precede workload replacement. Human ingress and its network policy remain operator-managed; no OCE human account is required. See Gateway authentication. Provisioning supplies no Gateway token or trust override; losing its claim cancels Kubernetes Configuration requests.

4. Deployment becomes the lifecycle owner

packages/occ/src/index.ts:observeProvisioningDeployment

At handoff, provisioning saves the first Agent revision ID and stays running. Provisioning waits without using attempts. On success, PostgreSQL marks provisioning succeeded. If the claim has an audit attempt ID, PostgreSQL saves openclaw.controller_work.completed in the same transaction.

The job reports the wait, success, or a safe deployment error. During rollout, Stop gives REVISION_STOPPED. Stop or Delete before handoff gives PROVISIONING_CANCELLED with its action. Agent and revision IDs survive restart.

Create Agent (apps/controller/src/console/agents/create.mts:waitForProvisioning) polls the job. When a pending job names its Agent and first revision, Create gives the deployment read one second to finish. If it succeeds, Create stops polling and opens that revision's Deployment tab for progress, Stop, and recovery. A 403 or 404 keeps Create on the job with generic status and ends deployment checks for this attempt. If the read is unavailable or times out, Create shows any wait reported by the job and checks the deployment again on the next poll. A 401 sends the caller to sign in again. If Create sees job success before opening Deployment, it opens Configuration.

The Latest visible deployment summary shows the version's recorded wait, even with Deployment details folded. A temporary read failure labels a retained wait as last recorded. A refused read clears it.

Admission, status, and retry report the stored client requestId. If absent or different, Create keeps the original request and any confirmed job. meta.requestId identifies each HTTP request. Leaving stops polling, not provisioning. If Create sees that a newer deployment took over, it explains what happened without a retry or a link. The job identifies only the deployment that ended. For a failure, follow the linked version's recovery guidance. After a Stop, deploy when ready. Reconciliation owns startup and activation; later versions use Deploy.

Console parses each reply in apps/controller/src/console/agents/provisioning-job.mts:provisioningJob before apps/controller/src/console/agents/create.mts:submitProvisioningAttempt selects recovery. A malformed present agentId or revisionId makes even a terminal failed reply unknown. The form keeps the accepted job URL and original request, disables Create, and offers Retry without a recovery link. Retry posts to the same job's /retry. packages/occ/src/index.ts:retryAgentProvisioning refuses a changed Agent lifecycle or an existing deployment handoff with 409. After refusal during unknown-outcome recovery, the form enables a resend of the original request ID.

With valid IDs, a failure whose message is absent or not a nonempty string stays confirmed. ProvisioningFailure uses “Provisioning did not complete.” while keeping the failure code and any applicable recovery link. For a confirmed failure with a linked version, follow its recovery guidance.

Dedicated OpenClaw admission requires native worker support and a Sandbox Driver with all required containment facets. The pinned runtime declares native support; custom images still require an operator declaration in Installation startup configuration. packages/occ/src/index.ts:requireDedicatedNativeSupport enforces both requirements. Admission does not prove workload delivery. Sandbox receives the setup identity and Secret reference through HarnessWorkloadRequirements.workspaceSetup; OpenShell runs workspace initialization through ExecSandbox before Harness startup. Stock OpenShell rejects Secret-backed environment projection; the OpenShell flow covers remaining limits and verification-only support.

5. Failures preserve useful outputs

packages/occ/src/state/postgres-state.ts:provisioning

Safe failures retry with a fresh claim/authorization, reusing completed resources. Unresolved writes retain target/ownership evidence; expiry or not-found alone does not permit redispatch. Exception: Configuration creates absent after 90 seconds are resent. Only pre-record Configuration refusals roll back, deleting the written Configuration or marking it for later cleanup.

Provisioning blocks conflicting edits and manual deployment. Stale workers cannot hand off. Stop or Delete saves openclaw.agents.provision.cancelled with cancellation if request audit is enabled or the claim has an audit attempt ID. The event saves workId and available request and attempt IDs.

Agent deletion defers runtime credential removal for one lease without spending attempts. It saves the receipt with deletion. Deploy, Agent update, and runtime-credential requests return 409 until lease expiry, then settle the effect. Namespace deletion waits for queued or running work and effects without receipts. Namespace Secrets and completed Configurations remain.

Requests have no delete API; Agent deletion removes its requests. Agent-less requests remain; for migration 0049 blockers, see legacy bindings.

Debugging and Verification

Search documentation