Recommend a least-privilege policy from recorded traffic
Derives the tightest policy that would still pass every statement this agent credential has legitimately run, using its recorded audit history over a lookback window (default 30 days). The candidate's table allowlist is the union of relations actually referenced, its statement-kind allow set is the observed set, it downgrades to read-only when no writes were seen, and its max_rows ceiling comes from an observed high-percentile row count. The candidate is proven safe by replaying it through the data plane's own policy engine against the same history: a good recommendation has replay.summary.newly_blocked == 0. This endpoint is advisory only. It reads the audit log, never connects to the upstream database, and never creates, updates, or mutates any policy or credential; the operator loads the candidate into the editor and saves it themselves.
JWT issued by Better Auth. Verified via JWKS.
In: header
Path Parameters
Unique project identifier (prefixed, e.g. prj_xxx).
^[a-zA-Z0-9_.-]+$Unique agent credential identifier (prefixed, e.g. agt_xxx).
^[a-zA-Z0-9_.-]+$Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Optional parameters for a least-privilege policy recommendation. Every field is optional; an empty body analyzes the last 30 days of the credential's audit history.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/projects/string/agents/string/policy-recommendation" \ -H "Content-Type: application/json" \ -d '{}'{ "sufficient_history": true, "message": "string", "candidate": { "name": "string", "access_mode": "read_only", "statement_rules": { "allow": [ "string" ], "deny": [ "string" ] }, "table_allowlist": [ "string" ], "table_denylist": [ "string" ], "masking_rules": [ { "table": "users", "column": "email", "kind": "redact" } ], "budget_queries_per_hour": 0, "budget_queries_per_day": 0, "max_rows": 0, "statement_timeout_ms": 0, "row_filters": [ { "table": "orders", "predicate": "tenant_id = current_setting('pgbeam.tenant')" } ], "write_mode": "normal", "approval_mode": "off", "approval_auto_max_rows": 0, "approval_timeout_seconds": 300, "migration_safety": "off", "egress_bytes_per_day": 0, "max_affected_rows": 0 }, "replay": { "summary": { "entries_scanned": 0, "distinct_queries": 0, "evaluated": 0, "would_allow": 0, "would_block": 0, "would_mask": 0, "would_row_filter": 0, "newly_blocked": 0, "newly_allowed": 0, "skipped_unparseable": 0, "truncated": true }, "items": [ { "query_hash": "string", "sql": "string", "statement_kind": "string", "occurrences": 0, "first_seen": "2019-08-24T14:15:22Z", "last_seen": "2019-08-24T14:15:22Z", "recorded_event": "string", "recorded_rule": "string", "change": "newly_blocked", "result": { "verdict": "allow", "rule": "ok", "reason": "string", "hint": "string", "masked_columns": [ { "column": "email", "kind": "redact" } ], "row_filter_predicate": "tenant_id = current_setting('pgbeam.tenant')", "rewritten_sql": "string", "notes": [ "string" ] } } ] }, "observed_queries": 0, "observed_entries": 0, "window_start": "2019-08-24T14:15:22Z", "window_end": "2019-08-24T14:15:22Z", "notes": [ "string" ]}{ "error": { "code": "string", "message": "string" }}{ "error": { "code": "string", "message": "string" }}{ "error": { "code": "string", "message": "string" }}{ "error": { "code": "string", "message": "string" }}{ "error": { "code": "string", "message": "string" }}