This repo is a serverless-friendly “1:1 conversion” starter that keeps the same UI conventions (Telegram, WhatsApp Cloud API, Textbelt SMS) while replacing the always-on daemon with:
- One public Gateway route:
app/api/claw/route.ts - Durable queues + autonomy using Workflow DevKit (
"use workflow"/"use step") - Composio for integrations (optional, filterable)
- Optional SSH tool (strongly restricted by allowlist)
/health→ redirects to/api/claw?op=health/pair→ redirects to/api/claw?op=pair/webhook→ redirects to/api/claw?op=webhook(internal send/schedule endpoint)/telegram→ Telegram webhook endpoint/whatsapp→ WhatsApp Cloud API webhook endpoint (GET verify + POST messages)/sms→ Textbelt SMS reply webhook endpoint (JSON)
⚠️ Vercel Cron does not support 1-second schedules. We use Workflow sleep("1s") indaemonWorkflow()and a 1-minute Cron watchdog to ensure it’s running.
npm install
cp .env.example .env.local
npm run devUse Upstash Redis (recommended) or Vercel-injected Redis variables.
Set either:
UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKEN, orKV_REST_API_URL+KV_REST_API_TOKEN
If no Redis env vars are set, the app falls back to an in-memory store (works locally only, not durable).
- Create a bot with BotFather, set
TELEGRAM_BOT_TOKEN. - Optional webhook secret: set
TELEGRAM_WEBHOOK_SECRET. - Set webhook URL to:
https://YOUR_DOMAIN/telegram
If using a secret, set Telegram webhook with secret token so the gateway validates it.
Set:
WHATSAPP_VERIFY_TOKENWHATSAPP_ACCESS_TOKENWHATSAPP_PHONE_NUMBER_ID
Configure Meta webhook callback URL to:
https://YOUR_DOMAIN/whatsapp
Set:
Configure Messaging webhook to:
https://YOUR_DOMAIN/sms
Default is "locked":
- Unknown senders receive a pairing code and must reply with:
/pair <CODE>
To auto-allow admin identities, set:
ADMIN_IDENTITIES=telegram:123456789,sms:+15551234567,whatsapp:+15551234567
POST to:
/webhook (redirects to /api/claw?op=webhook)
Headers:
x-claw-secret: <INTERNAL_WEBHOOK_SECRET>
Body example:
{
"action": "send",
"channel": "telegram",
"sessionId": "telegram:123456",
"text": "hello from webhook"
}AUTONOMOUS_MODE:
assistive(default): agent instructed to avoid destructive actions unless requestedfull: agent can act more freely (use with caution)
Run:
npm run workflow:webThis opens the Workflow DevKit UI locally so you can inspect runs/logs.
This starter also implements the ZeroClaw gateway endpoints:
GET /health(public)POST /pairwith headerX-Pairing-Code→ returns a bearer tokenPOST /webhookwithAuthorization: Bearer <token>→ triggers an agent message delivery
Because Vercel is serverless, there is no single permanent "startup". This template generates the one-time 6-digit pairing code the first time it needs it, stores it in Redis, and logs it:
- Look in Vercel Function Logs for:
Pairing code generated: 123456
curl -X POST https://YOUR_DOMAIN/pair \
-H 'X-Pairing-Code: 123456'Response:
{ "ok": true, "token": "..." }curl -X POST https://YOUR_DOMAIN/webhook \
-H 'Authorization: Bearer YOUR_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"message":"Remind me to review PRs in 20 minutes"}'By default, this delivers the agent run to the last active chat session (Telegram/WhatsApp/SMS) seen by the gateway.
If you set any of these env vars, they override pairing for that channel:
TELEGRAM_ALLOWED_USERS=123456789,*WHATSAPP_ALLOWED_NUMBERS=+15551234567SMS_ALLOWED_NUMBERS=+15551234567
Rules:
- empty list = deny all
*= allow all- otherwise = exact match
Visit /ui to configure webhooks, send test messages, and connect Composio integrations.
Set ADMIN_UI_PASSWORD first.