# Redis Intent Router concepts

```json metadata
{
  "schema_version": 2,
  "title": "Redis Intent Router concepts",
  "description": "Understand Routers, intents, examples, targets, scores, and access grants.",
  "categories": ["docs","develop","ai"],
  "tableOfContents": {"sections":[{"id":"routers","title":"Routers"},{"children":[{"id":"examples","title":"Examples"},{"id":"targets","title":"Targets"},{"id":"revisions","title":"Revisions"}],"id":"intents","title":"Intents"},{"id":"matching","title":"Matching"},{"id":"authoring-and-consistency","title":"Authoring and consistency"},{"id":"access","title":"Access"}]}

,
  "codeExamples": []
}
```


Intent Router classifies each incoming user message by matching it against example phrases you group into intents. This page explains the parts you work with and how they fit together, so the task pages make sense when you reach them.

It covers Routers, which hold a set of intents and control who can use them, and intents, with their examples, targets, and revisions. It then explains how matching scores a query, when a change takes effect, and which agent-key actions each operation needs.

## Routers

A **Router** is the unit you create, configure, and secure. It holds a set of intents and their examples, an embedding model, and a default minimum score. Each Router has its own access grants, so use separate Routers for workloads that must not share intents.

A Router has an opaque identifier that starts with `rtr_`. Its embedding model is fixed when you create it and can't change afterward, because every stored example is embedded with it.

A Router is in one of these states:

| State | Meaning |
| ----- | ------- |
| `PROVISIONING` | The data plane is building the Router's search index. Data requests return `409` until it is ready. |
| `READY` | The Router serves requests. You can suspend or delete it. |
| `FAILED` | Provisioning failed. `failureReason` explains why. A failed Router can only be deleted. |
| `SUSPENDED` | An administrator paused the Router. Data requests return `423` until it is resumed to `READY`. |
| `DELETING` | The data plane is removing the Router and its data. Data requests return `404`. |

Administrators manage Routers through the **control plane**. Applications use the **data plane** to author intents and match queries. The two planes don't call each other, and a Router serves only after the data plane has applied its current configuration. See [Manage Routers](https://redis.io/docs/latest/develop/ai/context-engine/intent-router/manage-routers) to create one, and [service limits and errors](https://redis.io/docs/latest/develop/ai/context-engine/intent-router/limits) for the errors a Router returns when it isn't serving.

## Intents

An **intent** is a named classification. Its name is unique within the Router and can contain letters, digits, `.`, `_`, and `-`, starting with a letter or digit. An intent has:

- **Examples**: phrasings that should match the intent.
- A **description**: when the intent should win, in your words. Optional.
- A **target**: what a match dispatches to. Optional.
- A **minimum score**: how close a query must be for this intent to match. Optional.
- **Metadata**: labels such as an owner or tags. Optional.

An intent without examples never matches.

Intents and examples are ordered lists. Redis Intent Router returns them in the order you created them, not sorted by name.

### Examples

An **example** is one phrasing of an intent, such as "where is my order" for `track_order`. Redis embeds each example when you write it.

Add several varied phrasings per intent. Matching compares a query with every example, so more varied examples cover more of the ways people ask. An example identifier starts with `exm_` and is derived from the text, so adding the same phrasing twice keeps one example.

### Targets

A **target** tells your application what to do when an intent matches:

| Field | Meaning |
| ----- | ------- |
| `type` | The dispatch mechanism, such as `tool`, `pipeline`, `handler`, `prompt`, or `agent`. The set is open: use any identifier without whitespace. |
| `ref` | The callee within that type's namespace, such as `orders.track`. |
| `args` | Optional dispatch arguments, as a JavaScript Object Notation (JSON) object. |

The Router checks that `args` is valid JSON and passes it through untouched. It knows how an intent is dispatched, never what the target does.

Metadata is for descriptive labels. Put dispatch data in the target: metadata rejects the keys `type`, `ref`, `target`, and `args`.

### Revisions

Every intent has a `revision` that changes with every write to the intent, including a `PUT` that changes nothing. Adding or deleting examples through the example operations doesn't change it. Send the revision back as `expectedRevision` to make a write conditional: the write fails with `412 Precondition Failed` if someone else changed the intent first.

## Matching

To **match** a query, Redis Intent Router embeds the text, finds the nearest examples in the Router's vector index (50 by default), and groups them by intent. By default an intent scores as its closest example, so one good example is enough for a match. Then it drops intents below their minimum score and returns the rest, best first.

A score is 1 minus the cosine distance between the query and the example, kept between 0 and 1, and higher is closer. Every threshold in the API points the same way: **higher is stricter**.

The minimum score that applies to an intent, from highest to lowest precedence:

1. The `minScore` in the match request.
1. The intent's own `minScore`, when it is above `0`.
1. The Router's `minScore`, which is `0.7` unless you set another.

An intent `minScore` of `0` means "use the Router's", never "match everything". Only the match request can lower the threshold to `0`.

A query with no sufficiently close intent returns `200` with an empty list. That is a normal result, not an error.

See [Match queries](https://redis.io/docs/latest/develop/ai/context-engine/intent-router/match) to tune thresholds and result limits.

## Authoring and consistency

Writes keep matching available. When you replace an intent, Redis writes the new examples first and removes the old ones afterward, so a concurrent match never sees an empty intent. Writing the same intent twice produces the same intent, with a new `revision`.

A write that adds several intents validates all of them first, and writes nothing if any is invalid.

## Access

Two credentials guard the service:

- An **admin token** manages Routers on the control plane. Platform teams hold it.
- An **agent key** authenticates an application's data-plane requests as a bearer token. It carries a grant for each Router it can use. Redis Iris issues agent keys through its Identity Service, not through the Intent Router API.

A grant lists one or more actions on one Router. A key without the action an operation needs gets `403`.

| Action | What it allows |
| ------ | -------------- |
| `read` | Match queries, read intents and examples, and check the Router's health. |
| `write` | Create, change, and delete intents and examples, and clear the Router. Includes `read`. |
| `full` | Includes `write`. No operation needs more than `write` today. |

Grants apply to a whole Router. Don't rely on intent names or metadata to separate audiences. Use a separate Router instead.

