> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inworld.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Conditional Routing

> Route requests based on CEL expressions and request metadata

Conditional routing allows you to route requests to different models based on conditions that evaluate request metadata.

You can use conditional routing to:

* **Segment by user tier** — route premium users to flagship models and free users to cost-effective ones.
* **Route by geography** — direct requests to different models based on geography.
* **Optimize by complexity** — send simple prompts to fast, cheap models and complex ones to high-capability models.

## Basic Structure

Routes are defined directly on the Router. Each route has a `route` object and a `condition` object.

<Accordion title="Example router set up">
  ```json theme={"system"}
  {
    "name": "routers/my-router",
    "routes": [
      {
        "route": {
          "route_id": "premium-tier",
          "variants": [
            {
              "variant": {
                "variant_id": "premium-gpt5",
                "model_id": "openai/gpt-5.2"
              },
              "weight": 100
            }
          ]
        },
        "condition": {
          "cel_expression": "tier == \"premium\""
        }
      },
      {
        "route": {
          "route_id": "free-tier",
          "variants": [
            {
              "variant": {
                "variant_id": "free-flash",
                "model_id": "google-ai-studio/gemini-2.5-flash"
              },
              "weight": 100
            }
          ]
        },
        "condition": {
          "cel_expression": "tier == \"free\""
        }
      }
    ],
    "defaultRoute": {
      "route_id": "default",
      "variants": [
        {
          "variant": {
            "variant_id": "default-variant",
            "model_id": "google-ai-studio/gemini-2.5-flash"
          },
          "weight": 100
        }
      ]
    }
  }
  ```
</Accordion>

The `condition` field accepts a [CEL](https://cel.dev/) expression that can be evaluated against the following from each [Chat Completions](/api-reference/routerAPI/chat-completions) request:

* **Request metadata** — key-value pairs sent in `extra_body.metadata` (e.g. user tier, region, complexity score).
* **Messages** — the full `messages` array from the request body

<Tip>Routes are evaluated **in order**, and the first route whose condition evaluates to `true` is selected.</Tip>

The table below lists the available operations for constructing a CEL expression:

| **Operation**      | **Example**                                             | **Description**                                      |
| :----------------- | :------------------------------------------------------ | :--------------------------------------------------- |
| Equality           | `tier == "premium"`                                     | Matches a specific value.                            |
| Comparison         | `request_count > 100`                                   | Numeric comparisons (`>`, `<`, `>=`, `<=`).          |
| Logical AND        | `tier == "premium" && region == "us-east"`              | Both conditions must be true.                        |
| Logical OR         | `tier == "premium" \|\| tier == "enterprise"`           | Either condition must be true.                       |
| Range check        | `score >= 80 && score <= 100`                           | Matches values within a range.                       |
| `startsWith()`     | `user_id.startsWith("enterprise-")`                     | Checks if a string starts with a prefix.             |
| `endsWith()`       | `user_id.endsWith("-admin")`                            | Checks if a string ends with a suffix.               |
| `contains()`       | `user_id.contains("test")`                              | Checks if a string contains a substring.             |
| `matches()`        | `messages.last().content.matches("(?i).*\\bcode\\b.*")` | RE2 regex match on any string field.                 |
| `size()`           | `user_id.size() > 10`                                   | Gets the length of a string.                         |
| `messages.has()`   | `messages.has()`                                        | `true` if the message array exists and is non-empty. |
| `messages.first()` | `messages.first().content.contains("system")`           | First message in the array.                          |
| `messages.last()`  | `messages.last().content.matches("(?i).*help.*")`       | Last message in the array.                           |
| `messages.get(i)`  | `messages.get(0).role == "system"`                      | Message at index `i` (0-based).                      |
| `messages.len()`   | `messages.len() > 3`                                    | Number of messages in the array.                     |

<Note>
  Expressions are typed — ensure your metadata types match. Use `count == 100` when the value is a number and `tier == "premium"` when it's a string. Mismatched types will not match.
</Note>

## Making a Request

When calling your router, pass metadata in your requests using `extra_body.metadata` to provide the values referenced by your conditions, enabling dynamic route selection.

```bash theme={"system"}
curl --request POST \
  --url https://api.inworld.ai/v1/chat/completions \
  --header 'Authorization: Basic <your-api-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "model": "inworld/my-router",
    "messages": [
      {"role": "user", "content": "Hello"}
    ],
    "extra_body": {
      "metadata": {
        "tier": "premium",
        "user_id": "user-123",
        "region": "us-east"
      }
    }
  }'
```

In this example, the provided metadata (`tier`, `user_id`, and `region`) will be available for the router’s CEL expressions, enabling conditional routes to match and select the appropriate model configuration based on those values.

## Example Use Cases

### User Subscription Tiers

Route users to different models based on their subscription tier:

```json theme={"system"}
{
  "cel_expression": "subscription_tier == \"pro\""
}
```

### Geographic Routing

Route requests based on user location:

```json theme={"system"}
{
  "cel_expression": "region == \"eu\""
}
```

### Prompt-Based Routing

You can combine fast prompt-based regex routing with metadata checks in a single condition, enabling routing by both **what the user is asking** and **who the user is**.

Route coding questions from premium users to a reasoning model:

```json theme={"system"}
{
  "cel_expression": "messages.last().content.matches(\"(?i).*\\\\b(code|debug|refactor|bug fix)\\\\b.*\") && tier == \"premium\""
}
```

<Tip>
  Regex also works on metadata fields (e.g. `user_id.matches(".*-admin$")`) and on any message — use `messages.first()` to match the first message or `messages.get(i)` for a specific turn.
</Tip>

Route translation requests to a multilingual model:

```json theme={"system"}
{
  "cel_expression": "messages.last().content.matches(\"(?i).*\\\\btranslat(e|ion)\\\\b.*\")"
}
```

Route long conversations (e.g. 10+ turns) to a model with a large context window:

```json theme={"system"}
{
  "cel_expression": "messages.len() > 10"
}
```

<Note>
  Conditions are evaluated before route variants are selected, so messages defined inside variants are not part of condition evaluation.
</Note>

### Dynamic Tiering

Route requests to different model tiers based on prompt complexity. Use a lightweight classifier in your application to score complexity, then let the router pick the right model:

```json theme={"system"}
{
  "routes": [
    {
      "route": {
        "route_id": "complex",
        "variants": [
          {
            "variant": { "variant_id": "gpt5-premium", "model_id": "openai/gpt-5.2" },
            "weight": 100
          }
        ]
      },
      "condition": {
        "cel_expression": "complexity_score >= 8"
      }
    },
    {
      "route": {
        "route_id": "standard",
        "variants": [
          {
            "variant": { "variant_id": "gpt5", "model_id": "openai/gpt-5-mini" },
            "weight": 100
          }
        ]
      },
      "condition": {
        "cel_expression": "complexity_score >= 4"
      }
    }
  ],
  "defaultRoute": {
    "route_id": "simple",
    "variants": [
      {
            "variant": { "variant_id": "flash", "model_id": "openai/gpt-5-nano" },
        "weight": 100
      }
    ]
  }
}
```

Simple tasks go to fast, cheap models while complex tasks get flagship models — optimizing cost without sacrificing quality where it matters.
