agentsclimarketplace

Webhook subscriptions

Skill braxtonROSE4/zorro-agent/skills/devops/webhook-subscriptions

The Agent that evolves through use, distills session experience into domain knowledge, then converts knowledge into executable skills.

Install
npx -y skills add braxtonROSE4/zorro-agent --skill webhook-subscriptions

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Create and manage webhook subscriptions for event-driven agent activation. Use when the user wants external services to trigger agent runs automatically.

SKILL.md

5.5 KB, as published. Nobody here has run it

Webhook Subscriptions

Create dynamic webhook subscriptions so external services (GitHub, GitLab, Stripe, CI/CD, IoT sensors, monitoring tools) can trigger Zorro Agent runs by POSTing events to a URL.

Setup (Required First)

The webhook platform must be enabled before subscriptions can be created. Check with:

zorro webhook list

If it says "Webhook platform is not enabled", set it up:

Option 1: Setup wizard

zorro gateway setup

Follow the prompts to enable webhooks, set the port, and set a global HMAC secret.

Option 2: Manual config

Add to ~/.zorro/config.yaml:

platforms:
  webhook:
    enabled: true
    extra:
      host: "0.0.0.0"
      port: 8644
      secret: "generate-a-strong-secret-here"

Option 3: Environment variables

Add to ~/.zorro/.env:

WEBHOOK_ENABLED=true
WEBHOOK_PORT=8644
WEBHOOK_SECRET=generate-a-strong-secret-here

After configuration, start (or restart) the gateway:

zorro gateway run
# Or if using systemd:
systemctl --user restart zorro-gateway

Verify it's running:

curl http://localhost:8644/health

Commands

All management is via the zorro webhook CLI command:

Create a subscription

zorro webhook subscribe <name> \
  --prompt "Prompt template with {payload.fields}" \
  --events "event1,event2" \
  --description "What this does" \
  --skills "skill1,skill2" \
  --deliver telegram \
  --deliver-chat-id "12345" \
  --secret "optional-custom-secret"

Returns the webhook URL and HMAC secret. The user configures their service to POST to that URL.

List subscriptions

zorro webhook list

Remove a subscription

zorro webhook remove <name>

Test a subscription

zorro webhook test <name>
zorro webhook test <name> --payload '{"key": "value"}'

Prompt Templates

Prompts support {dot.notation} for accessing nested payload fields:

  • {issue.title} — GitHub issue title
  • {pull_request.user.login} — PR author
  • {data.object.amount} — Stripe payment amount
  • {sensor.temperature} — IoT sensor reading

If no prompt is specified, the full JSON payload is dumped into the agent prompt.

Common Patterns

GitHub: new issues

zorro webhook subscribe github-issues \
  --events "issues" \
  --prompt "New GitHub issue #{issue.number}: {issue.title}\n\nAction: {action}\nAuthor: {issue.user.login}\nBody:\n{issue.body}\n\nPlease triage this issue." \
  --deliver telegram \
  --deliver-chat-id "-100123456789"

Then in GitHub repo Settings → Webhooks → Add webhook:

  • Payload URL: the returned webhook_url
  • Content type: application/json
  • Secret: the returned secret
  • Events: "Issues"

GitHub: PR reviews

zorro webhook subscribe github-prs \
  --events "pull_request" \
  --prompt "PR #{pull_request.number} {action}: {pull_request.title}\nBy: {pull_request.user.login}\nBranch: {pull_request.head.ref}\n\n{pull_request.body}" \
  --skills "github-code-review" \
  --deliver github_comment

Stripe: payment events

zorro webhook subscribe stripe-payments \
  --events "payment_intent.succeeded,payment_intent.payment_failed" \
  --prompt "Payment {data.object.status}: {data.object.amount} cents from {data.object.receipt_email}" \
  --deliver telegram \
  --deliver-chat-id "-100123456789"

CI/CD: build notifications

zorro webhook subscribe ci-builds \
  --events "pipeline" \
  --prompt "Build {object_attributes.status} on {project.name} branch {object_attributes.ref}\nCommit: {commit.message}" \
  --deliver discord \
  --deliver-chat-id "1234567890"

Generic monitoring alert

zorro webhook subscribe alerts \
  --prompt "Alert: {alert.name}\nSeverity: {alert.severity}\nMessage: {alert.message}\n\nPlease investigate and suggest remediation." \
  --deliver origin

Security

  • Each subscription gets an auto-generated HMAC-SHA256 secret (or provide your own with --secret)
  • The webhook adapter validates signatures on every incoming POST
  • Static routes from config.yaml cannot be overwritten by dynamic subscriptions
  • Subscriptions persist to ~/.zorro/webhook_subscriptions.json

How It Works

  1. zorro webhook subscribe writes to ~/.zorro/webhook_subscriptions.json
  2. The webhook adapter hot-reloads this file on each incoming request (mtime-gated, negligible overhead)
  3. When a POST arrives matching a route, the adapter formats the prompt and triggers an agent run
  4. The agent's response is delivered to the configured target (Telegram, Discord, GitHub comment, etc.)

Troubleshooting

If webhooks aren't working:

  1. Is the gateway running? Check with systemctl --user status zorro-gateway or ps aux | grep gateway
  2. Is the webhook server listening? curl http://localhost:8644/health should return {"status": "ok"}
  3. Check gateway logs: grep webhook ~/.zorro/logs/gateway.log | tail -20
  4. Signature mismatch? Verify the secret in your service matches the one from zorro webhook list. GitHub sends X-Hub-Signature-256, GitLab sends X-Gitlab-Token.
  5. Firewall/NAT? The webhook URL must be reachable from the service. For local development, use a tunnel (ngrok, cloudflared).
  6. Wrong event type? Check --events filter matches what the service sends. Use zorro webhook test <name> to verify the route works.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.