Skip to content

[Feature] Multi-model task routing: dispatch agent runs to the right model in the agent's own pool #4331

Open

Description

@FiveFingersMountain

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:

  1. When MODEL_ROUTING_ENABLED=true and 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 configured model_ids pool.
  2. Everything else stays exactly as today.

Behavior contract

  1. Explicit request-level model_id always wins; routing never overrides it.
  2. With MODEL_ROUTING_ENABLED=false (default) behavior is identical to the
    current release.
  3. Routing only selects models the tenant already validated and the agent
    already configured (no permission-boundary change).
  4. No classification signal → keep the existing selection (routing never
    guesses).
  5. No capable candidate / exhausted fallback → keep the existing selection
    (routing never fails a run).
  6. Tier fallback (quick_qa → long_context → deep_reasoning) is recorded in
    the audit record (fallback_from).
  7. Ties break stably by input order; same pool + same query → same decision.

Configuration surface

  • MODEL_ROUTING_ENABLED (env, default false)
  • 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

  1. Per-agent explicit task tag: which carrier is acceptable? context_policy
    is validated by PolicyLayers(extra="forbid") and cannot take extra keys.
    Candidates: dedicated column, metadata field, or tag entity.
  2. Should the switch stay env-level, or do tenants/agents need a per-agent
    toggle on top?
  3. 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

  1. FiveFingersMountain commented on Nov 11, 2026

    @FiveFingersMountain
    Author

    Draft PR: #4332 — implementation converges to the behavior contract above; happy to adjust scope per maintainer feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions