# Webhook Events Integration Instrument any AI agent with Capsule Security's detection pipeline using a generic HTTP webhook interface for real-time prevention and observability. ## Overview The Webhook Events integration is a platform-agnostic HTTP API that lets you connect **any** AI agent — custom-built agents, orchestration frameworks, internal tools — to Capsule Security. Unlike IDE-specific integrations (Claude Code, Cursor, GitHub Copilot), this integration requires you to add HTTP calls directly in your agent code. Two modes of operation are supported: - **Prevention** (synchronous) — your agent sends an event *before* executing an action and waits for an allow/block decision - **Telemetry** (asynchronous) — your agent fires an event *after* an action completes for observability, without blocking execution ``` Your Agent → HTTP POST → Capsule → Detection Pipeline → Allow/Block Response ``` Use this integration when: - You are building a custom AI agent or orchestration pipeline - Your platform does not have a native Capsule integration - You need programmatic control over when and how events are sent ## Event Types ### Blocking Events Synchronous — your agent waits for an allow/block response before proceeding. | Event | Description | | --- | --- | | `tool_invocation` | Before a tool or action executes | | `user_message` | Before a user prompt is processed | ### Observational Events Fire-and-forget — Capsule responds with `202 Accepted`. | Event | Description | | --- | --- | | `tool_result` | After tool execution completes | | `agent_message` | Agent response text | | `session_start` | Session begins | | `session_end` | Session terminates | ## Prerequisites Before you begin, ensure you have: - A **Capsule Security** account with admin access - An AI agent or application you want to instrument ## Step 1: Generate API Credentials 1. Log in to the **Capsule Security** portal 2. Navigate to **Integrations** and locate **Webhook Events** 3. Click **Install** — Capsule generates a JWT token scoped to your tenant 4. Copy the token and store it securely (it will not be shown again) ## Step 2: Instrument Your Agent Add HTTP calls to your agent code at the appropriate lifecycle points. Refer to the API Reference and Integration Examples sections below. ## API Reference ### Endpoint ``` POST https://{capsule-host}/v1/generic-webhook/hooks/events ``` ### Headers | Header | Required | Description | | --- | --- | --- | | `Authorization` | Yes | `Bearer ` | | `x-correlation-id` | No | Trace ID for request correlation | ### Request Body All events share a common envelope with event-specific fields. #### `tool_invocation` Sent **before** a tool executes. Blocks until Capsule responds. ```json { "event_type": "tool_invocation", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:30:00Z", "agent": { "id": "support-agent", "name": "Customer Support Agent" }, "user": { "email": "user@example.com" }, "tool": { "name": "database_query", "input": { "query": "SELECT * FROM users" } } } ``` #### `user_message` Sent **before** a user prompt is processed. Blocks until Capsule responds. ```json { "event_type": "user_message", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:30:00Z", "agent": { "id": "support-agent", "name": "Customer Support Agent" }, "user": { "email": "user@example.com" }, "message": { "content": "Show me all customer records from the last month" } } ``` #### `tool_result` Sent **after** tool execution completes. Fire-and-forget. ```json { "event_type": "tool_result", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:30:05Z", "agent": { "id": "support-agent", "name": "Customer Support Agent" }, "user": { "email": "user@example.com" }, "tool": { "name": "database_query", "input": { "query": "SELECT * FROM users" }, "output": { "row_count": 42 } } } ``` #### `agent_message` Sent after the agent produces a response. Fire-and-forget. ```json { "event_type": "agent_message", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:30:06Z", "agent": { "id": "support-agent", "name": "Customer Support Agent" }, "user": { "email": "user@example.com" }, "message": { "content": "Here are the 42 customer records from the last month..." } } ``` #### `session_start` Sent when a session begins. Fire-and-forget. ```json { "event_type": "session_start", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:29:55Z", "agent": { "id": "support-agent", "name": "Customer Support Agent" }, "user": { "email": "user@example.com" } } ``` #### `session_end` Sent when a session terminates. Fire-and-forget. ```json { "event_type": "session_end", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:45:00Z", "agent": { "id": "support-agent", "name": "Customer Support Agent" }, "user": { "email": "user@example.com" } } ``` ### Responses #### Blocking Events (`tool_invocation`, `user_message`) **Allowed:** ```json { "apiVersion": "1", "response": { "action": "allow" } } ``` **Blocked:** ```json { "apiVersion": "1", "response": { "action": "block", "reason": "Policy violation: query accesses sensitive table" } } ``` #### Observational Events `202 Accepted` with an empty body. ### Error Codes | Code | Meaning | Recommended Action | | --- | --- | --- | | `400` | Malformed request body | Fix the payload and retry | | `401` | Invalid or expired JWT | Regenerate credentials in the Capsule portal | | `408` | Request timeout | Treat as allow (fail-open) | | `500` | Server error | Treat as allow (fail-open) | ## Integration Examples ### Pre-Execution Guard Call `tool_invocation` before executing a tool. If the response contains `"action": "block"`, deny the action. ```bash curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "tool_invocation", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:30:00Z", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"}, "tool": {"name": "database_query", "input": {"query": "SELECT * FROM users"}} }' ``` **Allowed response:** ```json { "apiVersion": "1", "response": { "action": "allow" } } ``` **Blocked response:** ```json { "apiVersion": "1", "response": { "action": "block", "reason": "Policy violation: query accesses sensitive table" } } ``` ### Telemetry Reporter Fire-and-forget `tool_result` after execution. Capsule responds with `202 Accepted`. ```bash curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "tool_result", "session_id": "sess-abc123", "timestamp": "2026-03-03T10:30:05Z", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"}, "tool": {"name": "database_query", "input": {"query": "SELECT * FROM users"}, "output": {"row_count": 42}} }' ``` ### Full Session Lifecycle A complete sequence showing all event types. ```bash CAPSULE_URL="https://{capsule-host}/v1/generic-webhook/hooks/events" TOKEN="your-jwt-token" SESSION_ID="sess-$(uuidgen)" # 1. Session start curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "session_start", "session_id": "'"$SESSION_ID"'", "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"} }' # 2. User message (blocking) curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "user_message", "session_id": "'"$SESSION_ID"'", "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"}, "message": {"content": "Look up order #12345"} }' # 3. Tool invocation (blocking) curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "tool_invocation", "session_id": "'"$SESSION_ID"'", "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"}, "tool": {"name": "order_lookup", "input": {"order_id": "12345"}} }' # 4. Tool result (fire-and-forget) curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "tool_result", "session_id": "'"$SESSION_ID"'", "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"}, "tool": {"name": "order_lookup", "input": {"order_id": "12345"}, "output": {"status": "shipped", "tracking": "1Z999AA10123456784"}} }' # 5. Agent message (fire-and-forget) curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "agent_message", "session_id": "'"$SESSION_ID"'", "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"}, "message": {"content": "Order #12345 has been shipped. Tracking number: 1Z999AA10123456784"} }' # 6. Session end (fire-and-forget) curl -X POST "$CAPSULE_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "event_type": "session_end", "session_id": "'"$SESSION_ID"'", "timestamp": "'"$(date -u +%Y-%m-%dT%H:%M:%SZ)"'", "agent": {"id": "my-agent", "name": "My Agent"}, "user": {"email": "user@example.com"} }' ``` ## Timeout and Reliability | Setting | Blocking Events | Telemetry Events | | --- | --- | --- | | Server timeout | 10s | 10s | | Recommended client timeout | 10s | 5s | **Always fail-open**: if Capsule is unreachable or returns a server error, allow the action to proceed. Telemetry failures must never block agent operation. ## Verify the Integration 1. Send a `session_start` event followed by a `tool_invocation` event using the examples above 2. Log in to the **Capsule Security** portal 3. Navigate to **Inventory > Agents** and confirm your agent appears 4. Click on the agent and review the audit logs to verify events are captured 5. To view the full conversation, navigate to **Observability** and filter by **Activity Type — Session** ## Troubleshooting | Symptom | Cause | Resolution | | --- | --- | --- | | `401 Unauthorized` | Invalid or expired JWT | Regenerate credentials in **Integrations → Webhook Events** | | Events not appearing in portal | Incorrect endpoint URL or malformed payload | Verify the URL and validate your JSON against the examples above | | Blocking events always returning `allow` | No active policies configured | Configure detection policies in the Capsule portal | | High latency on blocking events | Network distance to Capsule instance | Ensure your agent is in the same region as your Capsule deployment | | `408 Request Timeout` | Capsule processing exceeded timeout | Your agent should treat this as `allow` (fail-open) | ## Security Considerations - Store JWT tokens in a secrets manager or environment variables — never hardcode them in source code - Use HTTPS exclusively — all Capsule endpoints require TLS - Rotate tokens periodically via the Capsule portal - Always fail-open — never let a dropped link to Capsule block your agent's operation ## Support For help with this integration, contact support. ## References - [JWT.io](https://jwt.io) — debug and inspect JWT tokens