Set up and operate Credential Proxy
Credential Proxy lets an Agent use an approved credential through an enforcing transport without putting provider material in the Agent's configuration. OCC controls access to the execution; the selected Driver enforces the request and credential delivery. For prepared GitHub access, Token Service also maintains the short-lived credential. The setup and verification depend on the selected delivery profile. The architecture walkthrough shows what a child process can request and what it can read in the response.
Use matching OpenShell 0.1.6 components and mandatory pre-credential middleware
for repository enrollment.
A rollout or source registration alone does not establish enforcement. Missing
request hooks are refused before credential release. Older or unqualified
compositions can return 409 REPOSITORY_GIT_SENDER_UNQUALIFIED; do not broaden a
ref-limited grant to bypass that error. The
Credential Proxy reference describes
the delivery contracts.
Choose the path before changing an installation
| Intended use | Requirement and limit |
|---|---|
| Protected static inference | The bundled OpenShell Driver refuses new protected sources, live adoption and new revisions. Existing admitted revisions retain recovery and original-owner cleanup. Other Drivers require qualified whole-execution enforcement; see protected static inference. |
| Prepared GitHub App access | Worker Token Service prepares credentials; OCC authorizes scope and lifetime; Credential Proxy installs and fences delivery. Protected delivery requires a qualified sender. |
| Native prepared Git | A separate explicit Kubernetes/dedicated Codex path without Sandbox or Credential Proxy; it does not provide OpenShell isolation. See native Git. |
For a packaged Driver, select its Sandbox and Credential Proxy capabilities from the same registration. The Driver selection guide shows the Installation settings and profile requirements. Selection establishes which implementation OCC loads; qualification establishes what the installed sender actually enforces.
Use the upgrade procedure for an existing installation, including when a Gateway source or its owner must remain.
Prepare enforcement, trust, and custody
For a reviewed development candidate, follow
local candidate image selection, including
all three immutable OpenShell images, their source commit, and matching charts.
New local protected static-inference launches are retired. The launcher rejects
OCC_DEVELOPMENT_PROTECTED_EGRESS=1 and any presence of
OCC_DEVELOPMENT_OPENSHELL_HOST_GATEWAY_IP before effects, including with
Kubernetes/OpenShell. Unset, empty or 0 protected-egress selections retain ordinary
Gateway authentication. See the retirement notice.
The following bundled static authority configuration preserves existing admitted
revisions and their authorization, withdrawal and cleanup. It does not re-enable
new protected sources, live adoption or new revisions.
For protected static inference, the Installation selects the same Driver ID in
backend[].drivers.credential_proxy and drivers.credential_proxy. A bundled
OpenShell authority selection has this shape:
drivers: credential_proxy: id: openshell-egress configuration: middlewareName: oce-authority authorityScope: execution authority: host: 0.0.0.0 port: 9444 certificatePath: /etc/openclaw/egress/tls/tls.crt privateKeyPath: /etc/openclaw/egress/tls/tls.key issuerPublicKeyPath: /etc/openclaw/egress/issuer/issuer.pub issuer: openshell-gateway:openshell-gateway audience: oce-egress keyId: currentThis is a fragment, not a complete Installation. Match issuer, audience, key ID,
and middleware name to the configured peers. Keep the
OpenShell Backend and Sandbox configuration.
A packaged Driver instead takes configuration through its Sandbox selection;
its matching Credential Proxy selection has an empty configuration.
Either kind can add requestCapacity to size OCC's in-memory request bounds; see
request-time capacity.
The API owns the static authority listener. Development binds only to loopback.
Production needs a reachable host and a certificate covering the Service DNS
name. With Helm, use host: 0.0.0.0 (or ::) and the egressAuthority.port
value. Startup and the upgrade check refuse another host or port, a disabled
egressAuthority, or file paths other than the chart mounts shown above, with
CHART_LISTENER_MISMATCH. The Backend requires HTTPS
with bearer-file or mutual TLS authentication. Register oce-authority under
[[openshell.supervisor.middleware]] with its HTTPS grpc_endpoint, audience,
tls_ca_cert_path, and max_payload_bytes = 4194304. Both peers must support
openshell.supervisor-middleware.http-credential-access.v1 and all five capabilities
required by connected qualification.
Verify the Agent's WSS server trust separately from the controller's Backend mTLS;
an administrator client Secret must never be projected into the Agent. See
trust prerequisites.
With Helm, enable egressAuthority, set its port, tlsSecretName (tls.crt,
tls.key), and issuerSecretName (public.pem). Its clients must select the
actual Gateway and trusted supervisor namespaces and Pod labels. Allow those
peers to reach the authority and resolve DNS. Keep upstream access constrained
to the selected endpoints. The Gateway signing private key stays with the
Gateway; the authority receives its public key. All phases of an exchange must
reach the same authority process; replicated shared exchange state is unavailable.
For prepared GitHub access, use the separate protected repository configuration. Only the worker receives the App signing key and persistent custody key. Do not copy either into Agent configuration. The request-phase worker service and its TLS port are separate from the static API authority above. A missing key, unqualified sender, or unavailable trust path is a stop condition, not a reason to use an ambient token.
Enable Google Workspace requests from a dedicated worker
OCE binds the selected Google source to its host, path, OAuth scopes and plugin release when deploying the Agent. For each request, the OpenShell supervisor sends the HTTP details and deployed binding to a shared guard in the execution cluster. The guard checks the release’s operation map locally. OpenShell substitutes the bearer after approval. Redeploy to apply a new plugin selection. Public Discovery uses no credential.
Set the source’s config.binary to /usr/local/lib/oce/plugins/google/bin/gog
when the installation allows other executables. The checks also cover gog helpers.
Install the guard once for the OpenShell Gateway. Use the execution cluster’s Helm context and the same digest-pinned OCE controller image that deploys the map.
helm upgrade --install oce-plugin-guard deploy/helm/openclaw-plugin-request-guard \ --namespace openshell-system --values guard-values.yaml --set-string image="$OCE_IMAGE"In guard-values.yaml, set tlsSecretName for the guard Service DNS name,
issuerSecretName for the Gateway’s verification key (public.pem), and
issuer and keyId to match the Gateway. Set clients to the Gateway and
supervisor namespace and Pod selectors, as illustrated in the
chart values.
Allow both peers to reach the Service. The guard reads its keys at startup.
Roll its Pods after rotating a Secret in place and update the Gateway’s trusted
CA if it changes. Register the guard on the Gateway:
[[openshell.supervisor.middleware]]name = "oce-plugin-requests"grpc_endpoint = "https://openclaw-enterprise-plugin-request-guard.openshell-system.svc.cluster.local:9445"audience = "urn:openshell:extension:middleware:oce-plugin-requests"tls_ca_cert_path = "/etc/openshell/certs/oce-egress-ca.pem"max_payload_bytes = 4194304timeout = "2s"Restart the Gateway to load the registration. Set
drivers.sandbox.configuration.gateway.managedPluginMiddleware to the same
grpc_endpoint. Select the account, save, and deploy. If the guard is
unreachable, the supervisor denies guarded requests before sending them upstream.
For Gmail, configure gmail.googleapis.com, /gmail/v1/users/me/messages and
gmail.readonly. At a controlled upstream, verify that listing IDs receives the
bearer and fetching an individual message produces no request. To allow more
mapped Gmail operations, explicitly configure a subtree such as /gmail/v1/users/me/**.
Withdraw the source to stop its use
by the running version.
Register, authorize, and deploy an OpenAI static inference source
The bundled OpenShell Driver rejects the source creation, live adoption and
deployment operations below with 409 RESOURCE_CONFLICT, including on existing
installations. These steps require a separately selected Driver
that supports new protected static admission and has qualified static enforcement.
For an existing bundled revision, keep its recorded owner and follow the
upgrade and withdrawal procedures.
Use the built CLI from the
repository root with jq, a ready Namespace, OCC_URL, OCC_NAMESPACE, and a
private OCC_SERVICE_KEY_FILE for an authorized operator.
Obtain whole-execution consent before creating the source: protection covers
sibling processes in that execution, not another execution of the same Agent.
Follow only the openai API-key example in
Register the key, then
return here. Do not use that page's codex-pat variant for this profile, or follow
its copied-key rotation and Agent-deleting cleanup as a live-adoption procedure.
Retain SOURCE_ID and the Secret reference.
With Credential Proxy selected, fresh openai registration is already live:
./bin/occ credential-source get "$SOURCE_ID" -o jsonRequire ownerCapability: credential_gateway, egress.adoption: live and
egress.retention: none. Creation reads the versioned Secret without depositing
a Gateway copy. The CLI's GATEWAY STATUS ready label does not prove such a copy
exists. Keep the Gateway selected: live reads do not transfer ownership. A ready
source alone does not prove installed enforcement.
For an existing unreferenced legacy or narrower source, obtain the same consent, then explicitly adopt live reads instead:
cat > source-adoption.json <<'JSON'{"adoption":"live","authorityScope":"execution"}JSON./bin/occ credential-source update "$SOURCE_ID" --file source-adoption.json./bin/occ credential-source get "$SOURCE_ID" -o jsonThis update requires exact source update and operate on every referenced
Secret, advances the source generation, and retains its Gateway owner. It does
not remove an old Gateway copy: retention: none describes live reads, not past
custody. A bound source cannot take this first cutover.
Follow create the Agent and grant the source
for the dedicated Codex Configuration, Agent request, and exact IAM binding.
Use an authorized native model ID; keep models.providers.codex.baseUrl at
http://127.0.0.1:9. The Agent lists { "sourceId": "$SOURCE_ID" } in
credentialSources and names that source in harnessAuth. The creating operator
and Agent service principal each need exact source operate; the Agent needs
no underlying Secret permission.
./bin/occ agent runtime-credentials provision "$AGENT_ID"DEPLOYMENT_ID="$(./bin/occ agent deploy "$AGENT_ID" -o json | jq -r .id)"./bin/occ agent deployment-status "$AGENT_ID" "$DEPLOYMENT_ID" -o json./bin/occ agent get "$AGENT_ID" -o json./bin/occ agent runtime "$AGENT_ID" -o jsonRequire the requested revision to succeed, become selected, and have a ready runtime. Protected Compute checks the current installation before releasing the workload. Do not bypass pending or failed admission.
Enroll prepared GitHub access
Follow OpenShell repository enrollment
to authorize repositories for a Namespace and select up to 16 on an Agent using
github-repository. The worker prepares a token for exactly that selection;
GitHub permissions and branch rules still apply. No preview option or OCE branch
list is needed. Existing explicit git-write grants retain their ref limits.
The walkthrough includes the separate Gateway model source, worker custody,
registry and mandatory pre-credential middleware setup.
Verify use, loss, and withdrawal
Use model verification to send a fresh nonce through the actual Agent. Its unauthenticated request must fail and its administrator-authenticated request must return the nonce. That denial tests Gateway authentication; it does not prove Credential Proxy enforcement.
For static inference, verify a valid POST to the configured base URL plus
/responses or /chat/completions with the exact admitted model. Attempt the same
request with a different model, and a GET to that inference route; both must be
refused by enforcement. Use a controlled origin with independent request logs,
and record the selected revision, enforcement refusal and no new origin
request. A provider error or an unready Harness does not establish that denial.
Save the successful response, then withdraw the exact source through OCC:
./bin/occ agent credential-withdrawal request "$AGENT_ID" "$SOURCE_ID"./bin/occ agent credential-withdrawal get "$AGENT_ID" "$SOURCE_ID" -o jsonInspect the withdrawal state and reason:
- In-place removal: wait for
revoked. Make a fresh request through the same Agent; record the enforcement refusal and verify that no request reached the controlled origin. - Runtime retirement required: if the reason is
CREDENTIAL_WITHDRAWAL_REQUIRES_RUNTIME_RETIREMENTandrevisionIdnames a version other than the selected one, see withdrawal. For the selected version, ifwithdrawalInProgressistrue, wait for that attempt first: a version that just became selected gets one more attempt. Otherwise follow the retirement procedure. Observe retirement of the exact execution, record the actual withdrawal state and reason, and leave pending custody with its original owner. Do not restart that execution to test a refusal.
An upstream request already sent can finish. Credential Proxy can still withhold a response it has not released; withdrawal cannot recall bytes already released. A withdrawn model source cannot support continued model turns. Restore service with an authorized replacement binding and a new revision; restarting cannot restore withdrawn permission. See withdrawal.
For a git-write grant with an explicit review ref, use the admitted <owner>/<repo>.git path.
Verify discovery (GET /<owner>/<repo>.git/info/refs?service=git-upload-pack),
fetch (POST /<owner>/<repo>.git/git-upload-pack) and a push to the approved review
ref (POST /<owner>/<repo>.git/git-receive-pack). Independently read the written ref. A push to another
ref and DELETE on the same Git route must be refused before reaching the origin.
For github-repository, push and read back its ref in each selected repository.
Verify that the same Agent cannot push to an unselected private repository in the
same installation. Ordinary permitted refs remain available within the selected set.
For installation-wide access, there is no OCE ref allowlist: GitHub controls
membership and permissions. Use an unsupported method such as that DELETE for
the OCE negative check; a GitHub 404 outside membership is not an OCE denial.
Capture the selected revision and correlated enforcement and origin evidence.
The native Git example
applies only to its separate composition.
Withdraw repository access
Token expiry, finite grant/session expiry and standing-approval removal are different checks. For standing access, fetch a commit known to be absent locally after the original token expires, without changing the binding. This checks renewal; it cannot extend a finite grant. Then withdraw while the replacement token and session are still valid:
-
As an Agent administrator, read
GET /namespaces/:namespaceId/agents/:agentId/repository-approvals. -
Select the approval for the current binding. Send
POST /namespaces/:namespaceId/agents/:agentId/repository-approvals/:approvalId/removewith{"expectedGeneration": <that approval's generation>}. This is the approval generation, not the Agent, source or policy generation. Require204; on a conflict, read current approval state before deciding what to do. -
Require a fresh fetch to fail with
access_withdrawnbefore the token/session expires, with no new origin request. An already authorized send may finish. -
Clear the binding using the existing Configuration ID:
bash jq -n --arg configuration "$CONFIGURATION_ID" \ '{configurationId: $configuration, repositoryBindings: []}' > repository-withdrawal.json./bin/occ agent update "$AGENT_ID" --file repository-withdrawal.json
Removing the binding before standing approval is rejected. For finite access, there is no standing approval to remove: use the binding-removal step directly and verify fresh denial.
Require a new model reply in the same conversation after Git removal. Continuity requires verified Git-only policy reduction and healthy independent model access; an explicit model withdrawal or IAM refusal queues retirement of that runtime. Unavailable evidence keeps cleanup pending without repeating the reduction or stopping a healthy Agent. Verify continuity on the selected release; readiness alone does not prove it. Static model sources do not renew tokens; existing Gateway refresh sources use their own rotation procedure.
Diagnose before retrying
| Observation | Action and recovery evidence |
|---|---|
Source failed, absent, or missing credentials |
Read credential-source get and its reason; correct the owning Secret or enrollment. Require a new successful real request, not just ready. |
| Unavailable authority or lost installation | Check peer TLS trust, selected Driver identity, network access, and current runtime. Keep access closed until the current installation is verified. |
| Prepared material is pending or expired | Check the Token Service’s issuer access. An authorized GitHub metadata request can start or join renewal until its deadline. Readiness checks and native Git broker requests still depend on background preparation. |
Refresh reports reauthorize |
Obtain new provider authorization through the source's supported enrollment; do not replay an old refresh token. |
| Installation or send outcome is unknown | Preserve the original operation and custody. Fence the old worker/recipient and reconcile through its owner; do not resend or fabricate success. |
Withdrawal remains pending |
Inspect its reason and withdrawalInProgress; follow the withdrawal recovery procedure. Do not report revocation as complete. |
Public deployment status is not a token-custody ledger. If the selected owner cannot establish whether issuance, installation, or retirement completed, stop the transition and retain its recovery state. Do not edit database rows as an operator workaround. For Git reason codes and log correlation, see adapter diagnostics. Detailed enforcement evidence belongs in qualification procedures.
