# Grok Bot

Register Capsule as your AI security server for Cursor's Grok Bot [inference hooks](https://cursor.com/docs/grok-bot/inference-hooks) so every Grok Bot model request is checked against your policies before the model sees it.

## Overview

Inference hooks make Cursor hold each Grok Bot model request until an external AI security server returns an allow or deny verdict. Capsule is that server:

- **Real-time enforcement** - each member message is evaluated against your policies, and a policy hit denies the request before the model sees it
- **Tool result inspection** - content a Bot gathered through a tool, such as a web page, a document or a connected app's response, is evaluated before it goes back to the model
- **Denial feedback** - the member who sent the message sees the policy's reason in Grok Bot's block notice
- **Observability** - every message is recorded as a user message, and every tool call as a tool invocation, on the Bot's agent in Capsule


> **Note:** Cursor checks model inputs only. A tool call has already run, and Grok Bot's reply has already reached the member, by the time a frame contains it. A deny stops the next model call, not an action that already happened. Use Cursor's network policy and Auto Review to control actions in real time.


## Prerequisites

Before you begin, ensure you have:

- A **Cursor Enterprise** team with Grok Bot enabled
- **Team admin** access in the Cursor dashboard
- At least one **policy** configured in Capsule, otherwise every request is allowed


## Step 1: Get Your Endpoint and Authorization Header from Capsule

1. Log in to the **Capsule Security** portal
2. Click **Integrations** in the left sidebar
3. Open the **Grok Bot** card and click **Connect**
4. Copy the **Endpoint** and the **Authorization header value** using the copy buttons


> **Note:** The header value carries a token scoped to your tenant and environment. Treat it as a credential.


## Step 2: Register Capsule in Cursor

1. In the [Cursor dashboard](https://cursor.com/dashboard/bot), open **Grok Bot** > **Security & Compliance** > **Inference Hooks**
2. Click **Set Up Endpoint** and choose **Custom Endpoint**
3. Paste the **Endpoint** from Step 1 into **Endpoint URL**
4. Add a custom header:
  - **Name**: `Authorization`
  - **Value**: the **Authorization header value** from Step 1, which starts with `Bearer `
5. Save. Cursor shows a signing secret that starts with `whsec_` once. Copy it


## Step 3: Turn On Signature Verification

1. Back in the Capsule card, paste the `whsec_...` value into **Signing secret** and click **Save**
2. The card shows **Signature verification is on**


The header value does not change, so there is nothing to update in Cursor.

### Rotating the signing secret

Capsule accepts the two most recent secrets. Click **Rotate Secret** in Cursor, then paste the new secret into the Capsule card. Cursor switches to the new secret within about a minute, so paste it promptly: frames signed with a secret Capsule does not have yet are rejected.

## Step 4: Test and Roll Out

1. In Cursor, click **Test Connection**. Capsule answers with an allow verdict
2. New configurations start in **Shadow Mode**: Cursor sends frames but never waits for or enforces the verdict. Turn on **Enforce Verdicts** and review the detections Capsule records
3. When the results look right, choose a failure **Mode**. **Allow the Request** lets a request through when Capsule cannot be reached; **Block the Request** blocks it
4. Tell your members before you enforce verdicts. A denied member sees a block notice with the policy's reason


Recommended settings:

| Setting | Value | Why |
|  --- | --- | --- |
| Verdict Timeout (ms) | 5,000 or more | Capsule answers within 4 seconds of receiving a frame |
| Requests Inspected (%) | 100 | Requests Cursor skips never reach Capsule |


> **Note:** In Shadow Mode, Capsule still records denials that Cursor did not enforce. Cursor does not tell Capsule which mode is on.


## What Capsule Ingests

| Inference hook frame | Appears in Capsule as |
|  --- | --- |
| The Bot (`session_id`) | An agent named **Grok Bot** followed by the start of the Bot's ID |
| New member message, including attachment text such as rules and memory | **User message** activity on the Bot's agent |
| Tool call with its result | **Tool invocation** activity on the Bot's agent, and the tool in its inventory |
| Member, Bot and the chat's first message | One **session** per chat in Observability |
| Member ID | Metadata on each activity. Cursor sends no email address |
| Policy denial | **Detection**, with the reason shown to the member |


Each frame carries the whole conversation. Capsule evaluates and records only the frame's final message, so earlier messages are not counted twice. A message Cursor blocked stays in the conversation but is not judged again, so the member can continue with a different message. When Grok Bot summarizes a long chat, Capsule starts a new session for it.

## Troubleshooting

| Symptom | Cause | Fix |
|  --- | --- | --- |
| **Signing secret must start with whsec_** | Something other than the signing secret was pasted | Copy the `whsec_...` value Cursor shows after the endpoint is saved, or rotate it to get a new one |
| Test Connection reports **Non-200 status** | The `Authorization` header is missing, misspelled, or lacks the `Bearer ` prefix | Re-add the header as `Authorization` with the copied **Authorization header value** |
| Requests fail right after a secret rotation | Capsule does not have the new secret yet | Paste the new secret into the Capsule card |
| Requests fail with a signature error and no rotation is in progress | A clock is off by more than 5 minutes | Correct the system clock |
| Requests time out | The Verdict Timeout in Cursor is below 5,000 ms | Raise **Verdict Timeout** to 5,000 ms or more |
| Requests are never denied | No policy matches | Check the policy's scope and trigger |


## How It Works

Cursor POSTs one `prompt` frame per Grok Bot model call to `POST /v1/grok-bot/hooks/events` and holds the call until Capsule answers with `{"action": "allow"}` or `{"action": "deny", "deny_reason": "...", "reference_id": "..."}`.

Authentication runs in two layers. The bearer token is a per-environment JWT that names your tenant and environment. Once the signing secret is saved, each frame must also carry a valid [Standard Webhooks](https://www.standardwebhooks.com) signature: an HMAC-SHA256 over `{webhook-id}.{webhook-timestamp}.{raw body}`, checked against the raw bytes Cursor signed.

Anything but a 200 carrying a verdict is a failed check in Cursor, which never reads as a deny: your failure mode decides the outcome, and repeated failures trip Cursor's circuit breaker. Capsule therefore answers 200 with a verdict on every path, allows frames it cannot read, and allows when analysis is unavailable or does not finish in time. A request is denied only on an explicit policy hit.

`deny_reason` is truncated to 500 characters. `reference_id` is the frame's `request_id`, which Cursor also records in its audit log, so a denial in Cursor joins back to the matching Capsule detection.

## Support

For help with this integration:

- **Email**: support@capsule.security
- **Include**: Your tenant ID and the `request_id` from any unexpected denial


## References

- [Grok Bot inference hooks](https://cursor.com/docs/grok-bot/inference-hooks)
- [Grok Bot security](https://cursor.com/docs/grok-bot/security)
- [Standard Webhooks specification](https://www.standardwebhooks.com)