Intelligent routing
Intelligent routing is opt in. Enable it with:
air = AIR(routing="intelligent")or
from air.config import AIRConfig
air = AIR(config=AIRConfig(routing="intelligent"))The default is routing="priority", which does not use any of the logic on this page.
What gets classified
air.routing.intelligent.classify_request(request) inspects the request and produces a RequestProfile(required, preferred, estimated_tokens) using deterministic keyword checks. No AI model is called to make this decision.
- Required capability
codingis added if any message contains```or one ofdef,class,function,stack trace,traceback,compile error(case insensitive). - Preferred capability
reasoningis added if any message containsstep by step,explain why,prove that, orwalk through your reasoning(case insensitive). - Preferred capability
speedis added if the estimated token count is under 200 andreasoningwas not already added. - Anything in
ChatRequest.requires(aset[str]) is added directly to the required set, letting you force capabilities likevisionthat the keyword rules do not detect.
Provider capabilities
Declare what a provider can do when you register it:
air.add_provider(
gemini,
capabilities={"coding": True, "vision": True, "context_tokens": 128_000, "speed": True},
)capabilities fields (all optional, air.routing.capabilities.ProviderCapabilities):
reasoning: bool = Falsecoding: bool = Falsevision: bool = Falsetool_use: bool = Falsespeed: bool = Falsecontext_tokens: int | None = None
If you never pass capabilities for a provider, it is treated as having none of these capabilities set, and will be skipped by intelligent routing for any request with required capabilities.
Selection
air.routing.intelligent.select_provider(ordered, states, profile) skips a provider if:
- its health status is
exhausted, - it is missing a required
coding,vision, ortool_usecapability, - its declared
context_tokensis lower than the request's estimated tokens, - its known or estimated remaining capacity (see capacity-tracking.md) is lower than the request's estimated tokens.
Among the remaining candidates, it scores each one: one point per satisfied required capability, one point for reasoning if preferred and available, one point for speed if preferred and available, one point for available health status, and a note (not an extra point difference between known and estimated) for whether capacity is known or estimated rather than unknown. The highest scoring provider is picked; ties keep whichever appears first in priority order.
What happens after selection
The picked provider is moved to the front of the priority ordered list AIR would otherwise use. Normal fallback still applies: if the picked provider fails with a fallback eligible error, AIR proceeds to the next provider in priority order, same as plain priority routing. See core/fallback.md.
If no provider satisfies the required capabilities, intelligent routing does not pick anything, and AIR falls back to plain priority order for that request.
Selection reason
response = await air.chat(request)
print(response.selection_reason)ChatResponse.selection_reason is a short human readable string (for example "coding capability, healthy, sufficient estimated capacity"), set only when intelligent routing's initial pick is the provider that actually produced the response. It is None in priority routing, and None if a different provider ended up answering after a fallback.