# Guard hook protocol

entity-gateway-hook/1, the HTTP protocol that lets a gateway or proxy call Guard on every model request and tool call. Open to third parties.

`POST https://api.securemyagent.ai/v1/guard/hook` runs [Guard](/docs/guard) on a model request before it leaves your gateway. The Entity Gateway calls it for every Agent Secret Store plan, for free. Any gateway, proxy or agent framework can call it the same way.

## Authenticate

Send `Authorization: Bearer <key>`.

- An organization key (`sma_...`) is the same key an agent gets at registration. Calls are logged to that agent's event log. No CAPTCHA, no login.
- The Entity Gateway uses a platform key held by Agent Secret Store. Its calls are attributed to `metadata.did`, are free, and never count against lookup or Checkup quotas.

A missing or wrong key answers `401`.

## Request

```json
{
  "version": "entity-gateway-hook/1",
  "event": "pre_request",
  "metadata": {
    "format": "openai_chat",
    "did": "did:key:z6Mk...",
    "request_id": "r1"
  },
  "request_body": { "messages": [{ "role": "user", "content": "..." }] },
  "tools": [
    { "kind": "declared", "name": "mcp__files__read" },
    { "kind": "tool_use", "name": "Bash", "input": { "command": "ls" } },
    { "kind": "tool_result", "content": "..." }
  ]
}
```

| Field          | Meaning                                                                                                                  |
| -------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `version`      | Must be `entity-gateway-hook/1`, else `400 unsupported_version`                                                          |
| `event`        | `pre_request` is checked. `request_complete` and `tool_calls` are accepted and always answer `allow`                     |
| `metadata`     | `format` is one of `openai_chat`, `openai_responses`, `anthropic_messages`, `gemini`, `bedrock`.                         |
| `request_body` | The provider request in its own wire format, up to 5 MB                                                                  |
| `tools`        | Up to 1000 entries. `declared` tools the request offers, `tool_use` calls the model made, `tool_result` content fed back |

## Answer

Always `200` with one of these. The hook checks in order.

| `action` | When                                                                                                                                                                              | Extra fields              |
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `block`  | A `tool_use` Guard denies (a reverse shell, a dropper, a secret leaving the machine), or a `tool_result` that carries instructions aimed at the agent (indirect prompt injection) | `status` (403), `message` |
| `ask`    | A `tool_use` Guard would ask about                                                                                                                                                | `message`                 |
| `modify` | Secrets, private keys, card numbers and US social security numbers were redacted, or tools from a malicious MCP server were stripped                                              | `request_body`            |
| `allow`  | Nothing to change                                                                                                                                                                 |                           |

Redaction replaces each value with a marker such as `[REDACTED:ssn]` and works on every string in the body, so it covers all five wire formats. A declared tool named `mcp__<server>__<tool>` is removed when the [Verdict Registry](/docs/registry) marks that MCP server `malicious`. Long unbroken base64 strings are treated as file payloads and left alone.

Send `modify` answers on to the provider in place of your original body. Treat `block` as the response to the client, using its `status` and `message` in the client's native error shape.

## Failure handling

The hook is a check, not a dependency. If it times out or errors, decide in your gateway whether to fail open or closed.

See also [Guard on every model call](/articles/guard-every-model-call), the [Entity Gateway guide](https://agentsecretstore.com/docs/guides/entity-gateway) and [signed requests](https://openentity.org/guides/signed-requests/).
