preloader
blog post

The Missing Primitives for Trustworthy AI Agents

This is another installment of an ongoing series on building trustworthy AI Agents:

Policy-as-Code Enforcement (Part 4)

Once you can identify an agent and securely authenticate its actions, the next primitive is policy. Policies define what those agents are allowed to do, under what conditions, and against which data.

In most organizations, this logic is still scattered across YAML configs, role-based access rules, and tribal “best practices.” That approach doesn’t scale in environments where agents are making hundreds of autonomous API calls per second.

We need policy-as-code: guardrails that execute at runtime, evaluated programmatically before an action occurs. It’s not enough to lint a deployment manifest or publish a “security checklist.” The enforcement must live in the same execution path as the agent’s decisions.

From Best Practices to Runtime Guarantees

The infrastructure world learned this lesson years ago. Cloud engineers moved from static documentation (“you should encrypt S3 buckets”) to automated enforcement (“this Terraform plan will fail if encryption is missing”). AI systems need the same shift.

Runtime policy enforcement has three key properties:

  1. Declarative – Policies are written in code, version-controlled, and testable.
  2. Real-Time – Policies execute synchronously with agent actions, not as a batch audit later.
  3. Composable – Policies apply uniformly across data pipelines, agents, and APIs.

This is the difference between trusting your developers to remember rules and having the runtime refuse to violate them.

Open Policy Agent for AI Systems

Open Policy Agent (OPA) is the industry standard for enforcing policy-as-code in cloud environments. It provides a high-performance, embeddable policy engine that evaluates Rego rules at runtime.

While OPA is widely used for Kubernetes, API gateways, and microservices, the same principles apply to AI orchestration and data pipelines.

Imagine you operate a set of data agents that execute queries across multiple databases. You want to ensure:

  • Only agents with a trusted identity can access production data.
  • Queries that include PII fields must be redacted before export.
  • No agent can access data outside its designated region.

Instead of embedding these conditions across dozens of scripts, you can express them in a single, declarative Rego policy.

How Policy-as-Code Works in Practice

To make these ideas concrete, let’s walk through a minimal end-to-end example that shows how runtime policy enforcement actually operates inside an AI system.

We’ll use Open Policy Agent (OPA) to evaluate authorization rules written in Rego, and a simple Python agent to query those policies before performing any sensitive action.

Policy-as-Code Enforcement Architecture

In this setup:

  1. Rego Policy – defines the rules of what an agent can and cannot do. It describes constraints such as allowed datasets, trusted agent identities, and forbidden query patterns (for example, anything containing personally identifiable information like ssn or credit_card). The OPA engine evaluates these rules declaratively, returning an “allow” or “deny” result.
  2. Python Enforcement Layer – represents how your agent (for example, DataQueryAgent) integrates policy checks into its runtime loop. Before executing a query or calling an external API, the agent sends the request context (its identity, the target dataset, and the intended query) to OPA over HTTP. The policy engine responds instantly with a decision. If the policy denies the request, the agent blocks the action - guaranteeing that compliance guardrails are enforced at execution time.

Together, these two components illustrate what baked-in governance looks like: policies are not just written down somewhere; they are evaluated in real time, preventing violations before they occur.

Rego Policy

package ai.policy

default allow = false

# Allow access only to approved datasets
allow {
    input.agent.identity == "spiffe://trust.local/agent/data-query"
    input.dataset == "customers"
}

# Block queries that contain restricted PII fields
deny[msg] {
    re_match("(?i)(ssn|credit_card|passport)", input.query)
    msg := sprintf("Query contains restricted field: %v", [input.query])
}

# Final decision
allow_all {
    allow
    not deny[_]
}

Python Enforcement Layer

import json
import requests

OPA_URL = "http://localhost:8181/v1/data/ai/policy/allow_all"

def is_allowed(agent_identity, dataset, query):
    """Query the OPA policy engine to decide if a request is allowed."""
    payload = {
        "input": {
            "agent": {"identity": agent_identity},
            "dataset": dataset,
            "query": query
        }
    }
    
    try:
        response = requests.post(OPA_URL, json=payload, timeout=0.5)
        response.raise_for_status()  # Raise an exception for bad status codes (4xx, 5xx)
        
        decision = response.json().get("result", False)
        return decision
        
    except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
        # If policy engine fails, default to 'deny'
        print(f"⚠️ Policy engine query failed: {e}. Defaulting to DENY.")
        return False

# --- Example Usage ---
agent_identity = "spiffe://trust.local/agent/data-query"
dataset = "customers"
query = "SELECT * FROM customers WHERE ssn IS NOT NULL;"

if is_allowed(agent_identity, dataset, query):
    print("✅ Policy check passed. Executing query...")
else:
    print("❌ Policy violation detected. Query blocked.")

# --- Example 2 (Should Pass) ---
query_safe = "SELECT name, email FROM customers WHERE region = 'US-West';"
print("\n--- Running safe query ---")
if is_allowed(agent_identity, dataset, query_safe):
    print("✅ Policy check passed. Executing query...")
else:
    print("❌ Policy violation detected. Query blocked.")

Runtime Behavior

  • If the agent identity is trusted and the query does not reference restricted terms, the request passes.
  • If the query contains PII-related fields or the agent identity is unrecognized, the request fails before execution.

This pattern scales across agent ecosystems: you can embed OPA as a library, run it as a sidecar container, or deploy it as a central policy service with caching.

Why It Matters for AI Agents

As autonomous agents gain permission to write code, move data, and trigger downstream workflows, human oversight cannot scale linearly.

Policy-as-code is the control plane that keeps autonomy bounded by governance.

In a trustworthy AI stack:

  1. SPIFFE provides identity (who the agent is).
  2. OPA provides policy (what that agent is allowed to do).
  3. Audit and Attestation provide accountability (what the agent actually did).

Without runtime enforcement, your “governance” is just a hope that developers remember to follow rules.

With policy-as-code, your governance becomes executable, testable, and provable.

Practical Next Steps for Engineers

  • Experiment locally: Run an OPA instance and write basic Rego policies for your internal APIs or data jobs.
  • Integrate with SPIFFE: Pass SPIFFE identities as policy input to authorize specific agents.
  • Shift-left and runtime: Combine CI/CD checks (Terraform, Kubernetes admission controllers) with live runtime enforcement.
  • Start small: Begin with one high-impact rule-like blocking unencrypted data exports-and expand from there.

Part 5 Preview: Verifiable Audit Logs - how to make every agent action tamper-proof and cryptographically verifiable for compliance and forensic analysis.

Built for Cloud. Ready for AI.

Accelerate your cloud, data, and AI initiatives with expert support built to scale and adapt.
Partner with us to design, automate, and manage systems that keep your business moving.

Unlock Your Potential