Webhooks
Use webhook destinations when another security system needs high-signal AgentKeeper events without polling. They are the right fit for blocked activity, MCP gateway decisions, investigation...
Use webhook destinations when another security system needs high-signal AgentKeeper events without polling. They are the right fit for blocked activity, MCP gateway decisions, investigation updates, workstation changes, and policy changes.
| Availability | Private preview |
| Plan | Team or Enterprise for non-email destinations |
| Verified | 2026-06-03 |
| Note | Notification destinations are dashboard-managed today. |
You will finish with
- A destination in Settings > Notifications.
- A route that selects event types, severity, and optional filters.
- A signed test delivery in the delivery log.
- A replay path for admins and owners from the dashboard.
For historical sync and backfill, check the current Data API status in API Reference. For hook and collector ingestion, use Runtime Integration API.
Events
| Event | Trigger |
|---|---|
activity.blocked | Runtime Shield blocked a tool call, command, MCP action, file read, file write, or repository operation |
activity.warned | Runtime Shield allowed an action with a warning |
activity.observed | AgentKeeper recorded an allowed activity event |
mcp.blocked | MCP Gateway blocked a tool call |
mcp.warned | MCP Gateway allowed a tool call with a warning |
mcp.drift_detected | MCP server or tool inventory drift was detected |
investigation.created | AgentKeeper opened a new investigation |
investigation.updated | Investigation status, severity, owner, feedback, or evidence changed |
investigation.resolved | An investigation was resolved |
chain.created | Chain-of-events detection opened a new chain |
chain.updated | Chain severity, evidence, or status changed |
workstation.registered | A new workstation appeared |
workstation.offline | A workstation crossed the offline threshold |
policy.changed | Runtime Shield or group policy changed |
otlp.error | OTLP ingestion reported an error |
otlp.cost_anomaly | OTLP usage or cost anomaly was detected |
otlp.tool_rejected | OTLP evidence showed a rejected tool call |
compliance.activity | Anthropic compliance activity was recorded |
posture.grade_dropped | A posture grade dropped |
posture.check_failed | A posture check failed |
exception.requested | A policy exception was requested |
exception.triaged | An exception request entered triage |
exception.decided | An exception request was approved or denied |
exception.expired | An approved exception expired |
exception.context_requested | An approver requested more context |
notification.test | A test notification was sent |
Delivery
AgentKeeper sends webhooks as JSON over HTTPS.
POST https://security.example.com/agentkeeper/webhooks
Content-Type: application/json
X-AgentKeeper-Event: activity.blocked
X-AgentKeeper-Delivery: deliv_01hzw4n
X-AgentKeeper-Timestamp: 2026-05-07T18:22:41.127Z
X-AgentKeeper-Signature: v1=<hmac-sha256>
Example payload:
{
"schema_version": "agentkeeper.event.v1",
"event_id": "runtime_events:evt_01hzw4n",
"event_type": "activity.blocked",
"severity": "high",
"occurred_at": "2026-05-07T18:22:41.127Z",
"detected_at": "2026-05-07T18:22:42.044Z",
"org": {
"id": "org_01hzw4k",
"name": "Example Co"
},
"actor": {
"email": "alex@example.com",
"type": "user"
},
"host": {
"hostname": "dev-laptop-01",
"platform": "macos"
},
"session": {
"id": "sess_01hzw4m"
},
"source": {
"system": "runtime_shield",
"table": "runtime_events",
"id": "evt_01hzw4n"
},
"risk": {
"verdict": "blocked",
"category": "path_policy"
},
"evidence": {
"title": "Runtime Shield blocked Bash",
"summary": "Blocked by Runtime Shield path policy.",
"details": {
"tool_name": "Bash"
}
},
"privacy": {
"redacted": true,
"excluded_fields": []
},
"delivery": {
"destination_id": "dest_01hzw4n",
"delivery_id": "deliv_01hzw4n"
}
}
Signing
Every webhook should be signed with an endpoint-specific secret.
signed_payload = timestamp + "." + raw_body
signature = hex(hmac_sha256(endpoint_secret, signed_payload))
Consumers should reject deliveries when:
- The timestamp is outside a short tolerance window, usually five minutes
- The signature does not match
- The delivery ID was already processed
Retries
AgentKeeper records retryable delivery failures when the destination returns 408, 409, 429, any 5xx status, or a network timeout.
Permanent 4xx failures are not marked retryable except 408, 409, and 429.
Current retry scheduling is transient and short-lived:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | About 1 minute |
| 3 | About 2 minutes |
Replay
Admins and owners can replay a delivery from Settings → Notifications → Deliveries when Notifications V2 storage is available in the environment.
There is no public Data API replay endpoint yet. Do not automate replay against /api/v1/webhook-deliveries/{id}/replay; that route is not implemented.
Recommended Destinations
| Destination | Pattern |
|---|---|
| Generic webhook | Signed HTTPS delivery for custom SOAR and ticketing workflows |
| Slack | Incoming webhook notifications |
| Microsoft Teams | Teams Workflow notifications |
| PagerDuty | Events API v2 |
| Splunk | Send high-signal events to Splunk HEC |
| Jira Cloud | Create issues from notification routes |
| ServiceNow | Create incident records |
When Not To Use Webhooks
Use a tenant-specific export contract or the Data API once enabled when you need:
- Full historical backfill
- Deterministic reconciliation
- Large result sets
- A daily warehouse sync
- Point-in-time exports for audit evidence
Prove it worked
- Create a destination in Settings > Notifications.
- Send the built-in test event and confirm the receiver sees
X-AgentKeeper-Delivery. - Confirm the delivery appears in the delivery log with status
sent. - Replay a delivery from the dashboard if the receiver needs another copy.
If this fails