Repository navigation
Description
Motivation
An Agent today uses the first configured available model for every run
(select_configured_model_id). When a tenant configures several models for
one Agent — e.g. a small non-thinking model, a long-context model and a
reasoning model — every request pays for the same capability level regardless
of what the request actually needs: a one-line terminology lookup and a
multi-document record summarization hit the same model.
This is a general capability gap; our driving scenario is a medical
deployment (record summarization / multidisciplinary discussion / quick
lookups map naturally to different model tiers), but the mechanism itself is
domain-agnostic.
Demand evidence: This feature originated from a production deployment
in the medical domain at a large top-tier (Grade-A tertiary) hospital in
China. Their multi-model medical architecture (quick-QA / long-context /
deep-reasoning service tiers backed by different models) cannot be
expressed with the current first-available model selection; closing that
gap is the direct trigger for this contribution.
Proposal
Add an opt-in routing step to run preparation:
- When
MODEL_ROUTING_ENABLED=trueand the request did not pin a model,
classify the run (task tier, risk, estimated size) and pick the
best-matching model from the agent's own configuredmodel_idspool. - Everything else stays exactly as today.
Behavior contract
- Explicit request-level
model_idalways wins; routing never overrides it. - With
MODEL_ROUTING_ENABLED=false(default) behavior is identical to the
current release. - Routing only selects models the tenant already validated and the agent
already configured (no permission-boundary change). - No classification signal → keep the existing selection (routing never
guesses). - No capable candidate / exhausted fallback → keep the existing selection
(routing never fails a run). - Tier fallback (
quick_qa → long_context → deep_reasoning) is recorded in
the audit record (fallback_from). - Ties break stably by input order; same pool + same query → same decision.
Configuration surface
MODEL_ROUTING_ENABLED(env, defaultfalse)MODEL_ROUTING_RULES_JSON_PATH(env) → JSON rules file: tier vocabularies,
size thresholds, task-tag mapping, risk terms. A medical example ships in
backend/configs/model_routing_rules.json; replacing the file adapts the
router to another domain. Engine code contains no domain vocabulary.
Open questions for maintainers
- Per-agent explicit task tag: which carrier is acceptable?
context_policy
is validated byPolicyLayers(extra="forbid")and cannot take extra keys.
Candidates: dedicated column, metadata field, or tag entity. - Should the switch stay env-level, or do tenants/agents need a per-agent
toggle on top? - Longer term, tier-exclusivity limits selection (a reasoning model with a
large window cannot serve the long-context tier). A "hard constraints
filter + task-preference scoring" model would compose capabilities; we
kept tiers for the smallest first slice.
Implementation status
A converged implementation exists on feature/multi-model-task-routing
(10 files, ~1400 lines incl. tests/docs): routing service + rules file,
wiring in create_agent_config, env constants, 43 unit tests +
create_agent_config integration coverage, .env.example documentation.
Will be submitted as a Draft PR referencing this issue.
Activity
FiveFingersMountain commentedon Nov 11, 2026
Draft PR: #4332 — implementation converges to the behavior contract above; happy to adjust scope per maintainer feedback.