Learn how Routers, intents, examples, targets, and scores work
Redis Intent Router
Classify a user's message into a named intent and get back the target your application should dispatch to.
What is Redis Intent Router?
Redis Intent Router classifies text into intents that you define. Each intent is a name, a few example phrasings, and an optional target that says what your application should do when the intent matches. Send a query to a Router and it returns the closest intents, best first, with a score for each.
It works like a semantic cache, but returns a structured intent instead of a cached response. Redis embeds the query, finds the nearest examples, groups them by intent, and applies a score threshold. No large language model (LLM) call is involved at match time.
For example, a support application can route "where is my package?" to a track_order intent that points at an order-tracking tool, and "I want my money back" to a refund intent that points at a refund workflow.
Define two intents and match your first queries
Create Routers, choose an embedding model, and control access
Tune thresholds and result limits for accurate routing
Why use Redis Intent Router?
- Fast, predictable routing: Matching embeds the query and runs a vector search over your examples, with no LLM call.
- Routing you can edit: Add an example or change a threshold and the change applies to the next query. You don't retrain or redeploy anything.
- Dispatch data stays with the intent: A target carries the tool, pipeline, or agent to call, so your application doesn't keep a separate lookup table.
- Tunable strictness: Set a minimum score on the Router, on each intent, or on a single request.
- Safe updates: Replacing an intent never leaves it empty while queries are in flight, and conditional writes prevent lost updates.
- Governed access: Each Router is its own authorization boundary, with separate
read,write, andfullgrants. - Flexible integration: Use Python, TypeScript, the
iriscommand-line interface (CLI), or the Hypertext Transfer Protocol (HTTP) API.
Concepts
A Router holds your intents and is its own access boundary. Each intent has example phrasings and an optional target, and each match returns intents with a score that a threshold on the Router, the intent, or the request can filter. See Intent Router concepts.
Quick example
-
Set up a Router:
- Redis Cloud: Create an Intent Router.
- Self-managed: Deploy with Self-managed Intent Router, then create a Router and an agent key. You need a license key to deploy: contact Redis to request access.
-
Install the Redis Iris Python package, which includes the
irisCLI:pip install 'redis-iris>=1.0.0' -
Set
IRIS_INTENT_ROUTER_URL,IRIS_INTENT_ROUTER_ID, andIRIS_INTENT_ROUTER_API_KEYas shown in the quickstart, connect, and define intents:
from redis_iris.intent_router import IntentRouter, Target
router = IntentRouter.from_env()
print(router.health())
from redis_iris.intent_router import IntentRouter, Target
router = IntentRouter.from_env()
print(router.health())
for intent in (
router.define(
"track_order",
description="The customer wants to know where an order is.",
target=Target("tool", "orders.track", {"region": "eu"}),
examples=["where is my order", "track my package", "has my parcel shipped"],
),
router.define(
"refund",
examples=["i want a refund", "refund my purchase", "i would like my money back"],
),
):
print(intent.name, intent.example_count, intent.revision)
for query in ("where is my order please", "i would like my money back", "zzz qqq"):
best = router.match(query).best
if best:
print(query, "->", best.name, round(best.score, 2), best.target)
else:
print(query, "-> no match")
for example in router.add_examples("track_order", ["when will my delivery arrive"]):
print(example.example_id, example.text)
updated = router.update("track_order", min_score=0.8)
print(updated.name, updated.min_score, updated.revision)
import { IntentRouter } from "@redis-iris/intent-router";
function requiredEnv(name: string): string {
const value = process.env[name];
if (!value) throw new Error(`Set ${name}`);
return value;
}
const router = new IntentRouter({
serverURL: requiredEnv("IRIS_INTENT_ROUTER_URL"),
routerId: requiredEnv("IRIS_INTENT_ROUTER_ID"),
apiKey: requiredEnv("IRIS_INTENT_ROUTER_API_KEY"),
retryConfig: { strategy: "none" },
});
console.log((await router.getRouterHealth()).result);
import { IntentRouter } from "@redis-iris/intent-router";
function requiredEnv(name: string): string {
const value = process.env[name];
if (!value) throw new Error(`Set ${name}`);
return value;
}
const router = new IntentRouter({
serverURL: requiredEnv("IRIS_INTENT_ROUTER_URL"),
routerId: requiredEnv("IRIS_INTENT_ROUTER_ID"),
apiKey: requiredEnv("IRIS_INTENT_ROUTER_API_KEY"),
retryConfig: { strategy: "none" },
});
console.log((await router.getRouterHealth()).result);
for (const intent of [
await router.upsertIntent("track_order", undefined, undefined, {
description: "The customer wants to know where an order is.",
target: { type: "tool", ref: "orders.track", args: { region: "eu" } },
examples: ["where is my order", "track my package", "has my parcel shipped"],
}),
await router.upsertIntent("refund", undefined, undefined, {
examples: ["i want a refund", "refund my purchase", "i would like my money back"],
}),
]) {
console.log(intent.result.name, intent.result.exampleCount, intent.result.revision);
}
for (const query of ["where is my order please", "i would like my money back", "zzz qqq"]) {
const { items } = (await router.match({ query })).result;
if (items.length > 0) {
console.log(query, "->", items[0].name, items[0].score.toFixed(2), items[0].target);
} else {
console.log(query, "-> no match");
}
}
const added = await router.addExamples("track_order", {
examples: ["when will my delivery arrive"],
});
for (const example of added.result.items) console.log(example.exampleId, example.text);
const { result: updated } = await router.updateIntent("track_order", undefined, { minScore: 0.8 });
console.log(updated.name, updated.minScore, updated.revision);
set -euo pipefail
ROUTER_API="${IRIS_INTENT_ROUTER_URL%/}/iris/data/v1/intent/routers/$IRIS_INTENT_ROUTER_ID"
curl --fail-with-body --silent --show-error \
"$ROUTER_API/health" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" | jq .
set -euo pipefail
ROUTER_API="${IRIS_INTENT_ROUTER_URL%/}/iris/data/v1/intent/routers/$IRIS_INTENT_ROUTER_ID"
curl --fail-with-body --silent --show-error \
"$ROUTER_API/health" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" | jq .
curl --fail-with-body --silent --show-error \
-X PUT "$ROUTER_API/intents/track_order" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"description": "The customer wants to know where an order is.",
"target": {"type": "tool", "ref": "orders.track", "args": {"region": "eu"}},
"examples": ["where is my order", "track my package", "has my parcel shipped"]
}' | jq -c '{name, exampleCount, revision}'
curl --fail-with-body --silent --show-error \
-X PUT "$ROUTER_API/intents/refund" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"examples": ["i want a refund", "refund my purchase", "i would like my money back"]}' \
| jq -c '{name, exampleCount, revision}'
for query in "where is my order please" "i would like my money back" "zzz qqq"; do
curl --fail-with-body --silent --show-error \
-X POST "$ROUTER_API/match" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data "$(jq -n --arg query "$query" '{query: $query}')" \
| jq -r --arg query "$query" 'if (.items | length) > 0
then "\($query) -> \(.items[0].name) \(.items[0].score * 100 | round / 100) \(.items[0].target | tojson)"
else "\($query) -> no match" end'
done
curl --fail-with-body --silent --show-error \
-X POST "$ROUTER_API/intents/track_order/examples" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"examples": ["when will my delivery arrive"]}' | jq -c '.items[] | {exampleId, text}'
curl --fail-with-body --silent --show-error \
-X PATCH "$ROUTER_API/intents/track_order" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"minScore": 0.8}' | jq -c '{name, minScore, revision}'
set -euo pipefail
iris intent-router health
set -euo pipefail
iris intent-router health
iris intent-router intents add track_order \
--description "The customer wants to know where an order is." \
--target '{"type": "tool", "ref": "orders.track", "args": {"region": "eu"}}' \
--example "where is my order" --example "track my package" --example "has my parcel shipped"
iris intent-router intents add refund \
--example "i want a refund" --example "refund my purchase" --example "i would like my money back"
for query in "where is my order please" "i would like my money back" "zzz qqq"; do
iris intent-router match "$query"
done
iris intent-router examples add track_order "when will my delivery arrive"
iris intent-router intents update track_order --min-score 0.8
for intent in (
router.define(
"track_order",
description="The customer wants to know where an order is.",
target=Target("tool", "orders.track", {"region": "eu"}),
examples=["where is my order", "track my package", "has my parcel shipped"],
),
router.define(
"refund",
examples=["i want a refund", "refund my purchase", "i would like my money back"],
),
):
print(intent.name, intent.example_count, intent.revision)
for (const intent of [
await router.upsertIntent("track_order", undefined, undefined, {
description: "The customer wants to know where an order is.",
target: { type: "tool", ref: "orders.track", args: { region: "eu" } },
examples: ["where is my order", "track my package", "has my parcel shipped"],
}),
await router.upsertIntent("refund", undefined, undefined, {
examples: ["i want a refund", "refund my purchase", "i would like my money back"],
}),
]) {
console.log(intent.result.name, intent.result.exampleCount, intent.result.revision);
}
curl --fail-with-body --silent --show-error \
-X PUT "$ROUTER_API/intents/track_order" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{
"description": "The customer wants to know where an order is.",
"target": {"type": "tool", "ref": "orders.track", "args": {"region": "eu"}},
"examples": ["where is my order", "track my package", "has my parcel shipped"]
}' | jq -c '{name, exampleCount, revision}'
curl --fail-with-body --silent --show-error \
-X PUT "$ROUTER_API/intents/refund" \
-H "Authorization: Bearer $IRIS_INTENT_ROUTER_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"examples": ["i want a refund", "refund my purchase", "i would like my money back"]}' \
| jq -c '{name, exampleCount, revision}'
iris intent-router intents add track_order \
--description "The customer wants to know where an order is." \
--target '{"type": "tool", "ref": "orders.track", "args": {"region": "eu"}}' \
--example "where is my order" --example "track my package" --example "has my parcel shipped"
iris intent-router intents add refund \
--example "i want a refund" --example "refund my purchase" --example "i would like my money back"
The redis-iris package covers matching, intent authoring, and Router administration in Python and the CLI. For TypeScript, the generated client @redis-iris/intent-router covers the data plane and the control plane. See the developer guide to choose a client, and define intents and match your first queries.
Redis Intent Router is available on Redis Cloud and for self-managed deployment on Kubernetes.
- Redis Cloud: Create an Intent Router and an agent key in the Redis Cloud console.
- Self-managed: See Self-managed Intent Router, then create a Router and an agent key. You need a license key to deploy: contact Redis to request access.
Choose how to use it
| Use case | How an intent helps |
|---|---|
| Agent routing | Send each request to the specialist agent or tool that handles it. |
| Model selection | Send simple requests to a small model and complex ones to a larger model. |
| Guardrails | Detect off-topic or disallowed requests before they reach the agent. |
| Workflow dispatch | Start a pipeline or handler from a natural-language request. |
The Router doesn't run the target. It returns the target, and your application decides how and whether to act on it.
Manage Routers and intents
- Manage Routers: choose an embedding model, create a Router, and suspend, update, or delete it.
- Manage intents and examples: create, update, replace, and delete intents and their example phrasings.
Route at runtime
- Developer guide: choose a client and connect.
- Match queries: classify text and tune thresholds.
Use the API reference for operations and schemas, and service limits and errors for constraints and recovery guidance.