Versioned Routing Policy
Route agent decisions through versioned, time-travelable policies — so you can prove which rule fired on any past date.
routing For: governance & auditWhen an agent’s routing choice is governed by a policy that changes over time, recording the choice is not enough. To reconstruct a past decision you need both the full policy that was in effect on the decision date and the specific rule that fired. A single-version policy store cannot answer that once the policy has changed.
The versioned routing layer stores every policy version in a bitemporal store. Publishing a new version is an append, never a mutation, so reading “the policy as of date X” returns exactly the rule set that was active then.
How it works
- Define a
PolicyVersion— an ordered list ofPolicyRules plus adefault_choice. - Publish it to a
PolicyRegistrywith avalid_fromdate; publishing is an append, so older versions are never overwritten. - Route a context through an
AgentRouter— it selects the first matching rule and recordsmatched_rule_id,policy_version, andrationale. - Reconstruct as-of a past date by passing
as_of_transaction_time— the registry returns the rule set that was active then.
Install
pip install briefcase-ai[routing]from briefcase.routing import ( AgentRouter, PolicyRegistry, PolicyRule, PolicyVersion,)Route a Ticket
This example routes a support ticket to a queue based on the ticket context, publishes a second policy version, and reconstructs the earlier decision as-of a past date.
from datetime import datetime, timezone
from briefcase.routing import ( AgentRouter, PolicyRegistry, PolicyRule, PolicyVersion,)
# 1. Define a policy: route a support ticket to a queue by context.policy_v1 = PolicyVersion( policy_id="ticket-routing", version="1.0.0", description="Route support tickets to a queue.", rules=[ PolicyRule( rule_id="enterprise-priority", condition={"plan": "enterprise", "priority": "high"}, choice="senior-queue", rationale="High-priority enterprise tickets go to the senior queue.", ), PolicyRule( rule_id="routine-lookup", condition={"category": {"in": ["faq", "status-check"]}}, choice="self-serve", rationale="Routine lookups are deflected to self-serve.", ), ], default_choice="standard-queue",)
# 2. Publish it to a versioned registry (bitemporal-backed by default).# valid_from is when the policy takes effect; transaction_time is when# the registry learned of it (defaults to now if omitted).registry = PolicyRegistry()registry.publish( policy_v1, valid_from=datetime(2026, 1, 1, tzinfo=timezone.utc), transaction_time=datetime(2026, 1, 1, tzinfo=timezone.utc),)
# 3. Route a request through the registry.router = AgentRouter( registry, use_case="ticket-routing", policy_id="ticket-routing",)
decision = router.route( {"plan": "enterprise", "priority": "high", "category": "billing"}, evidence_refs=["tkt-9001"],)
print(decision.selected) # senior-queueprint(decision.policy_version) # 1.0.0print(decision.matched_rule_id) # enterprise-priorityprint(decision.rationale) # High-priority enterprise tickets ...print(decision.evidence_refs) # ['tkt-9001']
# 4. Publish a newer version. Older decisions still reconstruct correctly.policy_v2 = PolicyVersion( policy_id="ticket-routing", version="2.0.0", description="De-escalate enterprise high-priority to the standard queue.", rules=[ PolicyRule( rule_id="enterprise-priority", condition={"plan": "enterprise", "priority": "high"}, choice="standard-queue", rationale="Updated: enterprise high-priority now goes to the standard queue.", ), ], default_choice="standard-queue",)registry.publish( policy_v2, valid_from=datetime(2026, 4, 1, tzinfo=timezone.utc), transaction_time=datetime(2026, 4, 1, tzinfo=timezone.utc),)
# Current routing uses v2.current = router.route({"plan": "enterprise", "priority": "high"})print(current.selected, current.policy_version) # standard-queue 2.0.0
# Reconstruct the decision as it would have been made before v2 was published.as_of = datetime(2026, 2, 1, tzinfo=timezone.utc)historical = router.route( {"plan": "enterprise", "priority": "high"}, as_of_transaction_time=as_of,)print(historical.selected, historical.policy_version) # senior-queue 1.0.0
# Inspect the full version history.print([v.version for v in registry.history("ticket-routing")]) # ['1.0.0', '2.0.0']flowchart LR
A["Context"] --> B["AgentRouter.route"]
B --> C["PolicyRegistry.get(as_of)"]
C --> D["PolicyVersion.select"]
D --> E{"rule matches?"}
E -- yes --> F["matched rule choice"]
E -- no --> G["default_choice"]
F & G --> H["AgentRoutingDecision"]
PolicyRule
A PolicyRule is a single “if the context matches this condition, select this
choice” rule. The condition is a small dict predicate evaluated against the
routing context.
| Field | Type | Description |
|---|---|---|
rule_id | str | Stable identifier, recorded as matched_rule_id. |
condition | dict | Predicate evaluated against the context. |
choice | str | The choice selected when the condition matches. |
rationale | str (optional) | Explanation copied into the decision record. |
condition supports three forms:
| Syntax | Meaning |
|---|---|
{"field": value} | equality |
{"field": {"in": [a, b]}} | membership |
{"field": {"ne": value}} | inequality |
All keys in a condition must match (logical AND). Call matches(context) to test
a rule directly:
from briefcase.routing import PolicyRule, PolicyVersion
rule = PolicyRule( rule_id="routine-lookup", condition={"category": {"in": ["faq", "status-check"]}}, choice="self-serve", rationale="Routine lookups are deflected to self-serve.",)
print(rule.matches({"category": "faq"})) # Trueprint(rule.matches({"category": "billing"})) # FalsePolicyVersion
A PolicyVersion is an ordered list of rules. select(context) evaluates the
rules in order and returns the first match. If no rule matches and
default_choice is set, the default is returned; otherwise choice is None
so the caller can fall back to human review.
policy = PolicyVersion( policy_id="ticket-routing", version="1.0.0", rules=[rule], default_choice="standard-queue",)
hit = policy.select({"category": "status-check"})print(hit.choice, hit.matched_rule_id) # self-serve routine-lookup
miss = policy.select({"category": "billing"})print(miss.choice, miss.matched_rule_id) # standard-queue Noneselect returns a PolicyEvaluationResult with choice, matched_rule_id,
policy_id, policy_version, and rationale.
PolicyRegistry
PolicyRegistry(store=None) is a versioned registry of policies. It defaults to
an in-memory bitemporal store; pass any BitemporalStore for durable storage.
| Method | Returns | Description |
|---|---|---|
publish(policy, *, valid_from, transaction_time=None, source=...) | BitemporalRecord | Append a new version. valid_from is a datetime. |
get(policy_id, *, as_of_transaction_time=None, as_of_valid_time=None) | PolicyVersion | The version visible at the as-of point; latest if no clamp is given. |
history(policy_id) | list[PolicyVersion] | Every published version, oldest first. |
valid_from records when a policy takes effect in the real world;
transaction_time records when the registry learned of it (defaults to now).
An as-of read clamps both, which is how a past decision reconstructs the rule
set that was active on its decision date.
AgentRouter
AgentRouter joins a registry to a use case and a policy, and produces an
AgentRoutingDecision ready to attach to a Briefcase decision snapshot.
router = AgentRouter( registry, use_case="ticket-routing", policy_id="ticket-routing", candidates_provider=None, # optional: derive candidate choices from context)route is synchronous — policy evaluation is a pure, in-memory computation
against the bitemporal store. This differs from the I/O-bound, asynchronous
BaseRouter; the two are independent abstractions.
route parameter | Description |
|---|---|
context | The dict evaluated against the policy rules. |
evidence_refs | Record IDs of the bitemporal rows that informed the decision. |
as_of_transaction_time | Reconstruct the decision using the policy active on a past date. |
The returned AgentRoutingDecision carries the full attribution:
| Field | Description |
|---|---|
selected | The chosen option (may be None if no rule and no default). |
policy_version | The version that produced the choice. |
matched_rule_id | The rule that fired, or None for the default. |
rationale | Human-readable explanation from the matched rule. |
evidence_refs | The evidence record IDs passed to route. |
candidates | The set of choices the policy could have selected from. |
Where this fits
Versioned routing is the Control act made reproducible: it records which rule fired so the decision can later be reconstructed and proven. It rests on the append-only store from the Store & Query act and feeds the tamper-evident bundles of the Prove act.