Skip to main content

Enforcement point tradeoffs

A decision from the PDP is only as good as the boundary that dispatches on it. The SDK supports three placements for that boundary, so it can be deployed against agents the integrator fully controls, partially controls, or does not control at all.

PlacementWhere it runsIntegrator controls the agent?Status
PEP — SidecarLocal egress proxy, one per agent processYesImplemented
PEP — GatewayShared central proxy, one per fleetYesDesign-stage (Phase 5)
PEP — Boundary adaptersAt whatever boundary is controllable: resource server, MCP proxy, or egress meshNoDesign-stage (Phase 5)

Sidecar: strongest guarantee, per-agent operational cost​

The sidecar sits on localhost next to one agent process; egress is pinned to it, so a request never reaches an upstream without a decision first. This is the deployment the how-to guide and the tutorial's decision step exercise, and the one with the most direct evidence: zero requests reach the upstream on a deny or on PDP unavailability (fail-closed), because forwarding is reachable from exactly one code path in sidecar/enforce.py. The cost is operational: one sidecar instance per agent process to deploy and keep running.

Gateway: one choke point, shared fate​

A gateway centralizes the same decision-then-forward logic behind one shared proxy instead of one per agent — simpler to operate at fleet scale, at the cost of a single point that must fail closed on its own unavailability (a gateway outage is not allowed to degrade into pass-through). See PEP — Gateway for the designed flow.

Boundary adapters: enforcement without owning the agent​

Not every agent an integrator needs to govern is one they can modify — a third-party agent, a managed connector, an agent runtime they don't operate. Boundary enforcement moves the checkpoint to whatever the integrator does control: their own resource server, an MCP-native proxy, or an injected egress mesh. These modes are explicitly ordered by strength, and the weakest — reduced-guarantee mode (coarse outer scoping plus revocation and edge audit only, no per-call narrowing) — is required to surface itself as reduced, never as a silent degrade: responses and logs carry a guarantee_level field so nobody mistakes it for full enforcement. See PEP — Boundary adapters.

Why all three share one PDP call​

Whichever placement is deployed, it asks the same question the same way — see the architecture overview for how every enforcement point routes through the same PDP and Token Exchange Service. This is what keeps "which enforcement mode is this fleet running" from becoming "which policy engine is this fleet running" — the enforcement-mode enumeration target (all three exercised by real integrators, per docs/design-doc.md's Success Criteria) is meaningful specifically because switching placement never changes the decision logic.

Where to go next​