Policy Engine

The component that evaluates declarative Rego policy on every tool call. Where intent enforcement asks "did the user authorize this action," the policy engine asks "is this action allowed under the rules for this role, at this scale, against this destination." Built on Open Policy Agent's Rego language, the policy engine enforces the destructive-verb deny-list, bulk-row ceilings, value thresholds on financial verbs, and approved-destination lists for outbound webhooks. It is the third check in the IntentGate authorization pipeline.

Why a dedicated policy engine

Capability tokens decide which tools an agent may attempt. Intent enforcement decides whether the agent is acting on the user's authorization. Neither covers the per-call rules a security team needs to enforce: that delete calls must touch fewer than 100 rows, that transfer_funds must stay under €5,000 per call for the AP-clerk role, that webhook posts may only target IBANs on an approved-vendor list, that any call against the customer database must include a tenant predicate. These are the rules that translate organizational policy into runtime enforcement, and they live in the policy engine.

Without a policy engine, these rules end up scattered across application code, expressed differently in each service, and inconsistently enforced. The OWASP LLM06 (Excessive Agency) and AGENT02 (Tool Misuse) risks are largely failures of policy enforcement: agents have access to tools that technically support destructive or large-scale actions and there is nothing inline to refuse those actions on out-of-policy calls.

Why Rego and Open Policy Agent

IntentGate uses Open Policy Agent (OPA) as the policy engine and Rego as the policy language. OPA is a CNCF graduated project, widely used for Kubernetes admission control, microservice authorization, and API gateway policy. Choosing OPA means policies are portable (the same Rego runs in CI for testing as runs in the gateway for enforcement), testable independently of IntentGate (Rego has a built-in testing framework), and written in a language your platform team likely already knows.

Policy logic is auditable, version-controlled, and reviewable the same way infrastructure code is. A policy change goes through pull request, code review, and CI tests before being bundled and deployed to the gateway. The bundle includes a hash that the gateway logs on every evaluation, so any decision can be traced back to the exact policy version that made it.

The four policy patterns

IntentGate's policy engine ships with four canonical patterns; customers extend them with custom Rego for organization-specific rules.

Destructive-verb deny-list. Rules that block tool calls whose resolved verb falls into a defined set of destructive operations — delete, drop, truncate, mass-update — unless the calling agent's role explicitly permits the specific verb. This is the runtime principle of least privilege for agent actions: an agent is blocked by default from invoking destructive verbs, even when the underlying tool API technically supports them. The deny-list is the defence against the "agent steered into mass deletion" attack class.

Bulk-row ceilings. Rules that cap the number of rows a tool call can return or modify in a single invocation. The gateway inspects the resolved query (for reads) or the predicate (for writes) and refuses calls that exceed the configured ceiling. A list_customers call with no filter that would return 14,238 rows is refused if the ceiling is 1,000. A delete_records call whose WHERE clause matches 50,000 rows is refused if the ceiling is 100. Bulk-row ceilings defeat the mass data hijack and mass destructive write attack classes simultaneously.

Value thresholds on financial verbs. Rules that cap the value of a single tool-call argument. The classic example: transfer_funds blocked above the per-role ceiling. An AP clerk's role may authorize transfer_funds up to €5,000; calls above that amount are refused regardless of the agent's reasoning. Combined with approved-destination IBAN lists, this is the defence against the financial-verb variant of agent hijack — where the user's intent (process invoice) is legitimate but the hijacked agent rewrote the amount and destination.

Approved-destination lists. Rules that constrain outbound calls (webhooks, email sends, API forwards) to a defined set of approved destinations. A post_to_webhook call to an attacker-controlled URL is refused; only URLs on the approved-vendor list are allowed. This is the egress control for the agent layer, analogous to network egress filtering at the perimeter but enforced semantically at the tool-call layer.

Error code and observability

Policy failures return JSON-RPC error code −32012. The error payload includes the rule that failed (destructive-verb, bulk-row, value-threshold, approved-destination, or custom), the resolved tool call, and the specific predicate that was violated. SIEM adapters route on the error code and on the rule type; operators build alerts for clusters of value-threshold failures (often financial-verb hijack attempts) or bulk-row failures (often mass exfil attempts) without parsing the payload.

Related controls

The policy engine runs after intent enforcement and shares the same fail-closed semantics. See the Agent Runtime Authorization category page for the full pipeline, the Glossary for the Rego, destructive-verb, bulk-row, and value-threshold entries, and the Standards Alignment page for how the policy engine maps to OWASP, NIST, and EU AI Act requirements.

Frequently asked questions

Why Rego instead of a custom policy language?

Rego is the declarative policy language used by Open Policy Agent, a CNCF graduated project widely used for Kubernetes admission control, microservice authorization, and API gateway policy. Using Rego means policies are portable, testable independently of IntentGate, and written in a language your platform team likely already knows. Policy logic is auditable, version-controlled, and reviewable the same way infrastructure code is.

What is a destructive-verb deny-list?

A destructive-verb deny-list is a Rego rule that blocks tool calls whose resolved verb falls into a defined set of destructive operations — delete, drop, truncate, mass-update — unless the calling agent's role explicitly permits the specific verb. It is the runtime equivalent of "principle of least privilege" applied to agent actions: agents are blocked by default from invoking destructive verbs even when the underlying tool API technically supports them.

How do bulk-row ceilings work?

A bulk-row ceiling is a policy rule that caps the number of rows a tool call can return or modify in a single invocation. The gateway inspects the resolved query (for reads) or the predicate (for writes) and refuses calls that exceed the configured ceiling. Bulk-row ceilings defeat two attack classes: mass data hijack via a hijacked agent calling list_customers without a filter, and mass destructive writes via a hijacked agent calling delete with a permissive WHERE clause.