---
title: Risk Center
description: Read the distribution, tune from evidence rather than intuition, and understand why raising a threshold is a security change.
---

`/risk` in the console, backed by `GET /v1/risk/overview`.

## What the overview shows

| | |
| --- | --- |
| Counts by level | How much `LOW` / `MEDIUM` / `HIGH` / `CRITICAL` traffic you have |
| Signal breakdown | Which of the thirteen signals are firing, and how often |
| High-risk tools | Which tools produce the most elevated scores |
| Destinations | What your agents are actually contacting |
| Policy violations | Recent refusals, by agent |
| Credential anomalies | Unusual credential use |

Every score decomposes into named signals with human-readable explanations.
There is no opaque model, because a refusal an operator cannot explain to the
person it affected is a refusal that gets overridden, and then switched off.

## Read it in this order

:::steps

:::step The distribution

A healthy distribution has most traffic low and a thin tail. Two bad shapes:

**Everything is `HIGH`.** Your weights are too aggressive or your thresholds too
low. Any rule testing `risk.score` is now firing on everything, which means it
is not discriminating.

**Everything is `LOW`.** Either your traffic is genuinely uniform, or your
weights are too low to register anything. Check the signal breakdown — if
nothing is firing at all, the engine is not contributing.
:::

:::step The signal breakdown

For each of the thirteen signals, how often it fires.

| Pattern | Means | Do |
| --- | --- | --- |
| Fires on nearly every action | Not discriminating | Lower its weight, or fix the baseline |
| Never fires | Irrelevant to your traffic, or weighted too low | Investigate before dismissing |
| Fires on a thin, consistent slice | Working as intended | Leave it |

:::note New agents trip every "new" signal
`NEW_TOOL`, `NEW_RESOURCE`, `NEW_RECIPIENT` and `UNUSUAL_DESTINATION` are
**baseline** signals — they compare against what *this agent* has done before. A
brand-new agent has no baseline, so they fire on almost everything it does.

That is correct and it settles. Run new agents in `OBSERVE` or `SIMULATE` long
enough to establish a baseline before promoting, or you will spend the first week
reading noise.
:::
:::

:::step High-risk tools

Tools that consistently produce elevated scores. Two questions for each:

- Is `dangerous` set? If a tool is reliably scoring high, it probably deserves the flag and the approval requirement that comes with it.
- Is the risk coming from the tool, or from how one agent uses it? The tool breakdown and the agent breakdown answer different things.
:::

:::step Destinations

What your agents actually contact, which is frequently not what anyone
expected.

Compare against your tools' `destination_allowlist` entries. A destination
appearing here that nobody intended is worth a conversation, and probably a
narrower allowlist.
:::

:::

## Tune from evidence

```http
PUT /v1/risk/configuration
```

Requires `risk:configure`. The change is audited.

The method:

1. Run in `OBSERVE` or `SIMULATE` and let real traffic accumulate — at least a week, covering a normal day and a quiet one.
2. Read the distribution and the breakdown.
3. Adjust weights so each signal contributes in proportion to how much it actually tells you.
4. Set thresholds where the distribution has a natural gap, not at round numbers.
5. Re-check after a week.

:::danger Raising a threshold is a security change, not a tuning tweak
Moving the `HIGH` threshold from 70 to 85 silently removes the approval
requirement from every rule that tests it. Nothing errors. Nothing warns. Fewer
things get escalated and everything looks calmer.

It is audited for exactly that reason. Simulate before and after, and look at
what stops being escalated — not at whether the dashboard looks tidier.
:::

## Prefer signals over scores in rules

```json
{
  "kind": "condition",
  "id": "c-signal",
  "field": "risk.signals",
  "operator": "contains",
  "value": "UNUSUAL_DESTINATION"
}
```

reads better than

```json
{ "kind": "condition", "id": "c-score", "field": "risk.score", "operator": "gte", "value": 70 }
```

A named signal is a sentence an operator can read back to you. A score is a
number whose meaning changes every time you retune weights — which means a rule
written against a score silently changes behaviour when you tune, and a rule
written against a signal does not.

Use the score as a general safety net, and signals for the specific things you
care about.

The raw observations behind the signals are available too, so you can write a
rule on the observation rather than the derived signal when that is clearer:
`velocity.actions_last_minute`, `velocity.amount_last_day`,
`history.tool_used_before`, `history.destination_used_before`,
`history.resource_used_before`, `time.hour_utc`, `time.day_of_week`.

## Risk events

```http
GET /v1/risk/events
```

Every assessment that crossed a threshold, with its signal evidence attached.

Acknowledge with `risk:acknowledge`, so "we have looked at this" is recorded
rather than remembered. An unacknowledged backlog is a queue nobody is working,
same as approvals.

## Weekly review

- Distribution shape — any drift from last week?
- Any signal newly firing on everything, or newly silent?
- New destinations?
- New high-risk tools, or an existing one that got worse?
- Unacknowledged events accumulating?

Fifteen minutes. The value is in the deltas, not the absolute numbers.

## Related

:::cards

:::card Risk engine | /concepts/risk
The thirteen signals and the scoring model.
:::

:::card Write your first policy | /build/first-policy
Using signals in a rule.
:::

:::card Approvals queue | /operate/approvals-queue
Where escalated risk ends up.
:::

:::card Risk API | /reference/api/risk
Overview, events, configuration.
:::

:::
