Skip to main content
Documentation

Session-Aware Learning

Overview

Version: Latest

Session-Aware Learning

Overview

Session-aware learning keeps agent conversations stable without making session continuity a semantic route.

Each request still routes through normal decisions first. A simple task can propose a simple model, a complex task can propose a stronger model, a privacy task can propose a local model, and a domain task can propose a domain model. After that base proposal, session-aware learning decides whether to keep the current protected model for continuity, cache preservation, or a tool loop.

Key Advantages

  • Preserves model continuity during tool loops and provider-owned continuations.
  • Prices prefix-cache loss and model handoff cost before switching.
  • Supports conversation scope for agent runs and stricter session scope.
  • Lets privacy or safety decisions bypass adaptation cleanly.

What Problem Does It Solve?

Agent traffic often spans multiple requests. A later turn can look simple in isolation while still depending on a previous complex model choice, warm prefix cache, or tool-call state. Session-aware learning evaluates that stay-vs-switch trade-off after the base decision proposes a model.

When to Use

  • One agent run should stay stable across tool calls and follow-ups.
  • A session can start a new conversation that should be routed again.
  • Expensive frontier-model handoffs need a higher bar than cheap local switches.
  • Policy decisions need explicit bypass boundaries.

Configuration

global:
router:
learning:
enabled: true
adaptations:
session_aware:
enabled: true
scope: conversation
identity:
headers:
session: x-session-id
conversation: x-conversation-id
tuning:
idle_timeout_seconds: 300
min_turns_before_switch: 1
switch_margin: 0.05
cache_weight: 0.20
handoff_penalty: 0.05
handoff_penalty_weight: 1.0
switch_history_weight: 0.04
max_cache_cost_multiplier: 2.5

scope: conversation protects one agent run. A new x-conversation-id in the same x-session-id can route again, while cache and handoff cost still inform the decision. This is the right default for coding agents that create a new run for each user prompt but need model stability inside the run's tool loop.

scope: session is stricter. The session's established model is protected across conversations until the session idles out or a decision bypasses the adaptation. Use it when the application wants one session-level model choice to remain stable across multiple user-initiated runs.

ScopeWhat is protectedWhat can re-route
conversationTurns sharing the same x-conversation-idA new x-conversation-id in the same x-session-id
sessionTurns sharing the same x-session-idIdle timeout or a decision with adaptations.session_aware.mode: bypass

If the required identity headers are missing, the adaptation no-ops and the base decision result remains final.

Decision Boundaries

Most decisions do not need local configuration. The default mode is apply.

Use bypass for hard policy boundaries:

routing:
decisions:
- name: local_privacy_policy
modelRefs:
- model: local-private-model
adaptations:
session_aware:
mode: bypass

Use observe to evaluate the adaptation without changing the final model:

adaptations:
session_aware:
mode: observe

A decision can also override scope or a small tuning subset when it needs a stricter boundary than the global default:

adaptations:
session_aware:
mode: apply
scope: session
tuning:
switch_margin: 0.10

Unset local fields inherit from the global session-aware learning config. Unknown adaptation names and unsupported session_aware fields fail validation, so typos do not silently change routing behavior.

Diagnostics

Successful routed responses include a compact summary when learning ran:

x-vsr-learning-methods: session_aware
x-vsr-learning-actions: session_aware=stay
x-vsr-learning-scopes: session_aware=conversation
x-vsr-learning-reasons: session_aware=stay_has_best_adjusted_score
x-vsr-learning-modes: session_aware=apply

The headers are designed for lightweight clients and CLI displays. They contain:

HeaderMeaning
x-vsr-learning-methodsLearning methods summarized by this response.
x-vsr-learning-actionsMethod-keyed runtime results, such as session_aware=switch.
x-vsr-learning-scopesMethod-keyed protection scopes, such as session_aware=conversation.
x-vsr-learning-reasonsMethod-keyed short reasons for actions.
x-vsr-learning-modesMethod-keyed decision-level controls, such as session_aware=apply or session_aware=observe.

Client UIs should translate the compact action into user-facing routing language instead of showing the raw enum directly:

Header valueWhen it appearsSuggested display
x-vsr-learning-actions: session_aware=select with x-vsr-learning-reasons: session_aware=missing_previous_modelFirst routed request for the active scope; there is no previous protected model.Hide in the main route footer/overview. Show new run or first route for this run only in debug signals.
x-vsr-learning-actions: session_aware=stayLearning kept the current model because continuity, cache, handoff cost, or session policy outweighed the base route change.kept run model or kept session model.
x-vsr-learning-actions: session_aware=switchLearning allowed a model change after stay-vs-switch scoring.switch/run in compact route columns, with reason switch allowed and model switched in detail text.
x-vsr-learning-actions: session_aware=hard_lock with x-vsr-learning-reasons: session_aware=hard_lock=tool_loopA tool loop is active, so the model is pinned for tool-call stability.hard lock/run in compact route columns, with reason tool loop and tool-loop pinned in detail text.
x-vsr-learning-actions: session_aware=hard_lock with x-vsr-learning-reasons: session_aware=hard_lock=context_portability...Provider-specific state would not be portable across models.context pinned.
x-vsr-learning-actions: session_aware=hard_lock with x-vsr-learning-reasons: session_aware=hard_lock=min_turnsThe conversation has not reached the minimum turn count before switching.warmup pinned.
x-vsr-learning-actions: session_aware=bypassThe decision opted out of learning, for example a privacy boundary.learning bypassed.
x-vsr-learning-actions: session_aware=noopLearning was enabled but could not run, usually because identity headers were missing.Hide in the main UI. Show missing ids only in debug signals when the reason is identity_missing.

When x-vsr-learning-modes contains session_aware=observe, the action is an audit result and must be displayed as a non-applied prediction, such as would switch model or would keep run model. Status labels that are learning-specific should use neutral text styling; the selected model and decision can keep the router accent color.

Router Replay stores the full structured trace:

{
"learning": {
"adaptations": {
"session_aware": {
"mode": "apply",
"scope": "conversation",
"action": "stay",
"reason": "stay_has_best_adjusted_score",
"base_selected_model": "small-model",
"selected_model": "frontier-model",
"identity": {
"session": {
"source": "header:x-session-id",
"status": "present",
"hash": "4f2a8c0e9b7d3411"
},
"conversation": {
"source": "header:x-conversation-id",
"status": "present",
"hash": "0bb97f4a3c812efe"
}
},
"cache_warmth": 0.91,
"memory_prompt_tokens": 3840
}
}
}
}

Use the replay record when you need full debugging detail: base proposal, final model, protected current model, candidate scores, cache warmth, memory token counters, hashed identity diagnostics, phase, and hard-lock state. The response header only carries the bounded summary.

decision.algorithm.type=session_aware is removed from the public config contract. If a route needs an explicit base selector, configure a normal decision algorithm such as hybrid; otherwise omit algorithm and let the router use its default base selection.