Agent Workspace Files Flow
Overview
OCC privately stages authenticated creation inputs: AGENTS.md, SOUL.md,
IDENTITY.md, and USER.md. Compute initializes durable storage before execution;
activation retains completion metadata.
Subsequent file operations authorize the exact active Agent and use its Compute-resolved private endpoint through Envoy Gateway.
Dedicated execution uses Kubernetes Codex; see workspace and launcher boundaries. Dedicated OpenClaw worker execution remains pending.
See two-cluster transport for CP/DP routing.
Entry Points
apps/controller/src/index.ts:createFastifyAppaccepts initial contents throughPOST /namespaces/:namespaceId/agentsand handles liveGETandPUT /namespaces/:namespaceId/agents/:agentId/workspace/files/:name.packages/occ/src/index.ts:createAgentauthorizes creation and persists private setup state;apps/controller/src/worker.tspasses it to Compute on deployment.
Live access requires the Agent's private HTTPRoute and native gateway. Operators configure Envoy Gateway, native trust, and network restrictions through deployment; see the routing contract for transport and credentials. By default, the chart requests a private CA and listener certificate from cert-manager and uses a derived Service DNS hostname. Operators can provide an existing issuer and explicit hostname instead.
Flow
graph TD
subgraph Initial["Creation and first deployment"]
S["Create Agent with initial files"] --> T["Authorize and stage exact-Agent input"]
T --> U["Separate deploy request"]
U --> V["Compute initializes durable workspace"]
V --> W{"Setup complete?"}
W -->|no| X["Block execution; retain pending input"]
W -->|yes| Y["Start runtime; activate revision"]
Y --> Z["Clear staged bytes; retain completion metadata"]
end
A["GET or PUT Agent workspace file"] --> B["OCC authenticates and validates request"]
B --> C["Authorize exact Agent and select active revision"]
C --> D["Compute derives private Agent URL"]
D --> E["OCC reads service key and opens WSS"]
E --> F{"Envoy authenticates OCC?"}
F -->|no| G["503 dependency unavailable"]
F -->|yes| H["Overwrite identity and real IP; route to Agent Service"]
H --> I["Native gateway authorizes service identity"]
I --> J["Native file get or set"]
J --> K{"Result"}
K -->|read| L["Return name and content"]
K -->|write| M["Audit metadata and return name and size"]
K -->|missing| N["404 NOT_FOUND"]
K -->|unavailable| G
K -->|write uncertain| O["Audit UNKNOWN_OUTCOME; never replay"]Execution Trace
1. Creation validates and privately stages the inputs
apps/controller/src/console/agents/create.mjs fills four textareas from
workspace-defaults.mjs and submits their values with WORKSPACE_DEFAULTS_ID.
apps/controller/src/index.ts:createFastifyApp rejects a stale defaults identity;
packages/contracts/src/workspace-setup.ts:normalizeInitialWorkspaceFiles
rejects unknown names, invalid Unicode, NUL, and values above 16 KiB UTF-8.
An absent or empty map creates no setup state. The HTTP create route has a
448 KiB default body limit; a configured controller limit takes precedence.
packages/occ/src/index.ts:createAgent checks Namespace-scoped Agent creation,
exact Configuration read, and the existing binding permissions. Its transaction
creates a stopped Agent and, when keys were supplied, a private workspaceSetups
record keyed by exact Namespace/Agent. No AgentRevision is created. Inputs do
not enter the Agent, Configuration, revision snapshot, public response, or
metadata-only create audit. The original API strings are preserved; Console
textarea values use LF newlines.
2. Deployment initializes storage before execution
apps/controller/src/worker.ts reads private setup state while resolving
ComputeRevisionContext. A selected Driver without supportsWorkspaceSetup
returns WORKSPACE_SETUP_UNSUPPORTED. The existing deployment worker owns the
Agent's serialized startup and passes workspaceSetup to Compute.
The bundled Drivers deliver inputs to the shared
apps/controller/src/drivers/compute/workspace-setup-runtime.ts:WORKSPACE_SETUP_RUNTIME:
Kubernetes uses an owned Secret and an init container on the workspace owner
(Gateway for embedded execution; Harness for dedicated execution); Docker uses a
separate setup container and Agent-owned durable volumes; SSH uses the protected
exact-Agent directory and remote helper. Delivery does not put document strings
in container arguments or environment values. Dedicated Harness startup must
also verify completion before execution. Unsupported workspace placement fails
instead of writing outside the Agent's managed storage. Provider-owned Sandbox
startup cannot carry this init container and rejects workspace setup rather than
dropping initialization.
The runner validates identity, paths, OpenClaw 2026.9.6, and the rendered
template digest against Console defaults.
Defaults identities must match; links and conflicts fail. Without a completion
marker, native setup initializes the workspace and Git without starting the Gateway.
The Kubernetes initializer uses the configured Gateway resource budget because it
loads the native CLI, even when it runs in the dedicated Harness Pod.
It atomically replaces supplied files, including empty strings, when existing
content is absent, stock, or already submitted. It runs native setup
again so native BOOTSTRAP.md lifecycle sees the submitted profile, verifies
the results, then atomically writes .oce-workspace-setup.json.
Matching markers skip application after lost acknowledgement. Incomplete writes retry with the same safety checks. A divergent file or missing/mismatched marker after recorded completion blocks startup; it never authorizes replay over later user edits. Native setup output and failure details are suppressed at the delivery boundary to avoid disclosing contents.
3. Activation clears staged contents and keeps completion metadata
apps/controller/src/worker.ts completes setup in the activation-completion
transaction only after checking the exact active revision and work claim.
workspaceSetups.complete removes document bytes and retains identity and
completion metadata. Drivers remove or replace private delivery bytes with
metadata; subsequent startup verifies the durable workspace marker.
Failed or never-deployed Agents retain pending inputs. Agent deletion removes
the private setup record through packages/occ/src/index.ts:deleteAgent and
Driver cleanup owns the Agent's runtime storage. There is no public setup read
or update endpoint. Creation without supplied keys follows ordinary startup.
Once an Agent is active, live edits follow the independent path below and do
not update the original setup record.
4. Composition configures private access
apps/controller/src/server.mjs:start validates the optional absolute
OCC_GATEWAY_API_KEY_PATH before opening the database. Production and
PostgreSQL development composition bind the selected Compute Driver to
createWorkspaceFilesAccess. The worker uses the same mounted service key
for native node enrollment. Node loads any NODE_EXTRA_CA_CERTS trust
bundle at startup.
For the chart's automatic CA, API and worker Pods wait for cert-manager's generated root Secret and receive only its public certificate. They do not receive the CA signing key. An explicit external issuer uses the configured public CA bundle, or Node's existing trust store when no bundle is configured.
Kubernetes derives endpoints from admitted IDs and Installation routing. Drivers without endpoint support cannot serve workspace files.
5. OCC admits one exact-Agent file operation
apps/controller/src/index.ts:createFastifyApp requires a valid user
session or scoped service API key. Native Agent credentials cannot invoke this
administration surface. GET needs Agent read; PUT needs Agent operate
and, for session callers, passes the browser CSRF boundary. OCC resolves the
active AgentRevision before Compute endpoint resolution.
Only the four names are accepted. PUT accepts only { "content": "..." },
rejects NUL and unpaired UTF-16 surrogates, enforces 16 KiB of UTF-8 content,
and uses a 48 KiB request-body limit. The deadline and disconnect signal cover
admission and native access.
6. Compute resolves a route and OCC loads the current key
apps/controller/src/composition/workspace-files.ts:createWorkspaceFilesAccess
uses ComputeDriver.getGatewayEndpoint(revision) to resolve
wss://<hostname>[:<endpointPort>]/namespaces/<namespaceId>/agents/<agentId>.
Hostname defaults to Helm's Service DNS, port to 443; resolution does not
prove readiness.
kubernetes/index.ts:reconcileGatewayRoute provisions operator routing and a
separate exact /node HTTPRoute and SecurityPolicy for dedicated runtimes.
Only operator routes allow native admin UI subpaths. Both strip authorization
and cookies; node routes also strip administrative identity headers and use
native device authentication.
Preparation repairs the serving revision's node route before candidate activation.
Activation transfers ownership after replacing Gateway. Stop and retirement check
ownership and UID, then remove that revision's endpoint before its policy. See the
node endpoint contract.
prepareWorkspaceNode calls
gateway/node-enrollment-client.ts:createGatewayNodeEnrollment after Gateway
readiness. An Agent-owned Secret per Harness kind keeps the setup code and
device ID; preparation renews expired setup codes.
A Codex Harness reads the code from an optional Secret volume, so
enrollment restarts neither workload (Harness storage).
Other Harnesses are replaced, restarting their Gateway.
- Readiness requires
file.fetch,file.stat,file.write,file.create,dir.list,workspace.memory, andworkspace.skills. Gateway admits these commands before pairing, preserving explicit denies. - The Harness PVC keeps Agent-scoped identity at
/home/node/.openclaw-node(0700, nonroot initializer) across revisions until Agent deletion. AGENT_WITH_NODE_ENTRYPOINTruns nativesetup --baselinebefore supervising Codex and the node undertini. It passes admitted bootstrap options, preserves existing edits, and stops on setup failure. Codex starts at once with the managed PATH; the node waits for a complete code. Neither gets OCC's key.- With the status proxy, a Codex Gateway hot-loads
file-transferfrom an Agent-owned ConfigMap (replacing the Codex plugin runtime); activation awaits OpenClaw's report or fails with its cause. Otherwise the ID is set at Gateway start. Losing it fails. - Default reads cover the enrolled Agent's Harness workspace and managed skill roots. Symlinks are not followed; explicit policies remain authoritative. This serves previews, browsing, bootstrap and outputs.
- Writes remain restricted to owner documents, memory, skills, and staged inbound
files.
file.createpreserves existing files. Reads above 16 MiB retain caller and node limits; command admission does not replace path authorization.
The chart supplies worker credentials/public trust and Compute installs node access to Envoy. Memory uses node duplex with existing native file workers; index and embedding configuration stay on Gateway. Skills uses remote discovery, reads and policy-checked dependency installation. Each host initializes its own image assets; Gateway-provided Skills stay local. See the ownership table. Remote channel menus remain deferred to #241.
Only Harness mounts dedicated workspace/generated-image storage. Gateway sessions use its private PVC; Codex's existing remote-media reader transfers reply artifacts before cleanup. Embedded storage is unchanged. New Harness PVCs use RWO; owned existing RWX claims retain their data. The worker stops predecessors before dedicated preparation and suppresses their maintenance. The storage contract owns downtime and recovery limits. These contracts require matching runtime images; local checks do not prove deployed acceptance.
The API reads the mounted key for each operation, so new connections pick up Secret rotation without a restart. Missing routing, missing or invalid keys, expired deadlines, and unavailable targets fail closed. No URL or credential comes from caller JSON or headers.
7. Envoy authenticates and routes the native connection
apps/controller/src/gateway/workspace-files-client.ts:requestNativeWorkspaceFile opens WSS with only the
service key in x-api-key. The client verifies the server hostname and CA;
there is no leaf pin, device enrollment, native token, or client-certificate
option. It connects as a backend operator with deviceIdentity: null and no
self-asserted scopes.
The Gateway-level Envoy SecurityPolicy verifies and strips the key. The exact
Agent HTTPRoute overwrites x-occ-identity, removes forwarded and native-scope
headers, and sets X-Real-IP to Envoy's direct downstream socket address. It
rewrites the upgrade path to / and selects the existing same-namespace Agent
gateway Service. Namespace attachment labels, route ownership checks, and
restricted Kubernetes RBAC protect this mapping.
Kubernetes Compute renders native trust from Installation
network.gatewayTrustedProxyCidrs, fixing occ-workspace-files with
operator.admin. Conflicting tenant trust settings fail deployment. allowRealIpFallback accepts its genuine nonloopback OCC
connection address even within a shared Pod CIDR. NetworkPolicy admits only
Envoy to the native gateway; the CIDR is not an independent authentication
boundary. Native
hello grants operator.admin; reads also accept operator.read.
8. Native file access returns a bounded result
apps/controller/src/gateway/workspace-files-client.ts:requestNativeWorkspaceFile
The client invokes agents.files.get or agents.files.set for native Agent
main. Reads enforce the response content limit and return
{ name, content }; writes return { name, size }. There is no list, delete,
compare-and-swap, generic RPC, chat bridge, or PostgreSQL file copy.
The Harness PVC retains the dedicated workspace across Pod replacement. Certificate renewal under the same trusted CA affects new WSS connections without restarting OCC. Root-CA replacement follows the trust rotation requirements.
Writes audit only the Agent resource, authorization action, outcome, reason
when present, and file name. If a dispatched write has an unknown outcome,
OCC returns 503 UNKNOWN_OUTCOME, attempts the corresponding audit, and never
replays it. The native client closes in the operation's cleanup path.
Debugging and Verification
- For initial setup failure, check revision/work status and the selected Driver's
support, native release, defaults identity, and durable workspace placement.
WORKSPACE_SETUP_FAILEDintentionally omits document bytes. Do not delete a completion marker to force a replay; missing initialized storage needs operator recovery, not reuse of the creation payload. - A stale
workspaceDefaultsIdrejects creation with409 RESOURCE_CONFLICT; reload the Console create form before submitting again. A create response alone does not prove runtime initialization; verify active revision and live content. - The implementation gates initialization before execution. Structural checks, Driver fixtures, and runtime setup checks each prove different boundaries; the required first-use, retry, and redeploy scenarios need the real workflow integration evidence described in the feature spec.
- For
503 DEPENDENCY_UNAVAILABLE, check the Compute routing settings and key mount, then the Gateway, Certificate, SecurityPolicy, and HTTPRoute status. Check DNS/CA trust and exact NetworkPolicy peers before changing native auth. 400 INVALID_REQUESTindicates a file-name or content-contract violation.403 FORBIDDENcan indicate missing exact-Agent IAM or session PUT CSRF rejection. Granting a native service scope does not change human IAM.- An authenticated native upgrade failure can indicate missing trusted-proxy configuration, a simultaneous token, a loopback real IP, or absent native identity scopes. Do not fix it by inventing a forwarded address.
- Testing separates API conformance, Helm rendering, and the real Envoy/cert-manager/native-runtime proof. A calculated URL, ready proxy, or rendered chart does not establish file writes or model consumption.
