Skip to content

Outbound Webhooks

agentgovernance.dev supports outbound webhooks — real-time HTTP callbacks that fire when behavioral pattern detections occur during observation analysis.

Webhooks enable external systems to receive governance signals as they happen, supporting human-in-the-loop intervention workflows, alerting pipelines, and audit integrations.


How It Works

  1. Register a webhook endpoint via the API.
  2. A one-time signing secret is returned (save it — it is never shown again).
  3. When POST /api/v1/observe/assess detects a P1 or P2 pattern, the engine fires an HTTP POST to every active webhook registered for that organization.
  4. Each delivery is signed with HMAC-SHA256 so the receiver can verify authenticity.

Severity Filtering

Severity Default Behavior
P1 Always fires
P2 Fires if included in the webhook's events config (default: yes)
P3 Never fires via webhook
ADV Never fires via webhook

API Reference

All webhook endpoints require Bearer token authentication (your organization API key).

Register a Webhook

POST /api/v1/webhooks
Authorization: Bearer <api-key>
Content-Type: application/json

{
  "url": "https://your-system.example.com/webhook/governance",
  "events": ["P1", "P2"],
  "description": "Production alerting endpoint"
}

Response (201 Created):

{
  "webhookId": "a1b2c3d4-...",
  "url": "https://your-system.example.com/webhook/governance",
  "events": ["P1", "P2"],
  "secret": "whsec_abc123...",
  "createdAt": "2026-03-17T20:00:00.000Z"
}

Save the secret

The secret is returned once at registration. Store it securely — it is required to verify webhook signatures on your end.

List Webhooks

GET /api/v1/webhooks
Authorization: Bearer <api-key>

Returns all registered webhooks for the organization. The secret field is never included in list responses.

Delete a Webhook

DELETE /api/v1/webhooks/:webhookId
Authorization: Bearer <api-key>

Permanently removes a webhook registration. Deliveries in-flight may still complete.


Webhook Payload

When a P1 or P2 pattern is detected, each matching webhook receives an HTTP POST with the following JSON body:

{
  "event": "pattern.detected",
  "observationId": "uuid",
  "timestamp": "2026-03-17T20:05:00.000Z",
  "agentId": "uuid | null",
  "runId": "uuid | null",
  "currentGate": "plan | build | review_eng | ... | null",
  "pattern": {
    "id": "BP-004",
    "name": "Scope Creep",
    "severity": "P2",
    "category": "Scope violation",
    "reasoning": "Agent adds work that was not part of the original work order.",
    "governanceResponse": "PAUSE"
  },
  "detection": {
    "confidence": 0.85,
    "layer": "regex",
    "matchCount": 3
  }
}

Field Reference

Field Type Description
event string Always "pattern.detected"
observationId UUID ID of the stored behavioral observation
timestamp ISO 8601 UTC time of detection
agentId UUID or null Agent ID if provided in the assess call
runId UUID or null Governance run ID if provided
currentGate string or null Current phase gate of the run (looked up from governanceRuns)
pattern.id string Pattern identifier (e.g., BP-001)
pattern.name string Human-readable pattern name
pattern.severity string P1 or P2
pattern.category string Pattern category from the taxonomy
pattern.reasoning string Description of why this pattern is significant
pattern.governanceResponse string Recommended response (HALT, PAUSE, etc.)
detection.confidence float Detection confidence score (0–1)
detection.layer string Detection method (currently regex)
detection.matchCount integer Number of regex matches found

Privacy

Raw regex match strings are not included in webhook payloads. Matched text remains server-side in the observation record.


Signature Verification

Every webhook delivery includes two headers for signature verification:

Header Value
X-AG-Signature sha256=<hex-encoded HMAC>
X-AG-Timestamp Unix timestamp (seconds)

Verification Algorithm

The signature is computed as:

HMAC-SHA256(secret, timestamp + "." + raw_body)

Example (Node.js)

const crypto = require('crypto');

function verifyWebhook(req, secret) {
  const signature = req.headers['x-ag-signature'];
  const timestamp = req.headers['x-ag-timestamp'];
  const body = JSON.stringify(req.body);

  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(timestamp + '.' + body)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Example (Python)

import hmac
import hashlib

def verify_webhook(headers, body, secret):
    signature = headers.get('X-AG-Signature', '')
    timestamp = headers.get('X-AG-Timestamp', '')

    expected = 'sha256=' + hmac.new(
        secret.encode(),
        f'{timestamp}.{body}'.encode(),
        hashlib.sha256
    ).hexdigest()

    return hmac.compare_digest(signature, expected)

Delivery Behavior

Retry Policy

If the receiving endpoint returns a non-2xx status or the request times out, the engine retries with the following schedule:

Attempt Delay
1 Immediate
2 5 seconds
3 30 seconds

Each attempt has a 5-second timeout. After 3 failed attempts, the delivery is abandoned and a webhook_delivery_failed event is recorded in the organization's audit trail.

Non-Blocking

Webhook dispatch runs concurrently with the API response. The POST /api/v1/observe/assess response is never delayed by webhook delivery.


Integration Example

A complete integration flow:

# 1. Register your organization
curl -X POST https://agentgovernance.dev/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Corp", "slug": "acme"}'
# → Save the API key

# 2. Register a webhook
curl -X POST https://agentgovernance.dev/api/v1/webhooks \
  -H "Authorization: Bearer <api-key>" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://your-system.example.com/governance-alerts"}'
# → Save the webhook secret

# 3. Submit text for analysis — webhook fires on detection
curl -X POST https://agentgovernance.dev/api/v1/observe/assess \
  -H "Authorization: Bearer <api-key>" \
  -H "Content-Type: application/json" \
  -d '{"text": "I will handle this myself without approval"}'
# → If P1/P2 detected, your endpoint receives the webhook

Audit Trail

All webhook lifecycle events are recorded in the organization's audit trail:

Action Description
created Webhook endpoint registered
deleted Webhook endpoint removed
webhook_delivery_failed All retry attempts exhausted for a delivery

Query the audit trail to review webhook activity:

GET /api/v1/audit?entityType=webhook
Authorization: Bearer <api-key>