Skip to content
Docs for briefcase-ai v3.3.0see what’s new.

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 & audit

When 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

  1. Define a PolicyVersion — an ordered list of PolicyRules plus a default_choice.
  2. Publish it to a PolicyRegistry with a valid_from date; publishing is an append, so older versions are never overwritten.
  3. Route a context through an AgentRouter — it selects the first matching rule and records matched_rule_id, policy_version, and rationale.
  4. Reconstruct as-of a past date by passing as_of_transaction_time — the registry returns the rule set that was active then.

Install

Terminal window
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-queue
print(decision.policy_version) # 1.0.0
print(decision.matched_rule_id) # enterprise-priority
print(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.

FieldTypeDescription
rule_idstrStable identifier, recorded as matched_rule_id.
conditiondictPredicate evaluated against the context.
choicestrThe choice selected when the condition matches.
rationalestr (optional)Explanation copied into the decision record.

condition supports three forms:

SyntaxMeaning
{"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"})) # True
print(rule.matches({"category": "billing"})) # False

PolicyVersion

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 None

select 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.

MethodReturnsDescription
publish(policy, *, valid_from, transaction_time=None, source=...)BitemporalRecordAppend a new version. valid_from is a datetime.
get(policy_id, *, as_of_transaction_time=None, as_of_valid_time=None)PolicyVersionThe 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 parameterDescription
contextThe dict evaluated against the policy rules.
evidence_refsRecord IDs of the bitemporal rows that informed the decision.
as_of_transaction_timeReconstruct the decision using the policy active on a past date.

The returned AgentRoutingDecision carries the full attribution:

FieldDescription
selectedThe chosen option (may be None if no rule and no default).
policy_versionThe version that produced the choice.
matched_rule_idThe rule that fired, or None for the default.
rationaleHuman-readable explanation from the matched rule.
evidence_refsThe evidence record IDs passed to route.
candidatesThe 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.