Skip to main content

Routing

Routers evaluate decision context and return a RoutingDecision indicating whether the outcome can proceed automatically or requires human review.

All routers implement:

async def route(self, decision_context: Any) -> RoutingDecision

A RoutingDecision contains:

@dataclass
class RoutingDecision:
route: str # "auto_approve" or "human_review"
reason: str # human-readable explanation
latency_ms: float # routing evaluation latency

InternalRouter

Rule-based router. Routes to human_review when confidence is below the configured threshold, or when confidence is not available.

Constructor

from briefcase.routing import InternalRouter

router = InternalRouter(
confidence_threshold=0.85, # route below this value to human_review
)
ParameterDefaultDescription
confidence_threshold0.85Decisions with confidence below this are routed to human_review

Confidence Extraction

The router extracts confidence from the decision context by checking:

  1. decision_context.confidence attribute
  2. decision_context.outputs — list of outputs, checking each for .confidence
  3. decision_context.outputs — dict, checking for "confidence" key

If no confidence is found, the decision routes to human_review.

Example

import asyncio
from briefcase.routing import InternalRouter

router = InternalRouter(confidence_threshold=0.88)

class DecisionContext:
def __init__(self, confidence):
self.confidence = confidence

result = asyncio.run(router.route(DecisionContext(0.95)))
print(result.route) # "auto_approve"

result = asyncio.run(router.route(DecisionContext(0.72)))
print(result.route) # "human_review"
print(result.reason) # "confidence 0.72 below threshold 0.88"

Configuring via setup()

from briefcase.config import setup
from briefcase.routing import InternalRouter

setup(router=InternalRouter(confidence_threshold=0.90))

OPARouter

Routes decisions by querying an Open Policy Agent (OPA) server. Caches policy decisions using an LRU cache to reduce latency. Falls back to InternalRouter on timeout or network error.

Prerequisites

pip install httpx

Constructor

from briefcase.routing import OPARouter

router = OPARouter(
endpoint="http://opa.example.com:8181/v1/data/briefcase/route",
timeout_ms=50.0, # OPA query timeout
cache_ttl_seconds=60.0, # LRU cache TTL
fallback_threshold=0.85, # InternalRouter threshold used as fallback
)
ParameterDefaultDescription
endpointrequiredFull OPA policy query URL
timeout_ms50.0Query timeout in milliseconds
cache_ttl_seconds60.0Cache entries expire after this TTL
fallback_threshold0.85Threshold for the InternalRouter fallback

OPA Input Document

The router sends this JSON document as the OPA query input:

{
"input": {
"confidence": 0.91,
"context_version": "policy-v2.1",
"function_name": "claims_review",
"tags": {}
}
}

OPA Policy Example

package briefcase

default route = "human_review"

route = "auto_approve" {
input.confidence >= 0.88
input.context_version != ""
}

OPA Response Format

The router expects OPA to return:

{
"result": {
"route": "auto_approve",
"reason": "confidence above threshold"
}
}

If result.route is absent or the request times out, the router falls back to InternalRouter with the configured fallback_threshold.

Example

import asyncio
from briefcase.routing import OPARouter

router = OPARouter(
endpoint="http://opa:8181/v1/data/briefcase/route",
timeout_ms=50.0,
cache_ttl_seconds=60.0,
fallback_threshold=0.85,
)

class DecisionContext:
def __init__(self, confidence, context_version=""):
self.confidence = confidence
self.context_version = context_version

result = asyncio.run(router.route(DecisionContext(0.93, "v2.1")))
print(result.route) # "auto_approve" (from OPA policy)
print(result.latency_ms) # latency including cache lookup

Choosing a Router

RouterBest for
InternalRouterSimple confidence threshold, no external dependencies
OPARouterPolicy-as-code, multiple routing criteria, centralized policy management

Use OPARouter with fallback_threshold set to the same value as your InternalRouter threshold. This ensures consistent behavior when OPA is temporarily unreachable.


See Also