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

Govern Agent Actions

guardrails routing For: platform & governance

Recording a decision tells you what did happen. Governing one means deciding what is allowed to happen — before the action runs. This guide adds two controls to the support-triage agent: a guardrail that authorizes the action, and a versioned policy that decides where it goes.

Terminal window
pip install briefcase-ai[guardrails,routing]
  1. Define a guardrail

    A guardrail answers one question: may this agent perform this action on this resource? Subclass BaseGuardrailEnv and implement evaluate, returning an EvalResult with an Effect.

    from briefcase.guardrails import BaseGuardrailEnv, EvalRequest, EvalResult, Effect
    class QueueGuardrail(BaseGuardrailEnv):
    @property
    def name(self) -> str:
    return "queue_access"
    @property
    def request_space(self):
    return {}
    def evaluate(self, request: EvalRequest) -> EvalResult:
    allowed = request.context.get("priority") == "high"
    return EvalResult(
    effect=Effect.ALLOW if allowed else Effect.DENY,
    guardrail_name=self.name,
    reason="priority check",
    )
  2. Evaluate before acting

    Build the request that describes the action, evaluate it, and only proceed if it is allowed.

    guardrail = QueueGuardrail()
    request = EvalRequest(
    agent="triage-bot",
    action="route",
    resource="queue:senior",
    context={"priority": "high"},
    )
    result = guardrail.evaluate(request)
    if result.is_allowed:
    ... # perform the action
  3. Compose a pipeline and fail closed

    Real systems chain several guardrails. A GuardrailPipeline evaluates them in order and denies on the first denial (its default mode). Wrap the call so that any error becomes a denial — controls must fail closed, never open.

    from briefcase.guardrails import GuardrailPipeline
    pipeline = GuardrailPipeline(stages=[guardrail])
    def is_allowed(request: EvalRequest) -> bool:
    try:
    return pipeline.evaluate(request).is_allowed
    except Exception:
    return False # fail closed: an error never grants access
  4. Route the allowed action through a versioned policy

    Once an action is permitted, decide where it goes — using a policy you can reconstruct later. Publishing a policy version is append-only, so the rule that fired is always recoverable.

    from datetime import datetime, timezone
    from briefcase.routing import PolicyRegistry, PolicyVersion, PolicyRule, AgentRouter
    registry = PolicyRegistry()
    registry.publish(
    PolicyVersion(
    policy_id="ticket-routing",
    version="1",
    rules=[PolicyRule(
    rule_id="high-priority",
    condition={"priority": "high"},
    choice="senior-queue",
    rationale="High-priority tickets go to the senior queue.",
    )],
    default_choice="standard-queue",
    ),
    valid_from=datetime.now(timezone.utc),
    )
    router = AgentRouter(registry, use_case="ticket-routing", policy_id="ticket-routing")
    decision = router.route({"priority": "high"})
    print(decision.selected, decision.matched_rule_id, decision.policy_version)

Where this fits