# Claude Inference Hooks

Register Capsule as your AI security server for Anthropic's [inference hooks](https://platform.claude.com/docs/en/manage-claude/inference-hooks) so every governed Claude prompt is checked against your policies before the model answers.

![Claude Enterprise](/assets/claudeenterprise.abc2509c9ee9577ec389ce1cfde33911c23153c563b6461c642dda40384a9066.9c1bb791.png)

## Overview

Inference hooks let Anthropic hold a user's prompt until an external AI security server returns an allow or deny verdict. Capsule is that server:

- **Real-time enforcement** - each governed prompt in claude.ai and Claude Code is evaluated against your policies, and a policy hit denies the prompt before the model sees it
- **Denial feedback** - a denied prompt shows the policy's reason to the user in claude.ai, along with a reference ID you can search on in Capsule
- **Observability** - every frame is also recorded as a user message on the acting user's agent, so blocked and allowed prompts share one timeline


Hooks build on the [Claude Enterprise Compliance API](/guides/claude-enterprise) integration and reuse its per-user agents (`Claude Enterprise/<email>`). Set that integration up first - the hook frame's actor is the same identity that keys those agents.

> **Note:** Inference hooks govern prompts at the moment they are sent. They do not replace the Compliance API integration, which backfills members, the activity feed, and full conversation history.


## Prerequisites

Before you begin, ensure you have:

- An active **Claude Enterprise** plan with **inference hooks** enabled for your organization
- The **Claude Enterprise Compliance API** integration already connected in Capsule
- **Primary owner** access in claude.ai, required to register an AI security server
- At least one **policy** configured in Capsule, otherwise every prompt is allowed


## Step 1: Get Your Endpoint and Token from Capsule

Capsule generates a per-environment endpoint URL and bearer token. These are what you register in claude.ai.

### Steps

1. Log in to the **Capsule Security** portal
2. Click **Integrations** in the left sidebar
3. Open the **Claude Enterprise Compliance API** card. After the Compliance API credentials are saved, the card advances to **Block risky prompts in real time**
4. Copy the **Endpoint** and the **Token** using the copy buttons


> **Note:** The token is scoped to your tenant and environment. Treat it as a credential - anyone holding it can post frames to your endpoint.


## Step 2: Register Capsule in claude.ai

### Steps

1. Go to [claude.ai/admin-settings/inference-hooks](https://claude.ai/admin-settings/inference-hooks), or click **Open claude.ai Inference Hooks** from the Capsule card
2. Create a hook and paste the **Endpoint** from Step 1 into the URL field
3. Add a custom request header:
  - **Name**: `Authorization`
  - **Value**: `Bearer <token>`, using the token from Step 1
4. Save the hook. Anthropic immediately sends a connection test frame to the endpoint, which Capsule answers with an allow verdict


1. Copy the **signing secret** claude.ai shows once the hook is saved. It starts with `whsec_...`


> **Note:** Anthropic only reveals the signing secret after the hook exists, which is why setup is a two-pass round trip. Until you complete Step 3, frames are authenticated by the bearer token alone.


## Step 3: Turn On Signature Verification

### Steps

1. Back in the Capsule card, paste the `whsec_...` value into **Signing secret** and click **Save**
2. Capsule re-issues the bearer token so it carries the secret. Copy the new **Token**
3. Replace the header value in claude.ai with the new token and save the hook again
4. The card shows **Signature verification is on**. Click **Done**


### Rotating the signing secret

Capsule keeps the two most recent secrets active, so frames still signed with the previous one keep verifying while claude.ai finishes a rotation. To rotate, paste the new secret in Capsule, copy the re-issued token back into claude.ai, and save.

## What Capsule ingests

| Inference hook frame | Appears in Capsule as |
|  --- | --- |
| Prompt actor (user id and email address) | **Owner** on the per-user `Claude Enterprise/<email>` agent |
| Latest user turn, including text extracted from attachments | **User message** audit on that agent |
| Session ID | **Session** in Observability, shared with Compliance API conversations |
| Tool use and attachment names | Metadata on the audit entry |
| Policy denial | **Detection**, with the reason and reference ID shown to the user |


Frames are queued and ingested asynchronously so persistence never delays the verdict returned to Anthropic.

## Troubleshooting

| Symptom | Cause | Fix |
|  --- | --- | --- |
| **Signing secret must start with whsec_** | A token or organization ID was pasted into the signing secret field | Copy the `whsec_...` value claude.ai shows after the hook is saved |
| claude.ai reports the hook is **unauthorized** | The `Authorization` header is missing, misspelled, or lacks the `Bearer ` prefix | Re-add the header as `Authorization` with the value `Bearer <token>` |
| claude.ai reports **invalid signature** after Step 3 | The token in claude.ai is still the pre-secret one | Copy the re-issued token from the Capsule card and save the hook again |
| Frames rejected with a signature error, no rotation in progress | The sending or receiving clock is off by more than 5 minutes | Correct the system clock; Anthropic's signed timestamp is checked against a 5 minute tolerance |
| Prompts are never denied | No policy matches, or the acting user has no Claude Enterprise agent yet | Confirm the Compliance API integration has synced, then check the policy's scope and trigger |
| Card shows **Until the signing secret is saved, frames are accepted on the token alone** | Step 3 has not been completed | Paste the signing secret and copy the re-issued token back into claude.ai |


## How It Works

Anthropic POSTs one frame per governed prompt to `POST /v1/claude-inference-hooks/hooks/events` and blocks inference until Capsule answers. Capsule replies with `{"action": "allow"}` or `{"action": "deny", "deny_reason": "...", "reference_id": "..."}`.

Authentication runs in two layers. The bearer token is a per-environment JWT that carries the tenant, the environment, and (after Step 3) the signing secrets, so verification needs no database lookup. When secrets are present, each frame is additionally checked against its [Standard Webhooks](https://www.standardwebhooks.com) signature - an HMAC-SHA256 over `{webhook-id}.{webhook-timestamp}.{raw body}`, compared against the raw bytes Anthropic signed.

Anything but a 200 carrying a parseable verdict is a webhook failure, which never reads as a deny. Anthropic hands the outcome to your organization's failure handling setting instead, and that setting can block the prompt outright; sustained failures also trip a circuit breaker that stops enforcement until your endpoint recovers. Capsule therefore answers 200 with a verdict on every decided path, allows frame types it does not recognise, and allows when analysis is unavailable, so a Capsule-side problem never decides the outcome for your users. A prompt is denied only on an explicit policy hit.

`deny_reason` is truncated to 500 characters and is what the end user sees on a block. `reference_id` is truncated to 50 characters and restricted to the characters Anthropic accepts; it is never shown to the user. Capsule sends the frame's `request_id`, so a denial in the claude.ai Activity Feed joins straight back to the matching Capsule violation.

## Support

For help with this integration:

- **Email**: support@capsule.security
- **Include**: Your tenant ID, your Anthropic Organization ID, and the reference ID from any unexpected denial


## References

- [Inference hooks overview](https://platform.claude.com/docs/en/manage-claude/inference-hooks)
- [Claude Enterprise Compliance API guide](/guides/claude-enterprise)
- [Standard Webhooks specification](https://www.standardwebhooks.com)