Model Routing¶
routing
¶
Difficulty-based model routing for skill runs.
The router asks an agent (running on the harness default model, inside the
same sandbox as the real run) to rate a task as low, medium or
high difficulty and to write that rating to _run/route.json. The
host then maps the rating to a :class:ModelTier (a model id plus a default
reasoning effort) and runs the actual skill on it.
This module is pure: it knows nothing about backends or containers. The
caller supplies a :class:RunCallable that performs one agent invocation,
which keeps :func:classify testable without a sandbox.
Every classifier failure falls back to the caller-supplied default tier, so routing can never make a run worse than an unrouted one.
TIER_NAMES = ('low', 'medium', 'high')
module-attribute
¶
Difficulty tiers, from cheapest to strongest.
DEFAULT_CLASSIFIER_MAX_TURNS = 10
module-attribute
¶
Default turn cap for the classifier run (only enforced where the CLI supports it).
ROUTE_FILENAME = 'route.json'
module-attribute
¶
File the classifier writes under <work_dir>/_run/.
CLASSIFIER_OUTPUT_FILENAME = 'classifier-output.txt'
module-attribute
¶
Raw classifier stream, written under <work_dir>/_run/.
ModelTier(model, effort=None)
dataclass
¶
One routing tier: a model id plus the default reasoning effort for it.
effort is harness-specific (see :attr:HarnessModels.efforts).
None means "resolve normally": the effort env var, else the registry
default_effort. Only the literal override value none (via
--effort or the env var) disables the effort flag.
RouteDecision(model, effort, tier, source, reason='')
dataclass
¶
Outcome of routing one skill run.
source is "classifier" when the agent's rating was used,
"forced" when the caller pinned a tier, and "fallback" when the
classifier failed and the default model was used instead. tier is
None on fallback.
RouteError
¶
Bases: ValueError
Raised when the classifier's route file is missing, malformed, or invalid.
RunCallable
¶
Bases: Protocol
One agent invocation inside an already-prepared sandbox.
route_path(work_dir)
¶
resolve_model_tiers(harness, overrides)
¶
Overlay overrides on the harness default tier map and validate it.
Raises ValueError for an unknown tier name, an empty model id, or an
effort value the harness rejects, so configuration errors surface before
any container is started.
Source code in src/agentic_ci/routing.py
build_classifier_prompt(task_prompt, *, route_file=f'_run/{ROUTE_FILENAME}', max_files=DEFAULT_CLASSIFIER_MAX_TURNS)
¶
Build the prompt that asks the agent to rate task_prompt.
Source code in src/agentic_ci/routing.py
load_route(path)
¶
Read the classifier's route file and return (difficulty, reason).
Raises :class:RouteError when the file is missing, is a symlink, is not
a JSON object, or names a difficulty outside :data:TIER_NAMES.
Source code in src/agentic_ci/routing.py
forced_route(tier, tiers)
¶
Return a decision that pins tier without running the classifier.
Source code in src/agentic_ci/routing.py
classify(run, *, work_dir, task_prompt, tiers, classifier_model, classifier_effort, classifier_args, fallback, prompt_builder=None)
¶
Run the classifier and map its rating to a :class:RouteDecision.
run performs one agent invocation. The classifier prompt is built by
prompt_builder (default :func:build_classifier_prompt) from
task_prompt. Any failure (exception, non-zero exit, missing or invalid
route file) logs a warning and returns a "fallback" decision using
fallback; this function never raises on classifier failure.