Universal onboarding (works for every stack)

Time: ~30 minutes to shadow mode · 1–7 days to enforce
Requires: PostgreSQL 14+, ability to CREATE EXTENSION (or load the SQL in a lab)

This path is the same whether the client is psql, MCP, LangGraph, CrewAI, Cursor, or a homegrown tool gateway.

Install → Identity → Baseline pack → Shadow → Domain pack → Honor obligations → Enforce

Day 0 — Install the kernel

CREATE EXTENSION pg_policy;
SELECT pg_policy.set_setting('enforcement_mode', 'log_only');  -- never start at enforce

From a checkout:

psql "$DATABASE_URL" -f examples/packs/00-baseline.sql

You now have DDL/admin forbids + SQL guidance for every agent id "*".


Day 0 — Identity convention (do not skip)

Pick stable strings. Changing them later orphans logs.

Field Convention Example
principal_type agent agent
principal_id {framework}:{name} langgraph:analytics, cursor:compose, mcp:postgres
context.acting_for human user id (opaque) user:42 or HMAC of email
context.tenant_id tenant key also used by RLS acme
session_id one per user-visible chat/run LangGraph thread_id, MCP session, gen_random_uuid()

Open a session when the agent run starts:

SELECT pg_policy.open_session(
  'thread-abc',
  'agent',
  'langgraph:analytics',
  '{"acting_for":"user:42","tenant_id":"acme"}'::jsonb
);

Day 0 — Wire the one hook

Every tool call (not every SQL string inside a transaction) must hit evaluate before side effects.

Pseudo-contract (any language):

decision = evaluate(agent, tool, context, session_id)
if not decision.allowed:  return error(decision.reasons)
apply(decision.obligations)   # LIMIT, prefer other tool, show advice
execute_tool()

Copy-paste adapters: integrations.md and examples/integrations/.

If you cannot wrap tools yet, you are not ready for enforce. Stay in log_only and sample pg_policy.decision_log.


Day 1 — Prove shadow mode

SELECT at, principal_id, action_id, decision, reasons, obligations
FROM pg_policy.decision_log
ORDER BY at DESC
LIMIT 50;

Look for:

  • shadow_deny obligations → policies that would have blocked
  • agents with empty acting_for
  • tools you forgot to name (action_id junk)

Fix names and context before loading a stricter pack.


Day 2 — Load a domain pack

If you are… Load
BI / text-to-SQL examples/packs/analytics.sql
Support / CX examples/packs/support.sql
Payments / ledger examples/packs/fintech.sql
PHI / clinical examples/packs/healthcare.sql
DBA / migrations examples/packs/devops.sql
Multi-agent crew examples/packs/multi-agent.sql

Packs are idempotent upsert_policy scripts. They do not change enforcement_mode.

Also enable RLS on tenant tables (examples/04-rls-complement.sql pattern). Packs do not replace RLS.


Day 3–7 — Honor obligations in the PEP

guide never blocks. Your gateway must implement:

Obligation type PEP behavior
max_rows Inject LIMIT / truncate result
prefer_tool Hint the model or auto-route
advice Put in tool error/warning channel
shadow_deny / would_deny Metric + optional user-visible warning

Until max_rows is enforced in the MCP, the policy is theater.


Promote to enforce

-- only after: no surprise shadow_denies you disagree with
SELECT pg_policy.set_setting('enforcement_mode', 'enforce');

Rollback is one row:

SELECT pg_policy.set_setting('enforcement_mode', 'log_only');

Least-privilege Postgres role (required for “works for all”)

Never connect the agent as table owner or superuser.

CREATE ROLE agent_runtime NOINHERIT LOGIN PASSWORD '...';
GRANT USAGE ON SCHEMA public TO agent_runtime;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO agent_runtime;  -- tighten per pack
GRANT USAGE ON SCHEMA pg_policy TO agent_runtime;
GRANT SELECT, INSERT ON ALL TABLES IN SCHEMA pg_policy TO agent_runtime;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA pg_policy TO agent_runtime;
-- Do NOT grant BYPASSRLS
ALTER ROLE agent_runtime SET default_transaction_read_only = on;  -- analytics/support

Writes: dedicated agent_writer with default_transaction_read_only = off and a narrower pack.


Definition of done

  • [ ] Extension installed; mode started log_only
  • [ ] Stable principal_id / session_id / acting_for
  • [ ] All tools go through evaluate
  • [ ] Baseline + one domain pack loaded
  • [ ] RLS enabled on tenant tables
  • [ ] Obligations implemented in the gateway
  • [ ] Week of shadow review
  • [ ] enforce with a documented rollback

That onboarding is identical for every framework. Only the adapter file changes.