Skip to main content

authzen-policy-backend

PyPI Python License: MIT Typed

OpenID AuthZEN policy backend for the Microsoft Agent Governance Toolkit.

Connect any AuthZEN-compliant Policy Decision Point (PDP) to Microsoft's Agent Governance Toolkit as a pluggable ExternalPolicyBackend — with one add_backend() call.

┌────────────────────────────────────────────────────────────────┐
│                    Your AI Agent                                │
│  (LangGraph, OpenAI Agents, AutoGen, custom, ...)              │
└──────────────────────┬─────────────────────────────────────────┘
                       │ evaluate(context)
┌──────────────────────▼─────────────────────────────────────────┐
│            MS Agent Governance Toolkit                          │
│  PolicyEvaluator  →  YAML rules (fast local)                   │
│                   →  AuthZENBackend (this package)              │
└──────────────────────┬─────────────────────────────────────────┘
                       │ POST /access/v1/evaluation
┌──────────────────────▼─────────────────────────────────────────┐
│              AuthZEN PDP                                        │
│  (EmpowerNow ARIA, Cerbos, Aserto, or any compliant PDP)      │
│  → Obligations, Constraints, Advice, Delegation, Budget        │
└────────────────────────────────────────────────────────────────┘

Why

The Agent Governance Toolkit provides in-process YAML policy evaluation and optional OPA/Cedar backends. For enterprise deployments, you need:

  • Centralized policy management — one PDP governs all agents, not scattered YAML files
  • Standards-based authorization — OpenID AuthZEN, not proprietary policy formats
  • Rich decisions — obligations, constraints, budget limits, and denial advice beyond binary allow/deny
  • Delegation-aware identity — user-bound agents with scoped capabilities
  • Audit-grade decisions — decision IDs that link to cryptographic receipts

This package bridges that gap with a single add_backend() call.

Installation

pip install authzen-policy-backend

Quick Start

Minimal — 3 Lines to Policy Evaluation

from agent_os.policies import PolicyEvaluator
from authzen_backend import AuthZENBackend

evaluator = PolicyEvaluator()
evaluator.add_backend(AuthZENBackend(
    pdp_url="https://pdp.example.com/access/v1/evaluation",
    pdp_application="my-agent-platform",
    token="my-bearer-token",
))

decision = evaluator.evaluate({
    "tool_name": "file_read",
    "agent_id": "travel-agent-1",
    "user_id": "alice",
})

print(decision.allowed)       # True / False
print(decision.reason)        # Human-readable reason from PDP
print(decision.evaluation_ms) # Round-trip time in ms

Client Credentials — Production Auth

from authzen_backend import AuthZENBackend, ClientCredentialsAuth

backend = AuthZENBackend(
    pdp_url="https://pdp.example.com/access/v1/evaluation",
    pdp_application="my-agent-platform",
    client_credentials=ClientCredentialsAuth(
        token_endpoint="https://idp.example.com/oauth/token",
        client_id="agent-policy-client",
        client_secret="...",
        audience="pdp",
    ),
)

# Tokens are cached and refreshed automatically
decision = backend.evaluate({
    "tool_name": "transfer_funds",
    "agent_id": "finance-bot",
    "user_id": "bob",
})

Async Backend — For Async Agent Runtimes

from authzen_backend import AsyncAuthZENBackend

async with AsyncAuthZENBackend(
    pdp_url="https://pdp.example.com/access/v1/evaluation",
    pdp_application="my-agent-platform",
    token="my-bearer-token",
) as backend:
    result = await backend.evaluate({
        "tool_name": "deploy_service",
        "agent_id": "ops-agent",
    })

ARIA-Enhanced Context — Obligations, Constraints, Advice

When connected to an EmpowerNow ARIA PDP, extract rich governance context that generic AuthZEN backends don't provide:

from authzen_backend import AuthZENBackend
from authzen_backend.aria import extract_aria_context

backend = AuthZENBackend(
    pdp_url="https://aria-pdp.example.com/access/v1/evaluation",
    pdp_application="my-platform",
    token="...",
)

result = backend.evaluate({
    "tool_name": "transfer_funds",
    "agent_id": "finance-bot",
    "user_id": "bob",
    "amount": 50000,
})

aria = extract_aria_context(result)
print(aria.decision_id)       # Links to a signed receipt in Receipt Vault
print(aria.obligations)       # Actions the caller must perform
print(aria.constraints)       # Parameter-level restrictions
print(aria.advice)            # Structured denial guidance with remediation
print(aria.requires_approval) # True if human-in-the-loop approval needed

How It Works

sequenceDiagram
    participant Agent as Your Agent
    participant PE as PolicyEvaluator
    participant AZB as AuthZENBackend
    participant PDP as AuthZEN PDP

    Agent->>PE: evaluate(context)
    PE->>AZB: evaluate(context)
    Note over AZB: Map flat dict to<br/>AuthZEN 1.0 request
    AZB->>PDP: POST /access/v1/evaluation
    PDP-->>AZB: { decision, context }
    Note over AZB: Extract reason,<br/>obligations, constraints
    AZB-->>PE: BackendDecision
    PE-->>Agent: Final decision

