Evaluating agent routing and tool-selection policies offline
June 13, 2026 · View on GitHub
skdr-eval is an offline policy evaluation library, and an LLM-agent's
routing and tool-selection choices are exactly the kind of one-shot logged
decision it was built for. If your agent stack records which tool, model, or
route it picked and what that cost, you can ask the counterfactual question —
"would this candidate routing policy have done better?" — before you ship
it.
This page is the conceptual landing page for that use case. The runnable
version is
examples/use_cases/06_agent_routing_policy.py,
and the broader story is in the
offline-evaluation companion guide.
!!! warning "Offline evaluation does not replace online validation." A green verdict says a candidate routing policy is worth an online test, not that it is safe to ship. And for genuinely sequential / long-horizon agents (multi-step plans where each action changes the state the next one sees), single-step OPE is the wrong tool — see the limitations below.
What a logged agent decision looks like
Each logged decision is a (context, action, outcome, time) tuple:
- context — request features available at decision time: prompt size, detected intent, user tier, conversation length, retrieved-context size.
- action — the discrete choice the agent made.
- outcome / reward — what you observed afterward.
- time — when the decision happened (used for time-aware splits).
Example actions
- selected tool (search vs. calculator vs. code-exec);
- selected model / route (fast-cheap vs. smart-expensive);
- handoff target (which downstream agent);
- escalation choice (auto-resolve vs. ask-human);
- policy branch (allow / deny / ask, for a guardrail policy).
Example rewards / outcomes
success, resolution, latency, cost (tokens/$), safety violation (as a
penalty), or human-correction events. Costs work as negative rewards — lower
is better — matching the policy-induction convention in
induce_policy_from_sklearn.
What support / overlap means here
The estimate is only trustworthy where the logging agent actually explored.
If your production agent almost always picks route_smart, your logs carry
little signal about a candidate that leans on route_cheap — there is no
counterfactual evidence for the actions it would newly take. skdr-eval
reports this honestly as support_health = high_risk rather than returning a
confident number. A logging agent that explores (even a little ε-greedy
jitter) keeps every route's logged probability healthy and makes offline
evaluation possible.
How DR/SNDR diagnostics apply before rollout
The workflow is the standard one (see the Daily Driver guide):
- Map traces to logs with
skdr_eval.adapters.from_records/from_jsonl_trace. - Wrap the candidate routing policy as a scikit-learn-compatible model.
- Run
evaluate_sklearn_modelsand read support health before V̂. - Use the verdict (
deploy/ab_test/insufficient_evidence/do_not_deploy) to decide whether the candidate earns an online test.
import skdr_eval
adapted = skdr_eval.adapters.from_jsonl_trace("agent_traces.jsonl", reward_col="cost")
artifact = skdr_eval.evaluate_sklearn_models(
logs=adapted.logs,
models={"router_v2": candidate_router},
y_col="cost",
fit_models=True,
policy_train="pre_split",
)
print(artifact.warnings[["model", "estimator", "support_health"]])
Relation to the agent ecosystem
In an agent stack such as the Weaver stack, the upstream components produce the logs this page consumes:
- contextweaver routing logs → the
(context, action)for model/route selection; - AgentFence allow / deny / ask decisions → a guardrail-policy action with a safety-violation outcome;
- agent-kernel
ActionTracerecords → the per-decision trace mapped viafrom_records.
skdr-eval is the offline evaluation layer for those governance
decisions — it does not run the agent or route traffic; it judges a candidate
policy from the logs the stack already emits. See
weaver-stack.md for the end-to-end companion story.
When OPE is the wrong tool for agents
- Sequential / long-horizon plans — when an action changes the state the next action sees, you need reinforcement-learning OPE (SCOPE-RL / d3rlpy), not single-step contextual-bandit DR. See comparisons.
- No exploration in the logs — a near-deterministic logging agent leaves no overlap; gather exploratory logs first.
- Reward you cannot measure offline — if the outcome only exists after a human interacts live, offline evaluation cannot estimate it.