| date | 2026-03-13 | |||
|---|---|---|---|---|
| author | Onur Solmaz <onur@textcortex.com> | |||
| title | OpenClaw Integration | |||
| tags |
|
This document is the single source of truth for OpenClaw-related behavior in this repository.
Spritz supports running OpenClaw as a per-devbox application surface.
Each devbox runs its own OpenClaw process and is opened through its own /i/{name} route.
When OpenClaw is used as an ACP backend inside Spritz, it should also expose ACP on
the reserved internal port 2529.
- Image and runtime wrapper:
images/examples/openclaw/Dockerfileimages/examples/openclaw/entrypoint.shimages/examples/openclaw/README.md
- UI default preset label/image:
ui/public/app.js
- Helm surface for custom presets:
helm/spritz/values.yaml(ui.presets)helm/spritz/templates/ui-deployment.yaml
The OpenClaw example entrypoint does the following:
- Resolves config path (
OPENCLAW_CONFIG_PATH/OPENCLAW_CONFIG_DIR). - Writes config from one of:
OPENCLAW_CONFIG_JSONOPENCLAW_CONFIG_B64OPENCLAW_CONFIG_FILE
- Sets gateway fields:
gateway.modefromOPENCLAW_GATEWAY_MODE(defaultlocal)gateway.portfromOPENCLAW_GATEWAY_PORT(default8080)gateway.bindfromOPENCLAW_GATEWAY_BIND(defaultlan)
- Ensures
OPENCLAW_GATEWAY_TOKENexists (uses provided token or generates one). - Writes the gateway token to a local token file for ACP adapter use.
- Starts an image-owned ACP adapter on
0.0.0.0:2529unlessOPENCLAW_ACP_ENABLED=false. - Exposes:
- WebSocket ACP on
/ GET /healthzGET /.well-known/spritz-acp
- WebSocket ACP on
- When gateway auth mode is
trusted-proxy, automatically trusts loopback for the internal adapter, injects the required trusted-proxy headers on the adapter's upstream gateway hop, and rewrites the upstream gatewayconnecthandshake into a Control UI operator session without device identity. - Auto-starts OpenClaw when command is default (
sleep infinity), unlessOPENCLAW_AUTO_START=false.
Key implication: direct /i/{name} access with bind=lan expects real gateway auth.
Spritz treats ACP as backend-agnostic.
For OpenClaw to appear in the Spritz ACP chat UI, the instance must answer ACP on:
- port
2529 - WebSocket path
/
Spritz will then:
- discover the agent from the operator by sending ACP
initialize - surface it in
status.acp - proxy browser ACP traffic through
spritz-api
This ACP path is separate from OpenClaw's dashboard and gateway UI.
Today the example image satisfies that contract with a long-lived ACP adapter:
- one long-lived Node ACP server inside the image listens on
2529 - the adapter talks to the local OpenClaw gateway over loopback WebSocket
- ACP WebSocket clients connect to that long-lived adapter instead of spawning a fresh runtime
- the adapter also exposes cheap HTTP health and metadata endpoints for Spritz operator discovery
- if gateway auth mode is
trusted-proxy, the adapter uses a loopback-only header injector so the internal ACP hop satisfies the same trusted-proxy contract as the browser route - in trusted-proxy mode, the adapter impersonates a Control UI-style operator profile without device identity so OpenClaw does not force pairing for the internal ACP client
This keeps the Spritz side backend-agnostic while OpenClaw remains free to add native socket ACP later.
- Works with
bind=lan. - No startup crash.
- Required when route is direct to the devbox without trusted proxy auth headers.
Use this when you want users not to paste gateway tokens manually.
Required OpenClaw config:
gateway.auth.mode: "trusted-proxy"gateway.auth.trustedProxy.userHeader: "<header-name>"gateway.trustedProxies: ["<proxy-ip-or-cidr>", ...]
Required platform behavior:
- All
/i/{name}traffic must pass through an auth proxy. - Proxy must authenticate users and overwrite identity headers.
- No bypass path to the instance service.
auth.mode=nonewithbind=lanis rejected by OpenClaw runtime checks.- Use
noneonly for trusted local/loopback scenarios.
If the target is "no token prompt in Control UI":
- Put instance routes behind an identity-aware proxy.
- Switch OpenClaw auth to
trusted-proxy. - Configure
trustedProxiesto only the proxy source IPs/CIDRs. - Configure
trustedProxy.userHeaderto the forwarded authenticated identity. - Enforce network policy so instance pods are not reachable except through ingress/proxy.
Do not disable auth globally to get tokenless behavior.
Use ui.presets to ship an OpenClaw preset with config injected through env:
ui:
presets:
- name: OpenClaw Devbox
image: spritz-openclaw:latest
description: OpenClaw preinstalled
env:
- name: OPENCLAW_CONFIG_JSON
value: >-
{"gateway":{"mode":"local","bind":"lan","auth":{"mode":"token"}}}For trusted-proxy deployments, replace the auth block accordingly.
Refusing to bind gateway to lan without auth:- invalid config (typically
auth.mode=nonewithbind=lan).
- invalid config (typically
gateway token missingin Control UI:- gateway is in token mode but UI has no token.
- either provide token or move to trusted-proxy model.
origin not allowed:- add the dashboard origin to
gateway.controlUi.allowedOrigins.
- add the dashboard origin to