Policies
Guardrails decide whether content is safe. Policy decides whether a caller is allowed to make the request at all, based on identity, context, and organisational rules. Gateway OPA runs before Surface-level OPA, and a gateway deny is final. Cost and usage governance →
OPA
OPA is the embedded Rego policy engine used by Agent Stream, so policies are compiled and evaluated in-process with no sidecar or network round trip.
Gateway-Level Policy
Gateway-Level Policy is the OPA policy attached to the appliance itself and evaluated as the gateway-level gate before any Surface-level checks. A gateway deny is final: no Surface-level policy can override it.
Surface-Level Policy
Surface-Level Policy is the OPA policy attached to a Surface and evaluated after Gateway-Level Policy. LLM Surface policies use the package llm.policy; IDE Surface policies use the package ide.policy.
How front-door policy tells discovery apart from dispatch
The IDE Surface’s OPA input distinguishes discovery (GET /v1/models, which a policy can allow unauthenticated) from dispatch (POST /v1/chat/completions, which requires the signed-in caller), so sign-in never hits a chicken-and-egg where a client cannot fetch the sign-in profile because it is not yet signed in.
How a policy reference points to a reusable definition
- Policy Reference: A pointer from a Surface or a Gateway field to a stored OPA policy definition.
- Policy Definition: Stored Rego source plus metadata that can be reused by many Surfaces or Gateways. Definitions are immutable per version and carry a content hash so audit evidence can prove the exact bytes that ran.
A surface or gateway can also enforce more than one policy at once (policy_definition_ids); the combination is deny-overrides, so every referenced policy must allow a request for it to proceed. An administrator can additionally mark one or more policies as enforced globally across every surface of a type, ANDed with that surface’s own policy set, with a monitor-only rollout mode for observing the effect of a global policy before it blocks anything.

Model Allow-List
A Model Allow-List is a member-level list of models the Member is permitted to invoke. A request to a model that is not on the allow-list is rejected with 403 model_not_allowed.
What each of the four policy layers checks
Rego policy is evaluated at four distinct layers, each its own package queried at a fixed path. A deny at any layer stops the request immediately, and a layer earlier in this table cannot be overridden by an allow at a layer later in it:
| Layer | Package | Applies to |
|---|---|---|
| Trust Fabric | agentstream.policy | Appliance-to-appliance (DIDComm) traffic. Evaluated first; a deny here is final. |
| Surface / fabric | surface.policy | A2A/MCP-style fabric surfaces. Carries the richest input of any layer. |
| LLM Surface | llm.policy | LLM, API, MCP, and Webhook surfaces. |
| IDE front door + per-member Model Policy | ide.policy / llm.policy | The IDE catalogue’s front door, then, after it passes, each catalogue member’s own policy. |
The dashboard labels the first row Trust Fabric; agentstream.policy is retained only as the internal Rego package name, unchanged in stored policies and audit evidence.
What a policy can see
Agent Stream builds this input document automatically before every evaluation. A policy only ever reads from it and never declares or constructs input itself. Only the fields relevant to the current request are populated, and everything else is omitted:
{
"http": { "method": "POST", "path": "/v1/chat/completions" },
"source_auth": { "jwt_bearer": { "subject": "user-123", "claims": { "role": "admin" } } },
"resource": { "model": "gpt-5.5", "surface_type": "llm" },
"action": "dispatch",
"environment": { "now": "2026-01-01T00:00:00Z" },
"channel": { "variant_alias": "beta" },
"identity_binding": { "verified": true, "issuer_did": "did:web:issuer.example" }
}A policy reads a value with plain dot notation, such as input.source_auth.claims.role == "admin" to check a JWT claim, or input.resource.model to gate on the requested model. See Input document → for the complete field-by-field reference, including the fields not shown here.
Policies are immutable and versioned
Editing a policy never overwrites it: each save appends a new, numbered version, and prior versions are retained permanently. Every decision, especially a denial, is recorded against the exact version and content hash that was enforced, so any past decision can be proven against the precise policy that produced it. A policy change can also be dry-run against a sample input before it is activated, so a bad global policy doesn’t lock out every surface it applies to.

Why an embedded, in-process engine matters
Because policy evaluation runs in-process rather than as a network call to a sidecar, a policy decision adds no network latency and has no separate service to keep available.
Related
- Guardrails: Content-safety checks that run alongside policy in the request pipeline.
- Cost and attribution: The team gate that runs immediately after Trust Fabric policy.
- Security and access control: How source authentication establishes the identity a policy evaluates.
- Trust Fabric integration: The appliance-to-appliance DIDComm traffic the Trust Fabric policy layer evaluates first.
- Pipeline and stages: Where Gateway OPA and Surface-level policy run in the inbound stage order.
Glad to hear it! Please tell us how we can improve more.
Sorry to hear that. Please tell us how we can improve.
Thank you for sharing your feedback so we can improve your experience.