Skip to main content

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

1

Enable Webhooks

simpleclaw config set hooks.enabled true --json
simpleclaw config set hooks.token '"your-secret-token"' --json
2

Restart Gateway

simpleclaw gateway restart
3

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
  }
}
enabled
boolean
required
Enable webhook endpoints
token
string
required
Shared secret for webhook authentication
path
string
default:"/hooks"
Base path for webhook endpoints
allowedAgentIds
string[]
Restrict which agents can be triggered. Omit or include "*" to allow any agent.
allowRequestSessionKey
boolean
default:"false"
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:
text
string
required
Event description (e.g., “New email received”)
mode
string
default:"now"
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:
message
string
required
Prompt or message for the agent
name
string
Human-readable hook name (e.g., “GitHub”, “Email”)
agentId
string
default:"main"
Target agent ID
sessionKey
string
Custom session key (requires allowRequestSessionKey: true)
wakeMode
string
default:"now"
now or next-heartbeat
deliver
boolean
default:"true"
Send response to messaging channel
channel
string
default:"last"
Target channel: last, whatsapp, telegram, discord, slack, etc.
to
string
Recipient ID (phone number, chat ID, channel ID)
model
string
Override model (e.g., anthropic/claude-opus-4-6)
thinking
string
Thinking level: off, minimal, low, medium, high, xhigh
timeoutSeconds
number
Maximum duration for agent run (seconds)
Response:
{
  "ok": true,
  "sessionKey": "hook:github:pr-123",
  "message": "Agent task enqueued"
}

Authentication

Webhooks support two auth methods:
curl -H "Authorization: Bearer your-secret-token" ...

Custom Header

curl -H "x-simpleclaw-token: your-secret-token" ...
Query string tokens (?token=...) are rejected for security.

External Service Examples

GitHub Webhooks

1

Create GitHub Webhook

  1. Go to your repo → SettingsWebhooks
  2. Click Add webhook
  3. Set Payload URL: https://your-gateway.example.com/hooks/agent
  4. Set Content type: application/json
  5. Set Secret: (leave empty for now)
  6. Select events: Pull requests, Issues
2

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);
3

Deploy Proxy

Run the proxy and point GitHub webhook to it:
https://your-server.com:3000/github

Gmail Pub/Sub

Trigger on incoming emails:
1

Set Up Gmail Pub/Sub

Follow the Gmail Pub/Sub guide to configure email notifications.
2

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

Build docs developers (and LLMs) love