Start Free Trial
← Back to Blog

The Agent Isn't Enough: Why the Principal Has to Be Part of the Enforcement Model

Agent policy tells you what a role is permitted to do. It doesn't tell you who is actually behind the call. In regulated industries, that gap is the one that gets you in front of an auditor.

When we designed AutoPIL's original enforcement model, we organized it around the agent: register the agent, bind it to a policy, evaluate every request against that policy. The agent's registered role determines what it can access and what it can do. That model works well — it's fast, deterministic, and auditable.

But there's a question it can't answer, and it came up in almost every serious enterprise conversation we had in the first few months: which human authorized this action?

An agent might be a wealth_advisor with a policy that allows access to portfolio_holdings and client_profile. Fine. But the wealth advisor agent doesn't operate in a vacuum. It's invoked by a person — an analyst, an advisor, an operations staff member — and in a regulated industry, that person's entitlements matter as much as the agent's policy. A Series 65-licensed advisor should be able to pull those holdings. An operations analyst running a routine workflow probably should not, even if they trigger the same agent.

The enforcement model that only checks agent policy misses the second half of that question entirely.

What we built and why

We added principal_id to every evaluation request and every audit event. It's the identity of the human — or the downstream system acting on behalf of a human — behind the call. From there, we extended the policy YAML to let you specify entitlement requirements tied to specific sources, tasks, or sensitivity levels.

The enforcement model is now a two-sided intersection:

Enforcement model

ALLOW = agent_policy.ALLOW ∩ principal.has_entitlement
Either side can deny. Both sides have to pass.

This matters because it reflects how access control actually works in an enterprise. IAM governs what the service account can reach. Entitlements govern what the person can authorize. Treating these as separate systems that don't talk to each other is how you end up with an audit trail that shows what happened but not who sanctioned it.

What it looks like in a policy

The new require_principal_entitlements section sits alongside the existing allowed sources and denied sources in a policy file. Here's a simplified excerpt from a wealth management policy:

wealth.yaml — wealth_advisor_policy
require_principal_entitlements:
  # Only licensed advisors can pull holdings and client profiles
  - sources: [portfolio_holdings, client_profile]
    require_any: [group:licensed-advisors, role:series-65]

  # Rebalancing recommendations require a licensed advisor, full stop
  - tasks: [rebalancing_recommendation]
    require_all: [group:licensed-advisors]

  # Anything classified high sensitivity requires the same gate
  - sensitivity: [high]
    require_any: [group:licensed-advisors, role:series-65]

The matchers — sources, tasks, sensitivity — are all optional. Omitting them means the rule applies to every request under that policy. Multiple rules in the same policy are ANDed: the principal has to satisfy all of them that match the current request, not just one.

Where the principal identity comes from

There are two ways to pass a principal_id into an evaluation:

Per-call: include principal_id directly in the POST /v1/context/evaluate request body, alongside the agent ID and source. This works well for one-off calls and for frameworks where each tool invocation is independent.

Session-level binding: open a session with POST /v1/sessions and attach the principal_id there. Every evaluate call that references that session inherits the principal automatically — you don't pass the identity on every call. This is the right pattern for multi-step agent workflows where a single human action triggers a chain of tool calls. You set the principal once at the start of the session and every downstream decision is stamped with it.

The entitlement claims themselves come from your identity provider via JWT. AutoPIL's JWTClaimsResolver verifies the token signature and extracts the group and role claims. If you pass a valid JWT, the claims are used. If you don't, and the policy requires entitlements, the call is denied — the resolver doesn't fail open.

What changes in the audit trail

Before this change, the audit trail answered: what agent made this request, what did the policy say, and what was the decision? That's useful. But in a regulated context — a compliance review, an internal investigation, a regulatory exam — the question that comes next is always and who was the human behind it?

Now every audit event carries principal_id alongside the agent ID, the session, the source, the task, the sensitivity level, the decision, and the policy version in force at the time. The record is complete enough to answer the accountability question without reconstructing it from scattered logs.

We also added denial_type to every denied event — a field that classifies why the request was denied:

The distinction between policy and entitlement denials turns out to be more useful than it sounds. A spike in entitlement denials tells you that agents are being invoked by principals who aren't provisioned for the task — a workflow misconfiguration or an onboarding gap, not a policy problem. A spike in policy denials might mean a policy is misconfigured or an agent is being used in a context it wasn't designed for. These require different responses, and conflating them in the audit log makes both harder to diagnose.

The broader principle

There's a pattern in enterprise AI governance that I keep seeing: platforms are built around the agent as the unit of trust. Register the agent, trust the agent, audit the agent. That's a reasonable starting point when agents are simple and their invocation context is controlled.

It breaks down when agents become shared infrastructure — when multiple workflows, multiple teams, and multiple principals trigger the same agent in different contexts with different levels of authority. At that point, the agent's identity alone isn't a sufficient account of what happened. You need to know the full chain: who authorized it, under what entitlements, in what session, governed by what policy version.

That's what principal_id on the enforcement path gives you. Not just a richer audit log — a fundamentally more complete model of who is accountable for each decision the system makes.


Anil Solleti is the founder of AutoPIL, a governance-first agentic AI platform for regulated enterprises, and a partner at VibrantCapital.ai.

See principal-scoped enforcement in action

AutoPIL enforces both agent policy and human entitlements at the retrieval layer — every decision stamped with the principal who authorized it, auditable and tamper-evident.

Start Free Trial