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
)
| Parameter | Default | Description |
|---|---|---|
confidence_threshold | 0.85 | Decisions with confidence below this are routed to human_review |
Confidence Extraction
The router extracts confidence from the decision context by checking:
decision_context.confidenceattributedecision_context.outputs— list of outputs, checking each for.confidencedecision_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
)
| Parameter | Default | Description |
|---|---|---|
endpoint | required | Full OPA policy query URL |
timeout_ms | 50.0 | Query timeout in milliseconds |
cache_ttl_seconds | 60.0 | Cache entries expire after this TTL |
fallback_threshold | 0.85 | Threshold 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
| Router | Best for |
|---|---|
InternalRouter | Simple confidence threshold, no external dependencies |
OPARouter | Policy-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
- End-to-End Workflow — routing in context
- Infrastructure — Exporters — where decisions go after routing
- Features — Regulated Workflows — industry patterns