Enforcer

Authorization for AI agents, compared

Disclosure first: we build Enforcer, so we have an obvious bias. We have tried to write the comparison we wanted when we were choosing, which means naming the cases where something else is the better answer. Everything here is from public documentation, and we have said where we could not confirm something rather than guessing.

The two questions that actually separate these products

Where does the check run, and what do you have to keep in sync? Almost every difference that will annoy you in month three comes from those two.

ToolModelYou must sync your data into itReturns a reasonAlso handles sign-in
Open Policy AgentPolicy engine, RegoYes, via bundles or pushPartially, with decision logsNo
CerbosPolicy engine, YAMLNo, you pass context per requestYesNo
OpenFGA / SpiceDBRelationship, ZanzibarYes, dual writesLimitedNo
WorkOS FGARelationship + rolesYes, resources registered in their systemNot documented per endpointYes, via AuthKit
Permit.ioPolicy + MCP gatewayYesYesNo
Oso CloudPolicy, PolarYes, factsYesNo
Arcade.devActions runtime + tool authn/a, it runs the toolsn/aYes, tool OAuth
EnforcerPolicy over a resolved callerNo, it already holds identityYes, with the policy idYes

When each one is the right answer

Use a relationship engine (OpenFGA, SpiceDB, WorkOS FGA) when the core problem is a sharing graph. Any user shares any object with any other, arbitrary nesting, and you need to list every document a person can see. That is what Zanzibar was designed for and we would not pretend otherwise. The cost you accept is keeping a copy of your data in the permissions store.

Use Cerbos when you want a stateless policy engine you can run yourself next to your service, and you are happy passing the context in on every request. It is the simplest thing that works and has the shortest quickstart in the category, three commands and no account.

Use OPA when you already run it for infrastructure policy and want one engine. Be aware that Rego is the most complained-about part of the category.

Use Arcade when your problem is really tool authentication, holding OAuth tokens for the services an agent acts on, rather than deciding whether an action is permitted.

Use Enforcer when the question is whether this person, in this tenant, with this role and this verification status, may take this action within these limits, and you need to prove afterwards why it was allowed. Particularly where the answer depends on something the person earned, like passing an identity check.

The thing we do differently

Most of the products above are a decision layer. You hand them a subject id and they answer true or false, which means they need a copy of your data to answer at all. Enforcer signed the user in, so a policy is handed the resolved caller with role, tenant and group memberships already attached. Nothing to sync, nothing to drift.

It also means a group can be earned rather than assigned. Someone passes an identity check and lands in a group, and that group is what the rule reads, so "completed verification" and "allowed to move money" are the same recorded fact rather than two systems kept in step. That is also why a denial can say what would make it an allow, instead of returning false.

Where we are weaker

We do not do list filtering. If you need "return every document this user can see" as a query, a relationship engine will serve you better today. That is the most common gap people hit with Cerbos too, and it is honest to say we share it.

Last updated 2026-09-11. Enforcer is identity and authorization in one system, for applications and AI agents. Docs at docs.instruxi.dev. Set it up from an AI agent: docs.instruxi.dev/setup.