Skip to main content

Filtering

A filter can be set for a whole thread or for a single message, and every field is optional.

Where to Set the Filter

The modelRoutingFilter lives on GenerationConfig — the same object used for model, models, responseFormat, etc. It can be set at two levels:

1. Thread-Level Default

Set via create-thread in default_generation_config.model_routing_filter. Applies to every message in the thread.

curl -X POST https://api.travila.ai/api/v1/llm/gateway/create-thread \
-H "X-API-Key: $API_KEY" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"title": "Long research thread",
"default_generation_config": {
"models": [
"google/gemini-3.6-flash:nitro",
"anthropic/claude-sonnet-4.6:nitro",
"anthropic/claude-sonnet-5"
],
"model_routing_filter": {
"min_context_length": 128000
}
}
}'

When to use: When you want consistent capability requirements across all messages in a thread (e.g., "always require >=128k context for this long-context thread").

2. Per-Message Override

Set via send-message in override_generation_config.model_routing_filter. Applies to a single message only.

curl -X POST https://api.travila.ai/api/v1/llm/gateway/send-message \
-H "X-API-Key: $API_KEY" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"conversation_key": "research-001",
"user_message": {
"role": "ROLE_USER",
"content": [
{ "type": "CONTENT_PART_TYPE_IMAGE_BASE64", "content": "<base64_image>" },
{ "type": "CONTENT_PART_TYPE_TEXT", "content": "What is in this image?" }
]
},
"override_generation_config": {
"models": [
"google/gemini-3.6-flash:nitro",
"anthropic/claude-sonnet-4.6:nitro",
"anthropic/claude-sonnet-5"
],
"model_routing_filter": {
"required_input_modalities": ["image"]
}
}
}'

When to use: When a specific message needs different model capabilities (e.g., "this message includes an image, require image input support").

The override merges — it does not replace

override_generation_config is merged field-by-field onto the config the thread would otherwise use. Send only what you want to change; everything you leave out is inherited.

The granularity is the top-level config field. A field you do set replaces the base value wholesale rather than merging into it, so a partial model_routing_filter in an override replaces the thread's filter entirely — it does not combine with it.

Two details worth knowing:

  • Explicit zeros count. Scalars are presence-aware, so "temperature": 0 overrides the base rather than reading as "unset".
  • Empty lists do not. Repeated and map fields have no presence, so an empty list is indistinguishable from an absent one and inherits instead. To remove tools you must send clear_tools: true; omitting tools will not do it.

ModelRoutingFilter Fields

All fields are optional. Unset/zero-value fields are ignored (no filtering on that dimension). When multiple fields are set, they are ANDed — a model must pass every specified filter.

FieldTypeDescriptionBehavior
min_context_lengthint64Minimum context window in tokensModels below this are excluded
min_max_completion_tokensint64Minimum max output tokensModels reporting 0 (unknown) pass through
required_input_modalitiesstring[]e.g., ["image", "audio"]Model must support ALL listed. Models with empty modalities are excluded
required_output_modalitiesstring[]e.g., ["image"]Model must support ALL listed. Models with empty modalities are excluded
max_prompt_costdoubleMax cost per prompt token (e.g., 0.000003)0 = no limit. Unparseable pricing = pass
max_completion_costdoubleMax cost per completion token0 = no limit. Unparseable pricing = pass
exclude_moderatedboolSkip models with content moderationOnly filters when set to true
required_parametersstring[]e.g., ["tools", "response_format"]Model must support ALL listed

How filters combine

SituationBehaviour
No model_routing_filter setNo metadata filtering. Model-ID validation still runs.
Filter set, all fields zero/unsetNo filtering — the same as not setting one
Filter on override_generation_configApplies to that message only; the next message reverts to the thread default
A single model, no models arrayThe filter applies to that one model. If it fails, you get an immediate error.
model plus modelsThe filter applies to the merged candidate list — model first, then models