{"id":42931238,"url":"https://github.com/cloudflare/moltworker","last_synced_at":"2026-02-02T22:04:08.274Z","repository":{"id":335304747,"uuid":"1143261428","full_name":"cloudflare/moltworker","owner":"cloudflare","description":"Run OpenClaw, (formerly Moltbot, formerly Clawdbot) on Cloudflare Workers","archived":false,"fork":false,"pushed_at":"2026-01-30T13:21:00.000Z","size":743,"stargazers_count":3212,"open_issues_count":40,"forks_count":414,"subscribers_count":9,"default_branch":"main","last_synced_at":"2026-01-31T09:55:20.669Z","etag":null,"topics":["ai-agents","cloudflare-workers"],"latest_commit_sha":null,"homepage":"https://blog.cloudflare.com/moltworker-self-hosted-ai-agent/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudflare.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-01-27T11:09:39.000Z","updated_at":"2026-01-31T09:54:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/cloudflare/moltworker","commit_stats":null,"previous_names":["cloudflare/moltworker"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cloudflare/moltworker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fmoltworker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fmoltworker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fmoltworker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fmoltworker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudflare","download_url":"https://codeload.github.com/cloudflare/moltworker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudflare%2Fmoltworker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28952575,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T18:30:42.805Z","status":"ssl_error","status_checked_at":"2026-01-31T18:30:19.593Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","cloudflare-workers"],"created_at":"2026-01-30T19:00:56.317Z","updated_at":"2026-01-31T20:00:25.628Z","avatar_url":"https://github.com/cloudflare.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Autonomous Research \u0026 Content Generation","🚀 Deployment \u0026 Operations","Workers","框架与衍生项目","☁️ Hosting \u0026 Deployment","Self-Hosting","Deployment And Setup","Deployment und Betrieb","Agent Infrastructure","Cloudflare Workers (Moltworker) Deep Dive","🦞 OpenClaw Ecosystem","Deployment","Forks \u0026 Variants"],"sub_categories":["AI Assistants","AI","GitHub Issues","Cloud Platforms","Self-Hosted Deployment und Infrastruktur","Sandboxing \u0026 Execution","Cost Optimization Tips","Other Cloud Provider Credits","Nanobot"],"readme":"# OpenClaw on Cloudflare Workers\n\nRun [OpenClaw](https://github.com/openclaw/openclaw) (formerly Moltbot, formerly Clawdbot) personal AI assistant in a [Cloudflare Sandbox](https://developers.cloudflare.com/sandbox/).\n\n![moltworker architecture](./assets/logo.png)\n\n\u003e **Experimental:** This is a proof of concept demonstrating that OpenClaw can run in Cloudflare Sandbox. It is not officially supported and may break without notice. Use at your own risk.\n\n[![Deploy to Cloudflare](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/cloudflare/moltworker)\n\n## Requirements\n\n- [Workers Paid plan](https://www.cloudflare.com/plans/developer-platform/) ($5 USD/month) — required for Cloudflare Sandbox containers\n- [Anthropic API key](https://console.anthropic.com/) — for Claude access, or you can use AI Gateway's [Unified Billing](https://developers.cloudflare.com/ai-gateway/features/unified-billing/)\n\nThe following Cloudflare features used by this project have free tiers:\n- Cloudflare Access (authentication)\n- Browser Rendering (for browser navigation)\n- AI Gateway (optional, for API routing/analytics)\n- R2 Storage (optional, for persistence)\n\n## What is OpenClaw?\n\n[OpenClaw](https://github.com/openclaw/openclaw) (formerly Moltbot, formerly Clawdbot) is a personal AI assistant with a gateway architecture that connects to multiple chat platforms. Key features:\n\n- **Control UI** - Web-based chat interface at the gateway\n- **Multi-channel support** - Telegram, Discord, Slack\n- **Device pairing** - Secure DM authentication requiring explicit approval\n- **Persistent conversations** - Chat history and context across sessions\n- **Agent runtime** - Extensible AI capabilities with workspace and skills\n\nThis project packages OpenClaw to run in a [Cloudflare Sandbox](https://developers.cloudflare.com/sandbox/) container, providing a fully managed, always-on deployment without needing to self-host. Optional R2 storage enables persistence across container restarts.\n\n## Architecture\n\n![moltworker architecture](./assets/architecture.png)\n\n## Quick Start\n\n_Cloudflare Sandboxes are available on the [Workers Paid plan](https://dash.cloudflare.com/?to=/:account/workers/plans)._\n\n```bash\n# Install dependencies\nnpm install\n\n# Set your API key (direct Anthropic access)\nnpx wrangler secret put ANTHROPIC_API_KEY\n\n# Or use AI Gateway instead (see \"Optional: Cloudflare AI Gateway\" below)\n# npx wrangler secret put AI_GATEWAY_API_KEY\n# npx wrangler secret put AI_GATEWAY_BASE_URL\n\n# Generate and set a gateway token (required for remote access)\n# Save this token - you'll need it to access the Control UI\nexport MOLTBOT_GATEWAY_TOKEN=$(openssl rand -hex 32)\necho \"Your gateway token: $MOLTBOT_GATEWAY_TOKEN\"\necho \"$MOLTBOT_GATEWAY_TOKEN\" | npx wrangler secret put MOLTBOT_GATEWAY_TOKEN\n\n# Deploy\nnpm run deploy\n```\n\nAfter deploying, open the Control UI with your token:\n\n```\nhttps://your-worker.workers.dev/?token=YOUR_GATEWAY_TOKEN\n```\n\nReplace `your-worker` with your actual worker subdomain and `YOUR_GATEWAY_TOKEN` with the token you generated above.\n\n**Note:** The first request may take 1-2 minutes while the container starts.\n\n\u003e **Important:** You will not be able to use the Control UI until you complete the following steps. You MUST:\n\u003e 1. [Set up Cloudflare Access](#setting-up-the-admin-ui) to protect the admin UI\n\u003e 2. [Pair your device](#device-pairing) via the admin UI at `/_admin/`\n\nYou'll also likely want to [enable R2 storage](#persistent-storage-r2) so your paired devices and conversation history persist across container restarts (optional but recommended).\n\n## Setting Up the Admin UI\n\nTo use the admin UI at `/_admin/` for device management, you need to:\n1. Enable Cloudflare Access on your worker\n2. Set the Access secrets so the worker can validate JWTs\n\n### 1. Enable Cloudflare Access on workers.dev\n\nThe easiest way to protect your worker is using the built-in Cloudflare Access integration for workers.dev:\n\n1. Go to the [Workers \u0026 Pages dashboard](https://dash.cloudflare.com/?to=/:account/workers-and-pages)\n2. Select your Worker (e.g., `moltbot-sandbox`)\n3. In **Settings**, under **Domains \u0026 Routes**, in the `workers.dev` row, click the meatballs menu (`...`)\n4. Click **Enable Cloudflare Access**\n5. Click **Manage Cloudflare Access** to configure who can access:\n   - Add your email address to the allow list\n   - Or configure other identity providers (Google, GitHub, etc.)\n6. Copy the **Application Audience (AUD)** tag from the Access application settings. This will be your `CF_ACCESS_AUD` in Step 2 below\n\n### 2. Set Access Secrets\n\nAfter enabling Cloudflare Access, set the secrets so the worker can validate JWTs:\n\n```bash\n# Your Cloudflare Access team domain (e.g., \"myteam.cloudflareaccess.com\")\nnpx wrangler secret put CF_ACCESS_TEAM_DOMAIN\n\n# The Application Audience (AUD) tag from your Access application that you copied in the step above\nnpx wrangler secret put CF_ACCESS_AUD\n```\n\nYou can find your team domain in the [Zero Trust Dashboard](https://one.dash.cloudflare.com/) under **Settings** \u003e **Custom Pages** (it's the subdomain before `.cloudflareaccess.com`).\n\n### 3. Redeploy\n\n```bash\nnpm run deploy\n```\n\nNow visit `/_admin/` and you'll be prompted to authenticate via Cloudflare Access before accessing the admin UI.\n\n### Alternative: Manual Access Application\n\nIf you prefer more control, you can manually create an Access application:\n\n1. Go to [Cloudflare Zero Trust Dashboard](https://one.dash.cloudflare.com/)\n2. Navigate to **Access** \u003e **Applications**\n3. Create a new **Self-hosted** application\n4. Set the application domain to your Worker URL (e.g., `moltbot-sandbox.your-subdomain.workers.dev`)\n5. Add paths to protect: `/_admin/*`, `/api/*`, `/debug/*`\n6. Configure your desired identity providers (e.g., email OTP, Google, GitHub)\n7. Copy the **Application Audience (AUD)** tag and set the secrets as shown above\n\n### Local Development\n\nFor local development, create a `.dev.vars` file with:\n\n```bash\nDEV_MODE=true               # Skip Cloudflare Access auth + bypass device pairing\nDEBUG_ROUTES=true           # Enable /debug/* routes (optional)\n```\n\n## Authentication\n\nBy default, moltbot uses **device pairing** for authentication. When a new device (browser, CLI, etc.) connects, it must be approved via the admin UI at `/_admin/`.\n\n### Device Pairing\n\n1. A device connects to the gateway\n2. The connection is held pending until approved\n3. An admin approves the device via `/_admin/`\n4. The device is now paired and can connect freely\n\nThis is the most secure option as it requires explicit approval for each device.\n\n### Gateway Token (Required)\n\nA gateway token is required to access the Control UI when hosted remotely. Pass it as a query parameter:\n\n```\nhttps://your-worker.workers.dev/?token=YOUR_TOKEN\nwss://your-worker.workers.dev/ws?token=YOUR_TOKEN\n```\n\n**Note:** Even with a valid token, new devices still require approval via the admin UI at `/_admin/` (see Device Pairing above).\n\nFor local development only, set `DEV_MODE=true` in `.dev.vars` to skip Cloudflare Access authentication and enable `allowInsecureAuth` (bypasses device pairing entirely).\n\n## Persistent Storage (R2)\n\nBy default, moltbot data (configs, paired devices, conversation history) is lost when the container restarts. To enable persistent storage across sessions, configure R2:\n\n### 1. Create R2 API Token\n\n1. Go to **R2** \u003e **Overview** in the [Cloudflare Dashboard](https://dash.cloudflare.com/)\n2. Click **Manage R2 API Tokens**\n3. Create a new token with **Object Read \u0026 Write** permissions\n4. Select the `moltbot-data` bucket (created automatically on first deploy)\n5. Copy the **Access Key ID** and **Secret Access Key**\n\n### 2. Set Secrets\n\n```bash\n# R2 Access Key ID\nnpx wrangler secret put R2_ACCESS_KEY_ID\n\n# R2 Secret Access Key\nnpx wrangler secret put R2_SECRET_ACCESS_KEY\n\n# Your Cloudflare Account ID\nnpx wrangler secret put CF_ACCOUNT_ID\n```\n\nTo find your Account ID: Go to the [Cloudflare Dashboard](https://dash.cloudflare.com/), click the three dots menu next to your account name, and select \"Copy Account ID\".\n\n### How It Works\n\nR2 storage uses a backup/restore approach for simplicity:\n\n**On container startup:**\n- If R2 is mounted and contains backup data, it's restored to the moltbot config directory\n- OpenClaw uses its default paths (no special configuration needed)\n\n**During operation:**\n- A cron job runs every 5 minutes to sync the moltbot config to R2\n- You can also trigger a manual backup from the admin UI at `/_admin/`\n\n**In the admin UI:**\n- When R2 is configured, you'll see \"Last backup: [timestamp]\"\n- Click \"Backup Now\" to trigger an immediate sync\n\nWithout R2 credentials, moltbot still works but uses ephemeral storage (data lost on container restart).\n\n## Container Lifecycle\n\nBy default, the sandbox container stays alive indefinitely (`SANDBOX_SLEEP_AFTER=never`). This is recommended because cold starts take 1-2 minutes.\n\nTo reduce costs for infrequently used deployments, you can configure the container to sleep after a period of inactivity:\n\n```bash\nnpx wrangler secret put SANDBOX_SLEEP_AFTER\n# Enter: 10m (or 1h, 30m, etc.)\n```\n\nWhen the container sleeps, the next request will trigger a cold start. If you have R2 storage configured, your paired devices and data will persist across restarts.\n\n## Admin UI\n\n![admin ui](./assets/adminui.png)\n\nAccess the admin UI at `/_admin/` to:\n- **R2 Storage Status** - Shows if R2 is configured, last backup time, and a \"Backup Now\" button\n- **Restart Gateway** - Kill and restart the moltbot gateway process\n- **Device Pairing** - View pending requests, approve devices individually or all at once, view paired devices\n\nThe admin UI requires Cloudflare Access authentication (or `DEV_MODE=true` for local development).\n\n## Debug Endpoints\n\nDebug endpoints are available at `/debug/*` when enabled (requires `DEBUG_ROUTES=true` and Cloudflare Access):\n\n- `GET /debug/processes` - List all container processes\n- `GET /debug/logs?id=\u003cprocess_id\u003e` - Get logs for a specific process\n- `GET /debug/version` - Get container and moltbot version info\n\n## Optional: Chat Channels\n\n### Telegram\n\n```bash\nnpx wrangler secret put TELEGRAM_BOT_TOKEN\nnpm run deploy\n```\n\n### Discord\n\n```bash\nnpx wrangler secret put DISCORD_BOT_TOKEN\nnpm run deploy\n```\n\n### Slack\n\n```bash\nnpx wrangler secret put SLACK_BOT_TOKEN\nnpx wrangler secret put SLACK_APP_TOKEN\nnpm run deploy\n```\n\n## Optional: Browser Automation (CDP)\n\nThis worker includes a Chrome DevTools Protocol (CDP) shim that enables browser automation capabilities. This allows OpenClaw to control a headless browser for tasks like web scraping, screenshots, and automated testing.\n\n### Setup\n\n1. Set a shared secret for authentication:\n\n```bash\nnpx wrangler secret put CDP_SECRET\n# Enter a secure random string\n```\n\n2. Set your worker's public URL:\n\n```bash\nnpx wrangler secret put WORKER_URL\n# Enter: https://your-worker.workers.dev\n```\n\n3. Redeploy:\n\n```bash\nnpm run deploy\n```\n\n### Endpoints\n\n| Endpoint | Description |\n|----------|-------------|\n| `GET /cdp/json/version` | Browser version information |\n| `GET /cdp/json/list` | List available browser targets |\n| `GET /cdp/json/new` | Create a new browser target |\n| `WS /cdp/devtools/browser/{id}` | WebSocket connection for CDP commands |\n\nAll endpoints require the `CDP_SECRET` header for authentication.\n\n## Built-in Skills\n\nThe container includes pre-installed skills in `/root/clawd/skills/`:\n\n### cloudflare-browser\n\nBrowser automation via the CDP shim. Requires `CDP_SECRET` and `WORKER_URL` to be set (see [Browser Automation](#optional-browser-automation-cdp) above).\n\n**Scripts:**\n- `screenshot.js` - Capture a screenshot of a URL\n- `video.js` - Create a video from multiple URLs\n- `cdp-client.js` - Reusable CDP client library\n\n**Usage:**\n```bash\n# Screenshot\nnode /root/clawd/skills/cloudflare-browser/scripts/screenshot.js https://example.com output.png\n\n# Video from multiple URLs\nnode /root/clawd/skills/cloudflare-browser/scripts/video.js \"https://site1.com,https://site2.com\" output.mp4 --scroll\n```\n\nSee `skills/cloudflare-browser/SKILL.md` for full documentation.\n\n## Optional: Cloudflare AI Gateway\n\nYou can route API requests through [Cloudflare AI Gateway](https://developers.cloudflare.com/ai-gateway/) for caching, rate limiting, analytics, and cost tracking. AI Gateway supports multiple providers — configure your preferred provider in the gateway and use these env vars:\n\n### Setup\n\n1. Create an AI Gateway in the [AI Gateway section](https://dash.cloudflare.com/?to=/:account/ai/ai-gateway/create-gateway) of the Cloudflare Dashboard.\n2. Add a provider (e.g., Anthropic) to your gateway\n3. Set the gateway secrets:\n\nYou'll find the base URL on the Overview tab of your newly created gateway. At the bottom of the page, expand the **Native API/SDK Examples** section and select \"Anthropic\".\n\n```bash\n# Your provider's API key (e.g., Anthropic API key)\nnpx wrangler secret put AI_GATEWAY_API_KEY\n\n# Your AI Gateway endpoint URL\nnpx wrangler secret put AI_GATEWAY_BASE_URL\n# Enter: https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/anthropic\n```\n\n4. Redeploy:\n\n```bash\nnpm run deploy\n```\n\nThe `AI_GATEWAY_*` variables take precedence over `ANTHROPIC_*` if both are set.\n\n## All Secrets Reference\n\n| Secret | Required | Description |\n|--------|----------|-------------|\n| `AI_GATEWAY_API_KEY` | Yes* | API key for your AI Gateway provider (requires `AI_GATEWAY_BASE_URL`) |\n| `AI_GATEWAY_BASE_URL` | Yes* | AI Gateway endpoint URL (required when using `AI_GATEWAY_API_KEY`) |\n| `ANTHROPIC_API_KEY` | Yes* | Direct Anthropic API key (fallback if AI Gateway not configured) |\n| `ANTHROPIC_BASE_URL` | No | Direct Anthropic API base URL (fallback) |\n| `OPENAI_API_KEY` | No | OpenAI API key (alternative provider) |\n| `CF_ACCESS_TEAM_DOMAIN` | Yes* | Cloudflare Access team domain (required for admin UI) |\n| `CF_ACCESS_AUD` | Yes* | Cloudflare Access application audience (required for admin UI) |\n| `MOLTBOT_GATEWAY_TOKEN` | Yes | Gateway token for authentication (pass via `?token=` query param) |\n| `DEV_MODE` | No | Set to `true` to skip CF Access auth + device pairing (local dev only) |\n| `DEBUG_ROUTES` | No | Set to `true` to enable `/debug/*` routes |\n| `SANDBOX_SLEEP_AFTER` | No | Container sleep timeout: `never` (default) or duration like `10m`, `1h` |\n| `R2_ACCESS_KEY_ID` | No | R2 access key for persistent storage |\n| `R2_SECRET_ACCESS_KEY` | No | R2 secret key for persistent storage |\n| `CF_ACCOUNT_ID` | No | Cloudflare account ID (required for R2 storage) |\n| `TELEGRAM_BOT_TOKEN` | No | Telegram bot token |\n| `TELEGRAM_DM_POLICY` | No | Telegram DM policy: `pairing` (default) or `open` |\n| `DISCORD_BOT_TOKEN` | No | Discord bot token |\n| `DISCORD_DM_POLICY` | No | Discord DM policy: `pairing` (default) or `open` |\n| `SLACK_BOT_TOKEN` | No | Slack bot token |\n| `SLACK_APP_TOKEN` | No | Slack app token |\n| `CDP_SECRET` | No | Shared secret for CDP endpoint authentication (see [Browser Automation](#optional-browser-automation-cdp)) |\n| `WORKER_URL` | No | Public URL of the worker (required for CDP) |\n\n## Security Considerations\n\n### Authentication Layers\n\nOpenClaw in Cloudflare Sandbox uses multiple authentication layers:\n\n1. **Cloudflare Access** - Protects admin routes (`/_admin/`, `/api/*`, `/debug/*`). Only authenticated users can manage devices.\n\n2. **Gateway Token** - Required to access the Control UI. Pass via `?token=` query parameter. Keep this secret.\n\n3. **Device Pairing** - Each device (browser, CLI, chat platform DM) must be explicitly approved via the admin UI before it can interact with the assistant. This is the default \"pairing\" DM policy.\n\n## Troubleshooting\n\n**`npm run dev` fails with an `Unauthorized` error:** You need to enable Cloudflare Containers in the [Containers dashboard](https://dash.cloudflare.com/?to=/:account/workers/containers)\n\n**Gateway fails to start:** Check `npx wrangler secret list` and `npx wrangler tail`\n\n**Config changes not working:** Edit the `# Build cache bust:` comment in `Dockerfile` and redeploy\n\n**Slow first request:** Cold starts take 1-2 minutes. Subsequent requests are faster.\n\n**R2 not mounting:** Check that all three R2 secrets are set (`R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`, `CF_ACCOUNT_ID`). Note: R2 mounting only works in production, not with `wrangler dev`.\n\n**Access denied on admin routes:** Ensure `CF_ACCESS_TEAM_DOMAIN` and `CF_ACCESS_AUD` are set, and that your Cloudflare Access application is configured correctly.\n\n**Devices not appearing in admin UI:** Device list commands take 10-15 seconds due to WebSocket connection overhead. Wait and refresh.\n\n**WebSocket issues in local development:** `wrangler dev` has known limitations with WebSocket proxying through the sandbox. HTTP requests work but WebSocket connections may fail. Deploy to Cloudflare for full functionality.\n\n## Links\n\n- [OpenClaw](https://github.com/openclaw/openclaw)\n- [OpenClaw Docs](https://docs.openclaw.ai/)\n- [Cloudflare Sandbox Docs](https://developers.cloudflare.com/sandbox/)\n- [Cloudflare Access Docs](https://developers.cloudflare.com/cloudflare-one/policies/access/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudflare%2Fmoltworker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudflare%2Fmoltworker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudflare%2Fmoltworker/lists"}