10. OpenClaw local dev tool
Run the OpenClaw agent gateway as a companion to the
Mnemose dev stack. It joins the same mnemose Docker bridge network, so the
gateway can reach kernel-broker:8081, postgres:5432, and the OTEL collector
at otel-collector:4318 — and the host reaches the gateway at
http://localhost:18789.
Dev tooling only. There is no production deployment target for OpenClaw. The compose services run under the
clawprofile so they stay out of the defaultmnemoseprofile startup.
Prerequisites
- Docker with the Mnemose compose stack (see 06-local-development.md)
- A gateway auth token (any long random string; the gateway rejects requests without it)
1. Configure .env
Copy .env.example to .env (or edit the existing file) and enable OpenClaw:
OPENCLAW_ENABLED=trueOPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 16)Optional overrides:
# OPENCLAW_IMAGE=openclaw:local # source-built image from an openclaw checkout# OPENCLAW_GATEWAY_PORT=18789 # host-side port for the gateway HTTP API# OPENCLAW_BRIDGE_PORT=18790 # host-side port for the bridge# OPENCLAW_MSTEAMS_PORT=3978 # host-side port for Teams webhookSee docs/setup/environment-variables.md for the full variable reference.
2. Start the stack
docker compose --profile mnemose --profile claw up -dThis starts the usual Mnemose services plus:
| Service | Purpose |
|---|---|
openclaw-gateway | OpenClaw gateway on :18789 (HTTP API + WebSocket) |
openclaw-cli | Interactive CLI; shares the gateway’s network namespace via network_mode: "service:openclaw-gateway" |
3. Verify
curl -H "Authorization: Bearer $OPENCLAW_GATEWAY_TOKEN" http://localhost:18789/healthzdocker compose exec openclaw-cli node dist/index.js --helpdocker compose logs -f openclaw-gatewayThe gateway health check runs every 30s against
http://127.0.0.1:18789/healthz; wait for openclaw-gateway to report
healthy before relying on it.
4. Networking model
┌────────────────────────── host ──────────────────────────┐│ browser / agent CLI ─── http://localhost:18789 ────────┐ │└───────────────────────────────────────────────────────────┘ │ published port 18789 ╔══════════════════════╗ ╔─────╣ mnemose bridge ╠─────╗ │ ╚══════════════════════╝ │ │ │ ┌────────────────┴──────────────┐ ┌───────────────┴──────────┐ │ openclaw-gateway │ │ openclaw-cli │ │ network: mnemose │ │ network_mode: service: │ │ ports: 18789/18790/3978 │ │ openclaw-gateway │ │ extra_hosts: host.docker. │ └───────────────────────────┘ │ internal:host-gateway │ │ can reach: kernel-broker:8081│ │ postgres:5432 │ │ otel-collector:4318 └───────────────────────────────┘- Bridge network — the gateway resolves sibling services by Docker DNS
(
kernel-broker,postgres,otel-collector) because all three share themnemosenetwork. - Bonjour/mDNS — bridge networking drops multicast, so
OPENCLAW_DISABLE_BONJOUR=1(default) keeps the gateway from crash-looping retrying discovery. - Host sidecar services —
extra_hostsmapshost.docker.internalto the host gateway so the bundled local-model providers can reach LM Studio / Ollama on the host. - OTEL — the gateway emits OTLP/HTTP to
otel-collector:4318(outbound), so traces land in Jaeger alongside the rest of the stack.
5. Using the CLI
The CLI runs inside a container that shares the gateway’s network namespace:
docker compose --profile claw exec openclaw-cli node dist/index.js chatBecause openclaw-cli uses network_mode: "service:openclaw-gateway", it
connects to the gateway over localhost:18789 inside the shared namespace —
no extra network config needed.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Gateway not starting; logs show multicast / Bonjour retry spam | mDNS dropped on bridge network | Ensure OPENCLAW_DISABLE_BONJOUR=1 in .env, restart the gateway |
EACCES first-reply failures mentioning /Users/... | Host paths leaked from .env into container-side state resolution | Keep OPENCLAW_STATE_DIR/OPENCLAW_CONFIG_DIR pinned to /home/node/... inside the container (already done in compose) |
fetch http://127.0.0.1:18789/healthz failing in healthcheck | Gateway still booting or bound to loopback only | Wait for the 20s start_period; check --bind arg (defaults to lan) |
Host can’t reach localhost:18789 | Port mapping collision | Change OPENCLAW_GATEWAY_PORT in .env, restart |
error while creating mount source path '<host dir>': chown ... permission denied | Docker Desktop (macOS) cannot chown a bind-mount source under the user’s home; image runs as node | Pre-create the mount source dirs on the host (mkdir -p ~/.openclaw ~/.openclaw/workspace ~/.openclaw-auth-profile-secrets) before up, or point OPENCLAW_CONFIG_DIR / OPENCLAW_AUTH_PROFILE_SECRET_DIR at dirs Docker can manage |
a network with name mnemose exists but was not created by compose | An orphaned mnemose bridge from a previous non-compose setup occupies the name | docker network rm mnemose (only if no containers are attached), then re-up |
Gateway crash-loops with Invalid config at ...openclaw.json: ... Invalid input | The mounted openclaw.json uses schema fields the pinned image version rejects (config version drift) | Run openclaw doctor --fix, or align the config with the image version — pin OPENCLAW_IMAGE to the build your config targets (e.g. openclaw:local from a matching checkout) instead of :latest |