# AI Agent Database Access Policy Kit

A copy-paste kit for granting AI agents access to a production database without
losing control of it. One policy record per agent, every clause written so it
can be checked against the running system.

Engineering checklist, not legal advice. If your deployment is regulated,
involve counsel as well.

Maintained at: https://datapace.ai/blog/production-database-access-policy-ai-agents

---

## 1. The policy template (fill one per agent)

```yaml
# AI Agent Database Access Policy: one record per agent

agent:
  name: [agent-name, e.g. support-copilot]
  owner: [team or person accountable]
  purpose: [one sentence: what this agent does and why it needs data access]
  principal: [dedicated credential, e.g. db role "agent_support_copilot"]
  shared_credentials: forbidden

scope:
  databases: [list]
  allowed:
    - object: [schema.table or pattern]
      operations: [SELECT | INSERT | UPDATE | DELETE | DDL]
      conditions: [row limits, column exclusions, tenant filters]
  default: deny   # anything not listed above is denied

approval:
  autonomous: [e.g. SELECT under 10000 rows on non-sensitive tables]
  requires_human:
    - all DDL (schema changes)
    - writes affecting more than [N] rows
    - any operation on tables tagged [sensitive-tag]
  approvers: [named role or group, not an individual]
  approval_record: [where approvals are stored]

logging:
  record_per_operation:
    - agent identity and session id
    - exact statement or operation
    - objects touched and rows affected
    - decision: allowed | denied | approved_by [who]
    - timestamp (UTC)
  destination: [append-only store, outside the agent's reach]
  retention: [>= 6 months]

revocation:
  credential_expiry: [max lifetime, e.g. 90 days, auto-enforced]
  kill_switch: [exact command or console action]
  kill_switch_owners: [who may execute it]
  max_time_to_revoke: [target, e.g. 5 minutes]

escalation:
  on_denied_operation: [alert channel and severity]
  on_repeated_denials: [suspend agent pending review]
  on_sensitive_data_access: [page on-call, open incident]
  review_cadence: [re-review this policy every N days]
```

---

## 2. Worked example: a support copilot

```yaml
agent:
  name: support-copilot
  owner: support-engineering
  purpose: Summarizes and tags inbound tickets using ticket history.
  principal: db role "agent_support_copilot"
  shared_credentials: forbidden

scope:
  databases: [app]
  allowed:
    - object: support.tickets
      operations: [SELECT]
      conditions: no customer_email column; max 5000 rows per query
    - object: support.ticket_messages
      operations: [SELECT]
      conditions: max 5000 rows per query
    - object: support.ticket_tags
      operations: [SELECT, INSERT]
      conditions: inserts limited to 1 row per operation
  default: deny

approval:
  autonomous: all reads within scope; single-row tag inserts
  requires_human: [all DDL, any UPDATE or DELETE, anything outside scope]
  approvers: support-engineering on-call
  approval_record: "#agent-approvals" channel, mirrored to the audit log

logging:
  destination: append-only audit store (separate credentials)
  retention: 12 months

revocation:
  credential_expiry: 90 days
  kill_switch: REVOKE CONNECT ON DATABASE app FROM agent_support_copilot;
  kill_switch_owners: [dba on-call, support-engineering lead]
  max_time_to_revoke: 5 minutes

escalation:
  on_denied_operation: alert #agent-alerts, low severity
  on_repeated_denials: 3 denials in 10 minutes suspends the agent
  on_sensitive_data_access: page on-call, open incident
  review_cadence: 90 days
```

---

## 3. Landing clauses 1, 2 and 5 in PostgreSQL

```sql
-- Clause 1: identity per agent, with clause 5's expiry built in
CREATE ROLE agent_support_copilot
  LOGIN
  VALID UNTIL '2026-10-17';   -- credential auto-expires in 90 days

-- Clause 2: explicit scope, default deny
REVOKE ALL ON ALL TABLES IN SCHEMA public FROM agent_support_copilot;
GRANT SELECT ON support.tickets, support.ticket_messages
  TO agent_support_copilot;
GRANT SELECT, INSERT ON support.ticket_tags
  TO agent_support_copilot;

-- Clause 5: the kill switch (keep it one command two named people can run)
-- REVOKE CONNECT ON DATABASE app FROM agent_support_copilot;
```

Clauses 3 (approval), 4 (logging) and 6 (escalation) cannot live inside the
engine: Postgres can say what a role may do, but it cannot pause a statement
for approval, attach an approver's name, or page anyone. Those belong on the
connection path in front of the database.

---

## 4. Review checklist (run every quarter, and after any scope change)

- [ ] One policy record exists per agent that holds a credential
- [ ] Every `scope.allowed` line matches an actual GRANT (no drift either way)
- [ ] No agent shares a credential with an app or another agent
- [ ] Every credential has an enforced expiry date
- [ ] The kill switch has named owners who have run it at least once
- [ ] Logs land in a store the agent cannot read or write
- [ ] Denied-operation alerts reach a channel a human watches
- [ ] The policy is enforced outside the agent's prompt (grants + gateway),
      not pasted into its system prompt

---

## 5. Compliance cross-reference (rough map, not a compliance opinion)

| Clause | SOC 2 (Trust Services Criteria) | EU AI Act |
|---|---|---|
| 1. Identity per agent | CC6.1 access restricted to authorized principals | Art. 26 deployer oversight |
| 2. Scope, default deny | CC6.3 least-privilege access | none |
| 3. Approval thresholds | CC8.1 changes authorized before execution | Art. 26 human oversight |
| 4. Logging | CC7.2 anomalous activity monitored | Art. 26 retain logs >= 6 months |
| 5. Revocation | CC6.2 credential lifecycle management | none |
| 6. Escalation | CC7.3 / CC7.4 security events evaluated | Art. 26 incident duties |

A mapping like this satisfies an auditor only when the clause is actually
enforced and generates records. That is the argument for putting enforcement
on the connection path, where every decision is logged by construction.

---

Made by Datapace, the context layer and security gateway for AI on databases.
https://datapace.ai
