Access decisions you can test, explain, and audit.
The policy engine evaluates every request from a user, service account, model, or AI agent against who is asking, what they want, how sensitive it is, and where they are, then returns allow, deny, or require approval with the policy that decided it.
Prompts are not access control.
Most AI deployments enforce permissions with instructions in a system prompt: "only answer questions about billing." That holds until a retrieved document, a user, or another agent tells the model otherwise. Instructions are suggestions to a probabilistic system; they cannot be relied on to keep regulated data where it belongs.
Data.co Control moves the decision out of the model. Every request is evaluated by a deterministic policy decision point before data is retrieved, a tool is called, or a prompt leaves for a model endpoint. The model never sees data it was not allowed to see, so there is nothing for an injected instruction to exfiltrate.
Rules that match how regulated teams actually work.
Any subject
Users, groups, service accounts, AI agents, and models each have an identity. Policies target any of them, or tags on them.
Any resource
Datasets, tables, document collections, connectors, model endpoints, and individual MCP tools are all addressable.
Classification-aware
Conditions on PHI, PII, financial, privileged, or custom labels applied at ingest, not guessed at query time.
Context conditions
Restrict by environment, network zone, time window, purpose, or the destination model's approval status.
Three outcomes
Allow, deny, or require approval. Destructive and high-risk actions can wait for a named human.
Explainable
Every decision returns the policy IDs that matched and a plain-language reason that can be shown to users and auditors.
Version policies like the rest of your infrastructure.
Policies are YAML in a Git repository you control, reviewed in pull requests and tested in CI before they reach production. The simulator runs the same engine against hypothetical requests.
id: pol_phi_002
description: RCM agents cannot read clinical notes
subject: { type: agent, tags: [rcm] }
resource: { dataset: ehr.clinical_notes }
action: [read, search, export]
when:
classification: PHI
effect: deny
explain: "Clinical notes require a treating-provider relationship."Illustrative example · final API surface documented in /docs
One decision point, many enforcement points.
The decision is made once and enforced wherever the request travels, so an agent cannot route around a rule by switching tools.
- 1
Identify
The gateway attaches a verified identity to the request: the user behind the session, plus the agent or model acting for them.
- 2
Evaluate
The policy decision point matches applicable policies and evaluates conditions against classification and context.
- 3
Enforce
Enforcement points in the AI gateway, MCP gateway, and connectors apply the result before any data moves.
- 4
Record
The request, decision, matching policy IDs, and outcome are written to an append-only audit log in your environment.
When several policies match, the order of precedence is fixed.
Real policy sets overlap. A baseline allow, a team exception, and a classification deny can all match the same request. The engine resolves them in the same order every time, so reviewers can predict the outcome without running it.
| Step | Rule | Result and reason code |
|---|---|---|
| 1 | Any matching policy with effect deny | deny (policy_deny). A deny wins regardless of priority or how many allows also match. |
| 2 | The subject declares a scope and the resource or tool is outside it | deny (resource_not_in_scope or tool_not_in_scope). Scope is a hard ceiling no allow can widen. |
| 3 | A matching require_approval that has not been approved | require_approval, listing every approver group involved |
| 4 | A matching allow, or a require_approval already approved | allow (policy_allow or approval_granted) |
| 5 | Nothing matched | deny (no_matching_allow). Access is never granted by omission. |
A small language, with sharp edges filed off.
A policy names a subject, a resource, and one or more actions, then adds conditions under when. Subjects match on type, ID, tags, groups, roles, or attributes. Resources match on dataset, table, collection, connector, model endpoint, MCP server, or tool, with glob patterns such as ehr.* for families of assets. Conditions compare values with operators like in, not_in, subset_of, gt, lte, exists, and matches, and can reference other parts of the request, so a rule can say that a resource's region must equal the subject's region.
Several choices exist specifically to stop silent mistakes. Unknown keys anywhere in a policy are rejected, so a misspelled condition cannot quietly widen or narrow a rule. A missing value fails every comparison except an explicit exists check, which means a request that lacks a classification does not accidentally satisfy a rule written for one. Time windows are evaluated in a named IANA time zone against a timestamp stamped by the enforcement point, never against the server clock, so a business-hours rule behaves the same on every node. And if any single policy in a set fails validation, the whole set is refused: a partially loaded policy set is never enforced.
Every set also has a version: a hash of its canonical, sorted contents. Each decision records the version that produced it, alongside a hash of the request, which is what lets an auditor confirm months later exactly which rules were in force for a given request.
Designed to fail closed.
Governance has to keep working when something else breaks.
- Decisions are deterministic: same request, same policies, same answer
- No LLM in the decision path
- Fails closed if the policy store is unavailable
- Evaluation runs locally; no dependency on app.data.co
- Works in air-gapped deployments
- Policy changes are versioned and attributable
- Simulator and production share one engine
- Every decision is exportable as audit evidence
Questions buyers ask
Does an LLM decide whether a request is allowed?
No. Decisions come from a deterministic rules engine evaluating explicit policies. Models can help draft policies or summarize audit logs, but they are never in the enforcement path.
How is this different from role-based access in our existing systems?
Source-system permissions are respected and carried forward. The policy engine adds the layer those systems lack: rules about AI agents and models as actors, rules on data classification across sources, and rules on which model endpoints may receive which data.
Can we test a policy change before it goes live?
Yes. Policies are code with unit tests, and the access simulator evaluates hypothetical requests against a proposed policy set and shows the decision, the matching policy IDs, and the explanation.
What happens if the policy engine is unreachable?
Requests fail closed. Because the engine runs inside your infrastructure next to the gateways it serves, it does not depend on Data.co's hosted services or internet connectivity.
Can policies require a human to approve an action?
Yes. A policy can return require_approval, which pauses the request and routes it to a named person or group with a timeout and a default outcome.
Does policy priority change the outcome?
No. Priority only orders policies in the output so explanations read sensibly. Outcomes follow fixed precedence: deny, then scope, then approval, then allow, then default deny. Reordering files cannot change a decision.
What happens if someone commits a policy with a typo?
Validation rejects unknown keys and malformed values, and one invalid policy invalidates the whole set. In CI the change fails. In a running deployment the previously valid set stays active and the errors are reported.
See it against your own use case.
A 30-minute technical walkthrough, policy simulation on your scenarios, and a deployment recommendation for on-prem, private cloud, or hybrid.