Webhooks
SimpleClaw’s webhook system lets external services trigger agent runs and send system events to your assistant.
Use Cases
- GitHub - Trigger agent on new issues, PRs, or commits
- Email - Process incoming emails via Gmail Pub/Sub
- Monitoring - Alert agent when services go down
- Calendars - Notify agent of upcoming events
- Custom Services - Integrate any HTTP-capable service
Quick Setup
Enable Webhooks
simpleclaw config set hooks.enabled true --json
simpleclaw config set hooks.token '"your-secret-token"' --json
Restart Gateway
simpleclaw gateway restart
Test the Webhook
curl -X POST http://localhost:18789/hooks/wake \
-H "Authorization: Bearer your-secret-token" \
-H "Content-Type: application/json" \
-d '{"text": "Test event"}'
Configuration
{
"hooks": {
"enabled": true,
"token": "your-secret-token",
"path": "/hooks",
"allowedAgentIds": ["hooks", "main"],
"allowRequestSessionKey": false
}
}
Shared secret for webhook authentication
Base path for webhook endpoints
Restrict which agents can be triggered. Omit or include "*" to allow any agent.
Allow webhooks to specify custom session keys (security risk)
Webhook Endpoints
POST /hooks/wake
Trigger a system event in the main session.
Request:
curl -X POST http://localhost:18789/hooks/wake \
-H "Authorization: Bearer your-secret-token" \
-H "Content-Type: application/json" \
-d '{
"text": "New email from [email protected]",
"mode": "now"
}'
Parameters:
Event description (e.g., “New email received”)
When to trigger: now (immediate) or next-heartbeat (wait for periodic check)
Response:
{
"ok": true,
"message": "Wake event enqueued"
}
POST /hooks/agent
Run an isolated agent task.
Request:
curl -X POST http://localhost:18789/hooks/agent \
-H "Authorization: Bearer your-secret-token" \
-H "Content-Type: application/json" \
-d '{
"message": "Review this pull request: https://github.com/user/repo/pull/123",
"name": "GitHub",
"agentId": "coding",
"deliver": true,
"channel": "slack",
"to": "#engineering"
}'
Parameters:
Prompt or message for the agent
Human-readable hook name (e.g., “GitHub”, “Email”)
Custom session key (requires allowRequestSessionKey: true)
Send response to messaging channel
Target channel: last, whatsapp, telegram, discord, slack, etc.
Recipient ID (phone number, chat ID, channel ID)
Override model (e.g., anthropic/claude-opus-4-6)
Thinking level: off, minimal, low, medium, high, xhigh
Maximum duration for agent run (seconds)
Response:
{
"ok": true,
"sessionKey": "hook:github:pr-123",
"message": "Agent task enqueued"
}
Authentication
Webhooks support two auth methods:
Bearer Token (Recommended)
curl -H "Authorization: Bearer your-secret-token" ...
curl -H "x-simpleclaw-token: your-secret-token" ...
Query string tokens (?token=...) are rejected for security.
External Service Examples
GitHub Webhooks
Create GitHub Webhook
- Go to your repo → Settings → Webhooks
- Click Add webhook
- Set Payload URL:
https://your-gateway.example.com/hooks/agent
- Set Content type:
application/json
- Set Secret: (leave empty for now)
- Select events: Pull requests, Issues
Create Webhook Handler Script
Since GitHub sends complex payloads, create a proxy:// github-webhook-proxy.ts
import express from "express";
const app = express();
app.use(express.json());
app.post("/github", async (req, res) => {
const event = req.headers["x-github-event"];
const payload = req.body;
if (event === "pull_request" && payload.action === "opened") {
const pr = payload.pull_request;
const message = `New PR: ${pr.title}\n\nReview: ${pr.html_url}`;
await fetch("http://localhost:18789/hooks/agent", {
method: "POST",
headers: {
"Authorization": "Bearer your-secret-token",
"Content-Type": "application/json",
},
body: JSON.stringify({
message,
name: "GitHub",
agentId: "coding",
deliver: true,
channel: "slack",
to: "#code-review",
}),
});
}
res.json({ ok: true });
});
app.listen(3000);
Deploy Proxy
Run the proxy and point GitHub webhook to it:https://your-server.com:3000/github
Gmail Pub/Sub
Trigger on incoming emails:
Create Pub/Sub Handler
import { PubSub } from "@google-cloud/pubsub";
const pubsub = new PubSub();
const subscription = pubsub.subscription("gmail-subscription");
subscription.on("message", async (message) => {
const data = JSON.parse(message.data.toString());
// Parse email notification
const emailId = data.emailAddress;
const historyId = data.historyId;
// Fetch email details via Gmail API
const email = await fetchEmailDetails(emailId);
// Trigger agent
await fetch("http://localhost:18789/hooks/agent", {
method: "POST",
headers: {
"Authorization": "Bearer your-secret-token",
"Content-Type": "application/json",
},
body: JSON.stringify({
message: `New email from ${email.from}: ${email.subject}`,
name: "Email",
agentId: "main",
deliver: true,
channel: "telegram",
}),
});
message.ack();
});
Monitoring Alerts
Integrate with Uptime Kuma, Prometheus, etc.:
# When service goes down
curl -X POST http://localhost:18789/hooks/agent \
-H "Authorization: Bearer your-secret-token" \
-H "Content-Type: application/json" \
-d '{
"message": "ALERT: API server is down. Check logs and restart if needed.",
"name": "Monitoring",
"deliver": true,
"channel": "telegram",
"to": "@admin"
}'
Calendar Reminders
Cron job that checks calendar and sends reminders:
#!/bin/bash
# check-calendar.sh
UPCOMING=$(gcalcli agenda --nostarted --tsv | head -1)
if [ -n "$UPCOMING" ]; then
curl -X POST http://localhost:18789/hooks/wake \
-H "Authorization: Bearer your-secret-token" \
-H "Content-Type: application/json" \
-d "{\"text\": \"Upcoming: $UPCOMING\"}"
fi
Schedule with cron:
0 * * * * /path/to/check-calendar.sh
Remote Webhooks
Expose webhooks securely for external services:
Option 1: Tailscale Funnel
simpleclaw config set gateway.tailscale.mode '"funnel"' --json
simpleclaw config set gateway.auth.mode '"password"' --json
simpleclaw config set gateway.auth.password '"strong-password"' --json
Webhook URL:
https://gateway-name.tailnet.ts.net/hooks/agent
Option 2: Reverse Proxy (nginx)
server {
listen 443 ssl;
server_name hooks.example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location /hooks/ {
proxy_pass http://127.0.0.1:18789/hooks/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Security Best Practices
Always use HTTPS and strong tokens for production webhooks.
- Use long, random tokens (32+ characters)
- Never commit tokens to git
- Use environment variables:
export SIMPLECLAW_WEBHOOK_TOKEN="$(openssl rand -hex 32)"
- Restrict allowed agent IDs
- Disable
allowRequestSessionKey unless absolutely needed
- Use Tailscale or VPN for private webhooks
- Enable Gateway password auth for public exposure
Debugging Webhooks
Test Locally
curl -v -X POST http://localhost:18789/hooks/wake \
-H "Authorization: Bearer your-secret-token" \
-H "Content-Type: application/json" \
-d '{"text": "Debug test"}'
Check Gateway Logs
simpleclaw gateway logs --tail 50 | grep webhook
Webhook Request Inspector
Use webhook.site to inspect payloads from external services before routing to SimpleClaw.
Troubleshooting
- Verify token matches config:
simpleclaw config get hooks.token
- Check auth header format:
Authorization: Bearer <token>
- Verify hooks are enabled:
simpleclaw config get hooks.enabled
- Check webhook path:
simpleclaw config get hooks.path
- Check allowed agents:
simpleclaw config get hooks.allowedAgentIds
- View Gateway logs:
simpleclaw gateway logs --tail 50
- Verify channel is configured:
simpleclaw channels status
- Check
deliver: true in webhook payload
- Ensure
to parameter is valid for the channel
Next Steps
Custom Skills
Create tools that webhooks can trigger
Multi-Agent Setup
Route webhooks to specialized agents
Remote Gateway
Expose webhooks from remote server
Automation Guide
Advanced webhook automation patterns