Auto-Approval
The Auto-Approval Engine short-circuits human review for trace
patterns reviewers have consistently approved. After ≥50
observations, ≥95% approval rate, and a 4-eyes sign-off, the
pattern is active and matching flagged traces resolve to
approved without entering the Review Queue.
Patterns can never override a block. Blocks remain
deterministic safety boundaries; auto-approval only short-circuits
the flag-for-review path. Tested against API version v1. JWT
auth on every endpoint; plan-gated by autoApprovalEngine
(Enterprise and above).
The hard rule
flagged → ApprovalPattern match → approved ✓ permitted
blocked → ApprovalPattern match → approved ✗ NEVER PERMITTED
The engine reads the trace's pre-resolution status. A block
verdict from the Policy Engine
short-circuits the entire pipeline before auto-approval runs. The
schema enforces this: AutoApprovalDecision.priorStatus accepts
only flagged or escalated, never blocked.
The ApprovalPattern object
| Field | Type | Required | Description |
|---|---|---|---|
_id / id | string | yes | MongoDB ObjectId |
organizationId | string | yes | Owning org |
name | string | yes | Operator-readable name |
description | string | no | Free-form context |
match | object | yes | At least one match criterion (see below) |
observationCount | number | no | Read-only; total trace observations |
approvalCount | number | no | Read-only; reviewer-approved count |
rejectionCount | number | no | Read-only; reviewer-rejected count |
approvalRate | number | no | Read-only; approvalCount / observationCount, 0–1 |
status | enum | no | observing, pending_signoff, active, paused, expired |
signoffs | Signoff[] | no | 4-eyes sign-off history |
activatedAt | string (ISO 8601) | no | When the pattern transitioned to active |
lastRevalidatedAt | string (ISO 8601) | no | Last 90-day revalidation |
nextRevalidationAt | string (ISO 8601) | no | Next revalidation deadline |
expiresAt | string (ISO 8601) | no | Set when revalidation window closes |
createdAt / updatedAt | string (ISO 8601) | no | Standard timestamps |
match sub-document
| Field | Type | Description |
|---|---|---|
agentIds | string[] | Match traces from these agents |
policyIds | string[] | Match traces that hit these policies |
tags | string[] | Match traces carrying these tags[] |
confidenceMin | number | Minimum confidenceScore (0.0–1.0) |
inputContains | string[] | Case-insensitive substrings on the trace's rationale |
At least one criterion must be supplied at create time.
Signoff sub-document
| Field | Type | Description |
|---|---|---|
userId | string | User ObjectId of the approver |
userEmail | string | Snapshot of email at sign-off time |
signedAt | string (ISO 8601) | When the sign-off fired |
chainHash | string | Cross-link to the HashChainEntry anchoring this sign-off |
Maturation thresholds
The thresholds are deliberately conservative. Auto-approval removes a human from the loop — that is exactly the loop EU AI Act Article 14 requires for high-risk systems. The 50-observation floor exists so a pattern's empirical approval rate is statistically meaningful before it ever fires; the 95% bar exists because the reviewer-disagreement rate at 90% is an order of magnitude higher than at 95%; the 4-eyes sign-off exists so no single admin can unilaterally short-circuit human review; the 90-day re-validation exists so a pattern that drifts as the agent behind it drifts (new prompt, new model, new tool) cannot keep firing silently.
A pattern transitions through four states before it can fire:
observing ── ≥50 observations + ≥95% approval rate ──▶ pending_signoff
pending_signoff ── 2 distinct user signoffs (4-eyes) ──▶ active
active ── 90-day re-validation gate ──▶ active | expired
active ── manual /pause ──▶ paused
A pattern that fails the 90-day re-validation gate transitions to
expired and stops firing automatically. The audit-log entry on
auto_approval.pattern_signoff and the cross-linked chainHash
on each Signoff together prove the four-eyes principle held at
activation.
Endpoints
GET /api/v1/auto-approval/patterns
POST /api/v1/auto-approval/patterns
GET /api/v1/auto-approval/patterns/:id
POST /api/v1/auto-approval/patterns/:id/pause
POST /api/v1/auto-approval/patterns/:id/signoff
GET /api/v1/auto-approval/decisions
List patterns
GET /api/v1/auto-approval/patterns
curl https://api.adjudon.com/api/v1/auto-approval/patterns \
-H "Authorization: Bearer $ADJUDON_API_KEY"
Errors: 401, 403 UPGRADE_REQUIRED, 500 PATTERN_LIST_FAILED.
Create a pattern
POST /api/v1/auto-approval/patterns
| Body field | Required | Description |
|---|---|---|
name | yes | Operator-readable name |
description | no | Free-form context |
match | yes | At least one criterion (agentIds, policyIds, tags, confidenceMin, or inputContains) |
curl -X POST https://api.adjudon.com/api/v1/auto-approval/patterns \
-H "Authorization: Bearer $ADJUDON_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Trusted refunds < €50",
"description": "Approved 200x in Q2 by ops team",
"match": {
"agentIds": ["customer-support-bot"],
"tags": ["small-refund"],
"confidenceMin": 0.85
}
}'
The pattern starts in status: 'observing' and accumulates
observationCount as matching traces flow through. It fires no
auto-approvals until it reaches active. Errors: 400
VALIDATION_ERROR (missing name or empty match), 401, 403,
500 PATTERN_CREATE_FAILED.
Get one pattern
GET /api/v1/auto-approval/patterns/:id
Returns the full pattern with maturation counters and signoffs.
Errors: 401, 404 NOT_FOUND, 500 PATTERN_GET_FAILED.
Sign off (4-eyes)
POST /api/v1/auto-approval/patterns/:id/signoff
Records the calling user's sign-off for activation. Two distinct
users must call signoff while the pattern is in pending_signoff;
the second call promotes the pattern to active. The same user
calling twice is rejected with 400 INVALID_STATE.
curl -X POST https://api.adjudon.com/api/v1/auto-approval/patterns/65b1f2c4/signoff \
-H "Authorization: Bearer $ADJUDON_API_KEY"
Each sign-off appends a Signoff record with userId, userEmail
(snapshot), signedAt, and chainHash (a cross-link to the
Operations Audit Log entry on
auto_approval.pattern_signoff). Errors: 400 INVALID_STATE
(wrong status), 401, 404, 500.
Pause a pattern
POST /api/v1/auto-approval/patterns/:id/pause
Transitions an active pattern to paused. Paused patterns do
not auto-approve. Errors: 401, 404, 500 PATTERN_PAUSE_FAILED.
List auto-approval decisions
GET /api/v1/auto-approval/decisions
Returns the audit history of every flagged (or escalated) trace
that an ApprovalPattern resolved without human review. One row
per match. Each row carries patternId, traceId, priorStatus
(must be flagged or escalated — schema-enforced), appliedAt,
chainHash, and rationale. This is the primary surface a regulator
asks for when reviewing the human-oversight posture: every decision
the AI system made that a human did not see, with the pre-clearance
provenance attached. The chainHash cross-link to the
Hash Chain makes the trail
reconstructable from the original observation window forward.
curl https://api.adjudon.com/api/v1/auto-approval/decisions \
-H "Authorization: Bearer $ADJUDON_API_KEY"
Errors: 401, 500 DECISION_LIST_FAILED.
Common gotchas
- Patterns cannot override blocks. This is the most important
rule on the page. The schema enforces it
(
AutoApprovalDecision.priorStatusenum isflaggedorescalated, notblocked); the engine reads the trace's pre-resolution status; ablockverdict from the Policy Engine short-circuits the pipeline before auto-approval runs. - At least one match criterion. Creating a pattern with an empty
matchobject returns400 VALIDATION_ERROR. The engine refuses to ship a pattern that would match every trace. - 4-eyes is two distinct users. The same user calling
/signofftwice gets rejected. Open a separate session as a differentadminorownerfor the second sign-off. - 90-day re-validation. An
activepattern that does not re-validate within 90 days transitions toexpiredand stops firing. The dashboard surfacesnextRevalidationAtfor every active pattern. - Plan-gate. The whole resource requires the
autoApprovalEnginefeature. Sandbox, Scale, and Governance plans receive403 UPGRADE_REQUIRED— this is an Enterprise-only surface. - Idempotency. The
Idempotency-Keymiddleware is wired only onPOST /tracestoday; create / pause / signoff calls on this resource do not auto-receive replay protection. Retry defensively; a duplicate pattern create is rejected by the unique(organizationId, name)index, and a duplicatesignofffrom the same user is rejected with400 INVALID_STATE.
See also
- Policies API — the block / flag / approve verdict ladder this engine builds on top of
- Reviews API — the human-review queue auto-approval bypasses
- Alerts API — the flip-side: page on something rather than pre-clear it
- Audit Log API — where
auto_approval.pattern_created,auto_approval.pattern_paused, andauto_approval.pattern_signoffevents land - Hash Chain API — the
chainHashcross-link on everySignoffandAutoApprovalDecision - Error Codes — the full error taxonomy