OpenClaws is a hosted personal-agent platform. A user signs in on openclaws.biz, starts a dedicated OpenClaw gateway, manages provider keys and channels from the dashboard, and reaches that agent through the hosted web app plus paired messaging surfaces.
This document describes the current implementation, not the original Railway-era plan.
- Framework: Next.js 16 (App Router)
- Hosting: Vercel for the web app
- Auth: NextAuth.js (Google OAuth)
- Database: Supabase (PostgreSQL)
- Billing: Stripe
- Gateway provisioning: Fly Machines
- Observability: Sentry web + server SDKs, Sentry webhook -> Linear + Paperclip issue creation
- Agent runtime: Dedicated OpenClaw gateway per customer
/- marketing / landing page/login- Google sign-in/dashboard- primary app shell/dashboard/settings- model selection, provider keys, billing, personalization/dashboard/toolkits- Composio-connected integrations/api/instance- create, fetch, and destroy a customer gateway instance/api/gateway/*- gateway control-plane actions used by the dashboard/api/webhooks/sentry- receives Sentry issue webhooks and opens bugs in Linear and Paperclip
Gateway provisioning is handled in src/lib/fly.ts and invoked from src/app/api/instance/route.ts.
For each provisioned customer:
- A Fly app named from
FLY_APP_PREFIX+ a unique slug - A persistent Fly volume mounted at
/data - A dedicated Fly Machine running the OpenClaw gateway image
- A custom subdomain at
https://{slug}.openclaws.biz - A generated gateway token stored in the OpenClaws database
The machine currently runs:
- Image:
ghcr.io/openclaw/openclaw:main - Command path:
node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan
Before boot, provisioning seeds /data/openclaw.json and writes an IDENTITY.md file so the hosted agent introduces itself as an OpenClaws agent rather than a raw upstream model persona.
Provisioning currently sets:
gateway.controlUi.allowedOriginsfor the hosted domainsgateway.controlUi.allowInsecureAuth = falseskills.entries.composio.enabled = true- a minimal default
agents.listentry for the customer agent
OpenClaws passes through user-supplied model keys when available:
ANTHROPIC_API_KEYANTHROPIC_OAUTH_TOKENOPENAI_API_KEY
If the user has not supplied Anthropic credentials and the platform has one configured, OpenClaws mints a short-lived proxy token and points the gateway at the hosted Anthropic proxy.
If Composio is configured, provisioning also:
- passes
COMPOSIO_API_KEY - passes a per-user
COMPOSIO_ENTITY_ID - installs a lightweight
composio-execbridge into the customer gateway - installs a small Composio skill into persistent storage
The provisioned gateway is intentionally exposed through Fly on ports 80/443 and the OpenClaw process binds with --bind lan so Fly’s proxy can reach it.
Provisioning also starts a background loop that repeatedly runs:
openclaw devices approve --latest
This means device pairing is currently optimized for low-friction hosted onboarding rather than strict manual approval.
This is a deliberate managed-hosting exception to the stricter internal OpenClaw posture of loopback-only listeners plus explicit device approval.
Operational upside:
- much simpler end-user onboarding
- fewer support tickets for first-time pairing
- works with Fly’s public routing model
Tradeoff / risk:
- weaker pairing friction than a manually approved device flow
- background approval can hide pairing-state problems instead of surfacing them clearly
- security expectations must be documented accurately so support and engineering do not assume loopback-only behavior
If OpenClaws later tightens posture, the likely path is:
- remove auto-approval loop
- keep hosted ingress but require explicit pairing approval
- make sleeping / waking / approval state visible in the dashboard
The dashboard can call POST /api/gateway/approve-pairing.
Current behavior:
- looks up the customer’s Fly app / machine / gateway token
- verifies the Fly machine is actually running
- executes
openclaw devices approve --latest --jsoninside the machine - returns a specific response when there is no pending request
- returns a specific response when the machine is stopped / sleeping instead of a generic failure
This route still depends on Fly machine exec, so it is inherently more fragile than an in-process control-plane API. If Fly exec is degraded or the machine is asleep, approval can fail even though the underlying gateway config is fine.
OpenClaws initializes Sentry in both client and server contexts:
sentry.client.config.tssentry.server.config.ts
Current safeguards include:
- disabling default PII sending
- masking client-side inputs in session replay
- stripping provider API headers from server breadcrumbs
- scrubbing common API key patterns from client error messages
/api/webhooks/sentry verifies the Sentry HMAC signature and creates bug tickets in:
- Linear for product/project tracking
- Paperclip for agent assignment / triage
Routing is based on the Sentry project slug. For openclaws, bugs are routed into the OpenClaws Linear and Paperclip projects and assigned to the OpenClaws lead agent when configured.
OpenClaws is good at turning thrown errors into tickets, but thinner on customer-visible diagnostics for provisioning and pairing. Support still relies heavily on:
- Fly machine state
- Fly exec health
- Sentry traces/errors
- DB instance rows
The dashboard does not yet expose a rich, first-party support view for why onboarding or pairing failed.
-
Pairing approval should avoid shelling through Fly exec when possible. A first-class control endpoint on the gateway would be more reliable than exec-ing CLI commands into the machine.
-
Provisioning posture needs an explicit product decision. The current hosted setup favors onboarding convenience over strict manual device authorization. That should remain documented unless/until product changes it.
-
Support visibility is still thin. The dashboard should eventually expose machine state, last provisioning error, and pairing status more directly.
-
Keep this file honest. If provisioning or network posture changes, update this document in the same PR.