> ## Documentation Index
> Fetch the complete documentation index at: https://neuraltrust-92b43583-develop.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Policies

> A policy is where enforcement lives: gates that match request attributes before detection, detector rules that run detectors and decide the action, and a policy-wide Observe/Enforce switch.

A **policy** turns detection into a decision. [Detectors](/trustguard/concepts/detectors)
say *what* is in the traffic; a policy says *what to do about it*. You build
policies under **Agent Runtime → Policies**, then attach them to
[collectors](/trustguard/concepts/collectors).

Opening a policy opens a side panel with six tabs:

| Tab            | What it is                                                     |
| -------------- | -------------------------------------------------------------- |
| **Basics**     | Name and **Enforcement mode**.                                 |
| **Gates**      | Attribute matchers that run *before* detectors.                |
| **Detectors**  | Detector rules, split by **Input** / **Output**.               |
| **Collectors** | Which collectors send traffic here, and how.                   |
| **Test**       | Sandbox against the **last saved** policy.                     |
| **History**    | Change log for the policy, gates, detector rules, and routing. |

The list columns **Gates**, **Detectors**, and **Collectors** count what is on
those tabs. **Mode** is **Observe** or **Enforce**.

## Enforcement modes

The switch is on **Basics** (and in the panel header):

| Console     | API                  | Effect                                                                                      |
| ----------- | -------------------- | ------------------------------------------------------------------------------------------- |
| **Observe** | `report_only: true`  | Every gate and detector action is recorded only. Nothing is blocked, asked, or transformed. |
| **Enforce** | `report_only: false` | Actions apply as configured.                                                                |

Run a new policy in **Observe**, check **Activity** and **Test**, then switch to **Enforce**.

## Gates

**Gates** match request **attributes** (not prompt text) and run **before** any detector.

Each gate is a name, **And**/**Or** conditions, and a **Then** action:

| Action     | Effect                                                                                                                                                                     |
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Block**  | Stop immediately; **detectors are skipped**. In Observe this is recorded, not enforced.                                                                                    |
| **Report** | Record a finding and continue to detection.                                                                                                                                |
| **Skip**   | Stop remaining gates and continue to detectors without recording a gate finding.                                                                                           |
| **Ask**    | Request confirmation when the integration supports it. **Input only** (missing `direction` counts as input). On **output** the gate does not match. Detectors are skipped. |

Block, Skip, and Ask end the gate chain. Report continues. If any matching gate **Blocks**, detection does not run.

Ask behavior depends on the integration. [Claude Code](/integrations/claude-code)
and [Cursor](/integrations/cursor) display a permission prompt for tool calls,
but prompt events continue with a warning. [GitHub Copilot](/integrations/github-copilot)
prompts on interactive tool calls and treats Ask as denied in cloud jobs.
[Codex](/integrations/codex) has no Ask dialog; it allows the call and adds the
approval message to the agent context. See [How it works](/trustguard/how-it-works)
for the complete mapping.

### Condition attributes

| Group (console) | Attributes                                                      |
| --------------- | --------------------------------------------------------------- |
| **Consumer**    | `consumer.id`, `consumer.name`, `consumer.tag`, `consumer.type` |
| **Model**       | `model.name`, `model.provider`                                  |
| **Collector**   | `collector.id`, `collector.type`                                |
| **Source**      | `source.application`                                            |
| **Session**     | `session.id`                                                    |
| **Protocol**    | `protocol` (`llm` / `mcp` / `a2a`; API also accepts `all`)      |
| **Direction**   | `direction` (`input` / `output`)                                |
| **Tool**        | `tool.name`, `tool.command`, `tool.arguments`                   |

**Operators:** Equals, Not equals, Greater than, Less than, Contains, Does not contain, In (list), Matches (regex).

`consumer.*`, `model.*`, `collector.type`, and `source.application` come from
the request `attributes` object, or are stamped by an integration.
`collector.id`, `session.id`, `protocol`, and `direction` are resolved by
TrustGuard.

**`tool.name`** for MCP `tools/call` is read from **`payload.params.name`**, not
from `attributes.tool`. Hosts that expose tools as `mcp__<server>__<tool>` send
the last segment (`search_threads`). Gate on that short name.
`tool.command` is the shell line for Bash / Shell.

Do not put `name` inside `{ "input": "…" }` when `protocol` is `all`; that
body is rejected with `400`.

#### `source.application` values

| Value                | Path                                                                   |
| -------------------- | ---------------------------------------------------------------------- |
| `claude-ai`          | [Claude Enterprise](/integrations/claude-enterprise); claude.ai chat   |
| `claude-code`        | Claude Enterprise; Claude Code seen server-side, not the laptop plugin |
| `claude-code-plugin` | [Claude Code plugin](/integrations/claude-code); local lifecycle hooks |
| `cursor-plugin`      | [Cursor plugin](/integrations/cursor)                                  |
| `codex-plugin`       | [Codex plugin](/integrations/codex)                                    |
| `copilot-plugin`     | [GitHub Copilot plugin](/integrations/github-copilot)                  |
| `config-test`        | Anthropic **Test connection**                                          |

A gate on `claude-code` does **not** match the laptop plugin (`claude-code-plugin`).

## Detectors

The **Detectors** tab is split by **evaluation phase**:

* **Input:** prompt or tool call.
* **Output:** completion or tool result.

TrustGuard only runs the phase that matches the request `direction`. If the
caller never sends `output`, Output rules never run.

<Note>
  **Who sets `direction`?**

  * **[TrustGate](/integrations/trustgate)** sets it (`input` on
    the request path, `output` on the response path).
  * **IDE plugins** set it per hook (prompt and `preToolUse` → input; `postToolUse` → output).
  * **SDK / REST / browser** must send it on every call. Omitting it defaults to `input`.
</Note>

Each rule picks a [detector](/trustguard/concepts/detectors), an **action**, and
optional **conditions** (same attributes as gates):

| Action      | Console       | Effect                                                   | Rewrites payload |
| ----------- | ------------- | -------------------------------------------------------- | ---------------- |
| `report`    | **Monitor**   | Record a finding only.                                   | No               |
| `block`     | **Block**     | Flag for blocking; stops the remaining detector chain.   | No               |
| `transform` | **Transform** | Mask/rewrite. Only valid for **`data_loss_prevention`**. | Yes              |

## Verdict precedence

```text theme={null}
block  →  ask  →  transform  →  report  →  allow
```

`allow` means nothing fired, or everything was waived. The caller enforces the
verdict; see the [Evaluate API](/trustguard/api/evaluate). In **Observe**, the
status never goes past `report`.

## Test

**Test** evaluates the **saved** policy (unsaved Gates/Detectors do not apply).

1. **Test direction:** Input or Output. It must match the detector phase you want to test.
2. **Sample:** paste text, pick a preset, or select **Upload file**, which uses the **LLM** protocol.
3. **Extra parameters:** the same attributes available to gates. Skip, Block, and Ask match only when these are set. For example, set **Tool name** to `search_threads` or **Source application** to `claude-code-plugin`.
4. **Run test:** view the Blocked, Transformed, Reported, or Allowed decision and its findings.

Test does not emit **Activity** and does not consume the `/v1/evaluate` plan rate limit.

## History

History records create, update, and delete events for the policy, its gates,
detector rules, and collector routing.

## Collectors tab

Attach collectors with a routing mode:

* **Default:** fallback for all of that collector's traffic.
* **Consumer ID:** only requests with that `consumer_id`.

You can also bind routing from the collector’s **Policies** tab. A collector
with no matching policy leaves that request **unguarded** (`status: "allow"`, no findings).
