AI agent guardrails often begin as instructions: do not access sensitive data, do not execute destructive actions, and ask for approval before high-impact changes. Those instructions are useful, but they are not a security boundary.

A model can misinterpret an instruction. Retrieved content can compete with it. An application can assemble context incorrectly. A tool can be invoked through a path the prompt did not anticipate. If the same reasoning system decides what to do and whether it is allowed to do it, the control is not independent of the behavior it governs.

Open Policy Agent provides a different model: the application sends structured facts to an external policy decision point, and the enforcement layer acts on the decision. OPA separates policy decision-making from enforcement and evaluates declarative Rego policies against structured input. OPA documentation ↗

Operating principle: Let the agent propose an action. Let policy decide whether the system may execute it.

1. Put policy at the execution boundary

OPA becomes useful when the application asks for a decision where an agent crosses a meaningful boundary: sensitive retrieval, external communication, code execution, cloud changes, privileged identity operations, or delegation.

The policy check should happen after the proposed action and arguments are known, but before credentials are attached or the action is executed.

Architecture flow showing an agent proposal passing through trusted context normalization and OPA policy evaluation before tool credentials are attached and the action executes
REFERENCE ARCHITECTURE / OPA AS AN INDEPENDENT POLICY DECISION POINT

A policy decision that the application does not enforce is merely advice. The tool gateway—not the model—must own the final allow, deny, or approval behavior.

2. Give OPA facts, not prose

A useful request includes authenticated actor and tenant, agent identity and version, normalized tool and operation, target resource, environmental risk, approval state, and an immutable action digest. Trust those attributes only when they come from identity, inventory, approval, or control-plane systems—not from the model's own description.

{
  "actor": {"user_id":"user-1842","tenant_id":"blue","roles":["analyst"]},
  "agent": {"id":"incident-response-agent","version":"2026.07.3"},
  "action": {"tool":"identity_admin","operation":"revoke_sessions",
             "resource":"user-9281","effect":"write"},
  "context": {"environment":"production","human_approval":false}
}

3. Return a decision contract

Agent workflows need more than a boolean. Use explicit states such as allow, deny, require_approval, and allow_with_constraints. Return a reason, policy identifier, risk, and enforceable obligations. Unknown or malformed decisions should fail closed for privileged actions.

4. Express the guardrail in Rego

package agents.guardrails

import rego.v1

default decision := {"decision":"deny", "reason":"No policy permits action"}

decision := {"decision":"allow", "reason":"Authorized read"} if {
  input.action.effect == "read"
  input.actor.tenant_id == input.action.tenant_id
  input.action.tool in data.approved_read_tools
}

decision := {"decision":"require_approval", "risk":"high"} if {
  input.context.environment == "production"
  input.action.effect == "write"
  not input.context.human_approval
}

decision := {"decision":"allow", "reason":"Approved production write"} if {
  input.context.environment == "production"
  input.action.effect == "write"
  input.context.human_approval
  input.context.approved_action_digest == input.action.digest
}

Rego is declarative and supports schemas that improve type checking and expose incorrect input references before deployment. Rego policy-language documentation ↗

5. Bind approval to the exact action

“Human approved” is not enough. Bind the reviewer, tool, normalized arguments, target, authority, policy revision, expiration, and action digest. If the agent changes an argument after approval, the digest changes and the approval becomes invalid.

6. Define failure behavior

ACTION CLASSRECOMMENDED FAILURE BEHAVIOR
Public read-only lookupConsider bounded fail-open only when justified
Sensitive retrievalFail closed or return reduced data
External communicationFail closed
Production writeFail closed
Identity, code, or command actionFail closed

A timeout should not silently become permission. Benchmark real policies and data; OPA documents optimization and partial evaluation for latency-sensitive paths. Policy-performance guidance ↗

7. Distribute, audit, and test safely

Record the policy path, bundle revision, input schema, decision ID, result, enforcement outcome, and approval reference. OPA decision logs support bundle and trace metadata, but sensitive fields require deliberate redaction. Decision-log documentation ↗

Test missing identity, cross-tenant access, unknown tools, altered arguments, expired approvals, malformed input, stale bundles, timeouts, and conflicting rules. OPA provides a policy test framework through opa test. Policy-testing documentation ↗

Field checklist

  • Every privileged tool call passes through an enforcement point.
  • The model cannot directly access tool credentials.
  • Authorization input has identified trust sources.
  • Deny is the default for unknown privileged actions.
  • Approval is bound to the exact action.
  • Policy and schema revisions are recorded.
  • Sensitive decision-log fields are redacted.
  • Failure paths and misuse cases have tests.
  • Bundle rollout, rollback, availability, and latency are monitored.

Closing position

OPA should not decide whether an agent's reasoning is good. It should decide whether a proposed action is permitted under explicit organizational policy.

The boundary: Prompts can guide behavior. Policy can constrain authority. Secure agent design needs both—but should never confuse one for the other.