Agent skill

Crusoe Cloud Webhooks Skill

Receive and verify Crusoe Cloud webhooks (Notifications service, delivered via Svix). Use when setting up a Crusoe Cloud webhook handler, debugging svix-id / svix-timestamp / svix-signature verification, or handling Crusoe notifications such as resource.automated_remediation (Command Center / AutoClusters node replacement), resource health, budget alerts, organization and Managed AI events.

Install this skill

npx skills add hookdeck/webhook-skills --skill crusoe-webhooks


Crusoe Cloud's Notifications service routes alerts (resource health and automated remediation from Command Center, budget alerts, organization changes, Managed AI events) to email, the console, Slack and generic webhook endpoints. Webhook endpoints are managed in a Svix dashboard opened from the Crusoe Cloud Console.

When to Use This Skill

  • How do I receive Crusoe Cloud webhooks?
  • How do I verify Crusoe webhook signatures?
  • How do I handle Crusoe resource.automated_remediation (node replacement) notifications?
  • How do I route Crusoe budget alerts or resource health alerts to my own service?
  • Why is my Crusoe webhook signature verification failing?

Verification (core)

Inferred from Svix, not quoted from Crusoe. Crusoe's docs say webhooks are configured "on the Svix dashboard" but publish no verification details. The headers, algorithm and whsec_ secret format below are Svix defaults.

Each webhook carries svix-id, svix-timestamp (Unix seconds) and svix-signature (space-separated v1,<base64> entries). The signature is base64 HMAC-SHA256 over ${svix-id}.${svix-timestamp}.${raw body}, keyed with the base64-decoded secret after whsec_. Use the official svix SDK (Node and Python), which also enforces a 5-minute timestamp window and handles secret rotation:

import { Webhook } from 'svix'; // svix 2.8+ is ESM-only

const wh = new Webhook(process.env.CRUSOE_WEBHOOK_SECRET); // "whsec_..."
wh.verify(rawBody, {                                       // raw Buffer/string, NOT parsed JSON
  'svix-id': req.headers['svix-id'],
  'svix-timestamp': req.headers['svix-timestamp'],
  'svix-signature': req.headers['svix-signature'],
}); // throws WebhookVerificationError; returns undefined in svix 2.x
const payload = JSON.parse(rawBody.toString('utf8'));     // parse only after verifying

Python: from svix.webhooks import Webhook and call Webhook(secret).verify(raw_body, headers) the same way.

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

Crusoe documents one exact event type string; the rest are console categories you subscribe to per endpoint in the Svix dashboard.

Event / categoryDescription
resource.automated_remediationAutomated remediation of a node (e.g. Node Replacement after XID 79: GPU has fallen off the bus)
Resource HealthHardware issues and automated remediation on your nodes
User Account and Organization ManagementChanges to organization account settings and access controls
BillingBudget alerts when a budget threshold is exceeded
Managed AIManaged AI updates; self-serve deployment created / scaled / deleted

Parse defensively. Crusoe says the body "varies by event type", and the documented resource.automated_remediation example has no type field. The examples read type / event_type when present, otherwise recognise remediation payloads by workflow_type + resource_id, and log anything else without failing.

Environment Variables

CRUSOE_WEBHOOK_SECRET=whsec_xxxxx   # endpoint signing secret from the Svix dashboard

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 crusoe --path /webhooks/crusoe

Add the tunnel URL as a Webhook endpoint (Console → bell icon → All Notifications → Manage Slack/Webhook → Add Endpoint).

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Oct 28, 2026

View on GitHub →