Skip to main content

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

FieldTypeRequiredDescription
_id / idstringyesMongoDB ObjectId
organizationIdstringyesOwning org
namestringyesOperator-readable name
descriptionstringnoFree-form context
matchobjectyesAt least one match criterion (see below)
observationCountnumbernoRead-only; total trace observations
approvalCountnumbernoRead-only; reviewer-approved count
rejectionCountnumbernoRead-only; reviewer-rejected count
approvalRatenumbernoRead-only; approvalCount / observationCount, 0–1
statusenumnoobserving, pending_signoff, active, paused, expired
signoffsSignoff[]no4-eyes sign-off history
activatedAtstring (ISO 8601)noWhen the pattern transitioned to active
lastRevalidatedAtstring (ISO 8601)noLast 90-day revalidation
nextRevalidationAtstring (ISO 8601)noNext revalidation deadline
expiresAtstring (ISO 8601)noSet when revalidation window closes
createdAt / updatedAtstring (ISO 8601)noStandard timestamps

match sub-document

FieldTypeDescription
agentIdsstring[]Match traces from these agents
policyIdsstring[]Match traces that hit these policies
tagsstring[]Match traces carrying these tags[]
confidenceMinnumberMinimum confidenceScore (0.0–1.0)
inputContainsstring[]Case-insensitive substrings on the trace's rationale

At least one criterion must be supplied at create time.

Signoff sub-document

FieldTypeDescription
userIdstringUser ObjectId of the approver
userEmailstringSnapshot of email at sign-off time
signedAtstring (ISO 8601)When the sign-off fired
chainHashstringCross-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
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 fieldRequiredDescription
nameyesOperator-readable name
descriptionnoFree-form context
matchyesAt least one criterion (agentIds, policyIds, tags, confidenceMin, or inputContains)
curl — refund < €50 from trusted agent
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
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
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.priorStatus enum is flagged or escalated, not blocked); the engine reads the trace's pre-resolution status; a block verdict from the Policy Engine short-circuits the pipeline before auto-approval runs.
  • At least one match criterion. Creating a pattern with an empty match object returns 400 VALIDATION_ERROR. The engine refuses to ship a pattern that would match every trace.
  • 4-eyes is two distinct users. The same user calling /signoff twice gets rejected. Open a separate session as a different admin or owner for the second sign-off.
  • 90-day re-validation. An active pattern that does not re-validate within 90 days transitions to expired and stops firing. The dashboard surfaces nextRevalidationAt for every active pattern.
  • Plan-gate. The whole resource requires the autoApprovalEngine feature. Sandbox, Scale, and Governance plans receive 403 UPGRADE_REQUIRED — this is an Enterprise-only surface.
  • Idempotency. The Idempotency-Key middleware is wired only on POST /traces today; 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 duplicate signoff from the same user is rejected with 400 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, and auto_approval.pattern_signoff events land
  • Hash Chain API — the chainHash cross-link on every Signoff and AutoApprovalDecision
  • Error Codes — the full error taxonomy