Skip to main content

OpenID AuthZEN policy backend for Microsoft Agent Governance Toolkit

Project description

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 enforcedpdp_url must use HTTPS in production. HTTP is allowed only for localhost / 127.0.0.1 / [::1] during development.
  • Error sanitizationhttpx 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 loggingclient_secret and token fields use repr=False so they never appear in logs, tracebacks, or __repr__ output.
  • Injection protectionextra_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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

authzen_policy_backend-0.1.2.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

authzen_policy_backend-0.1.2-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

Details for the file authzen_policy_backend-0.1.2.tar.gz.

File metadata

  • Download URL: authzen_policy_backend-0.1.2.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for authzen_policy_backend-0.1.2.tar.gz
Algorithm Hash digest
SHA256 faadf04b90dd06814f93d76379e42b45b02b2c993c591ec6da15814056acf6a9
MD5 346443abaf68d04deb65c6db6cb3d8e1
BLAKE2b-256 33edbbff228dbc25f5b6254f389236d69ae1728d88704ad0756f90a18a1413a0

See more details on using hashes here.

File details

Details for the file authzen_policy_backend-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for authzen_policy_backend-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7650d20071d300486180b23643b256ada970cc9de6a07354a5011b51d1252f3f
MD5 b463b01c1cde289fa50ac7f1f4c8685c
BLAKE2b-256 5a741f1e9de690d95d99f5e68198ae3d95d54460445dc0ee3e7d001600d1d8cd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page