Context Mapping

The toolkit passes a flat dict to backends. This package maps it to a structured AuthZEN request:

Toolkit Context Key AuthZEN Field Notes
agent_id subject.id Normalized to ARN: auth:agent:agentmesh:{id}
user_id subject.properties.bound_to_user_id User the agent acts for
delegator subject.properties.delegator Delegation chain
tool_name action.name, resource.id Also generates op:tool:{name}
action action.name Overrides tool_name if present
resource_type resource.type Defaults to mcp_tool
resource_id resource.id Defaults to tool_name
(all others) context.* Forwarded as-is

context.pdp_application and action.properties.operation_ref_id are set automatically.

Custom Mapping

Override field names if your agents use different context keys:

from authzen_backend import AuthZENBackend, FieldMapping

backend = AuthZENBackend(
    pdp_url="https://pdp.example.com/access/v1/evaluation",
    pdp_application="my-platform",
    token="...",
    mapping=FieldMapping(
        agent_id_key="principal",
        tool_name_key="operation",
        user_id_key="end_user",
    ),
)

Fail-Closed vs Fail-Open

flowchart TD
    A[PDP call fails] --> B{fail_closed?}
    B -->|"True (default)"| C["Return deny<br/>error = None"]
    B -->|False| D["Return deny<br/>error = description"]
    C --> E[Toolkit stops — hard deny]
    D --> F[Toolkit tries next backend]
  • fail_closed=True (default): PDP errors produce an authoritative deny. The toolkit treats this as final and does not consult other backends. Use this for production.
  • fail_closed=False: PDP errors set the error field on the BackendDecision. The toolkit skips this backend and tries the next one, or falls back to its default action. Use this for multi-backend setups where another backend can decide.

Configuration Reference

Parameter Type Default Description
pdp_url str (required) AuthZEN evaluation endpoint URL
pdp_application str (required) Application ID for policy scoping
token str None Static Bearer token (mutually exclusive with client_credentials)
client_credentials ClientCredentialsAuth None OAuth client credentials config
timeout float 5.0 HTTP timeout in seconds
default_resource_type str "mcp_tool" Fallback resource type
default_subject_type str "ai_agent" Fallback subject type
mapping FieldMapping DEFAULT_MAPPING Context field name overrides
fail_closed bool True Hard deny on errors (True) or signal error (False)
http_client httpx.Client None Inject a pre-configured HTTP client

Security

  • HTTPS enforced — pdp_url must use HTTPS in production. HTTP is allowed only for localhost / 127.0.0.1 / [::1] during development.
  • Error sanitization — httpx exceptions are reduced to safe descriptions (HTTP 503, PDP request timed out) so URLs, tokens, and response bodies are never leaked in logs or error messages.
  • No credential logging — client_secret and token fields use repr=False so they never appear in logs, tracebacks, or __repr__ output.
  • Injection protection — extra_params cannot override OAuth core fields (grant_type, client_id, client_secret).

See SECURITY.md for reporting vulnerabilities.

Testing

70 tests | 100% coverage | mypy strict | ruff

pip install -e ".[dev]"
pytest tests/ -v
ruff check src/ tests/
mypy src/

Compatibility

Component Version
Python 3.10+
Dependencies httpx >=0.27, pydantic v2
Agent Governance Toolkit Any version with ExternalPolicyBackend
PDP Any OpenID AuthZEN 1.0 compliant PDP

This package has zero dependency on agent-os-kernel — it implements the ExternalPolicyBackend protocol structurally (duck typing). Install alongside the toolkit or use standalone.

Looking for AGT-native integration? If you're using AGT's ToolCallInterceptor, AuditBackend, or PolicyProviderInterface extension points, see aria-agentkit — which builds on this package and provides contract-tested adapters for the full AGT surface.

Links

License

MIT — see LICENSE.

Metadata

Release files for authzen-policy-backend 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for authzen-policy-backend 0.1.2
File Size Uploaded
authzen_policy_backend-0.1.2.tar.gz 21.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for authzen-policy-backend 0.1.2
File Interpreter ABI Platform
authzen_policy_backend-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 37.6 kB

Release files / authzen_policy_backend-0.1.2.tar.gz

Download URL authzen_policy_backend-0.1.2.tar.gz
Size 21.2 kB
Tags Source
SHA-256 checksum
How to use checksums
faadf04b90dd06814f93d76379e42b45b02b2c993c591ec6da15814056acf6a9
BLAKE2b-256 checksum
How to use checksums
33edbbff228dbc25f5b6254f389236d69ae1728d88704ad0756f90a18a1413a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.10

Release files / authzen_policy_backend-0.1.2-py3-none-any.whl

Download URL authzen_policy_backend-0.1.2-py3-none-any.whl
Size 16.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7650d20071d300486180b23643b256ada970cc9de6a07354a5011b51d1252f3f
BLAKE2b-256 checksum
How to use checksums
5a741f1e9de690d95d99f5e68198ae3d95d54460445dc0ee3e7d001600d1d8cd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.10

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page