Reference

Webhooks

Open Astra can deliver real-time event notifications to external services via webhooks. Register endpoint URLs to receive events for agent completions, memory updates, approval requests, heartbeat triggers, and more.

Registering a webhook

Send a POST /webhooks request with the target URL, a list of event types to subscribe to, and an optional signing secret. If a secret is provided it is used to sign every delivery with HMAC-SHA256.

bash
curl -X POST http://localhost:3000/webhooks \
  -H "Authorization: Bearer ${JWT_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-service.example.com/hooks/astra",
    "events": ["agent.completed", "approval.requested"],
    "secret": "your-signing-secret"
  }'

Event types

EventWhen firedKey payload fields
agent.completedAn agent turn finishes successfullyagentId, sessionId, durationMs, usage, toolCallCount
agent.failedAn agent turn ends with an unhandled erroragentId, sessionId, error, consecutiveFailures
approval.requestedA tool requires human approval before executionrequestId, agentId, tool, params, expiresAt
memory.propagatedA memory entry is promoted across tiersentryId, fromTier, toTier, userId, workspaceId
heartbeat.firedA scheduled heartbeat run completesheartbeatId, source, agentId, durationMs, itemCount
swarm.finishedAll agents in a swarm complete their tasksswarmId, agentCount, totalDurationMs, results

Payload format

Every webhook delivery is a POST request with a JSON body. The envelope always contains event, timestamp, and data. The shape of data matches the key payload fields documented in the event types table above.

json
{
  "event": "agent.completed",
  "timestamp": "2025-08-14T10:32:00.000Z",
  "data": {
    "agentId": "research-agent",
    "sessionId": "sess_abc123",
    "durationMs": 4210,
    "usage": { "promptTokens": 1200, "completionTokens": 340 },
    "toolCallCount": 3
  }
}

Signature verification

When a webhook is registered with a secret, Open Astra includes an X-Astra-Signature header on every delivery. The value is sha256=<hmac> where the HMAC is computed over the raw request body using the secret as the key. Always verify this header before processing a delivery.

typescript
import { createHmac } from 'crypto';

function verifySignature(rawBody: string, signature: string, secret: string): boolean {
  const expected = 'sha256=' + createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');
  return signature === expected;
}

// In your webhook handler
app.post('/hooks/astra', (req, res) => {
  const sig = req.headers['x-astra-signature'] as string;
  if (!verifySignature(req.rawBody, sig, process.env.WEBHOOK_SECRET!)) {
    return res.status(401).send('Invalid signature');
  }
  // process event...
  res.status(200).send('ok');
});

Retry policy

If your endpoint returns a non-2xx status or does not respond within 10 seconds, Open Astra retries the delivery using exponential backoff. After 5 failed attempts the delivery is moved to the dead-letter queue and no further retries are made.

AttemptDelay before retry
1st retry30 seconds
2nd retry2 minutes
3rd retry10 minutes
4th retry30 minutes
5th retry (final)2 hours

Inbound webhook verification (HMAC)

If you route external webhooks (e.g. from Slack, or your own services) into the Astra gateway, you can protect any endpoint with the built-in hmacVerify middleware. It performs a timing-safe HMAC-SHA256 (or SHA1) comparison so that unsigned or tampered requests are rejected with 401 before reaching any handler.

Configure the header name, algorithm, and prefix to match the sending service's convention:

ServiceHeaderPrefixAlgorithm
Slackx-slack-signaturev0=SHA-256
Astra (outbound)x-astra-signaturesha256=SHA-256

Managing webhooks

MethodPathDescription
GET/webhooksList all registered webhooks (secrets are stripped from responses)
DELETE/webhooks/:idDelete a webhook and stop all future deliveries
POST/webhooks/:id/testSend a test payload to the endpoint to verify connectivity and signature verification