Skip to main content

Consent UX (Human-in-the-Loop)

The Consent UX system provides human-in-the-loop approval workflows for AI agent actions. When an agent attempts an action that requires explicit human authorization — based on risk level, action type, or custom policies — Mandaitor creates a consent request that must be resolved by an authorized approver before the action can proceed.

Consent requests are triggered automatically based on consent policies configured by the tenant. Policies define which actions, risk levels, or conditions require human approval before execution.

TriggerExample
Risk levelAll HIGH or CRITICAL risk actions require approval
Action patternAny action matching finance.transfer.* above €10,000
First-time actionAgent performing an action type for the first time
Drift thresholdAgent's drift score exceeds the configured threshold

The consent flow integrates with the standard verification pipeline:

Consent policies define the rules for when human approval is required:

await client.post("/consent-policies", {
name: "High-Value Transactions",
description: "Require approval for financial actions above threshold",
conditions: {
action_patterns: ["finance.transfer.*", "finance.approve.*"],
risk_levels: ["HIGH", "CRITICAL"],
constraint_match: {
"amount_eur": { "gt": 10000 },
},
},
approvers: [
{ type: "role", value: "finance-manager" },
{ type: "subject", value: "user:cfo@company.com" },
],
timeout_hours: 24,
escalation: {
after_hours: 4,
to: "user:ceo@company.com",
},
});

Consent policies can be listed, inspected, updated, and deleted through the tenant API. This is useful when approval routing must evolve without changing mandate records.

OperationEndpointPurpose
List policiesGET /consent-policiesReturns all tenant-level approval policies.
Get policyGET /consent-policies/{id}Retrieves one policy including conditions, approvers, timeout, and escalation metadata.
Update policyPUT /consent-policies/{id}Replaces the policy definition. Existing consent requests keep their historical policy snapshot.
Delete policyDELETE /consent-policies/{id}Removes the policy from future verification decisions.
await client.put(`/consent-policies/${policyId}`, {
name: "High-Value Transactions",
conditions: {
action_patterns: ["finance.transfer.*"],
risk_levels: ["HIGH", "CRITICAL"],
},
approvers: [{ type: "role", value: "finance-manager" }],
timeout_hours: 12,
});

Listing Pending Consents

Approvers can view their pending consent requests:

GET /consents/pending

This returns all consent requests awaiting the caller's decision, ordered by creation time.

Approvers resolve consent requests through the implemented POST /consents/{id}/resolve endpoint. Resolution records the decision, reviewer context, reason, and optional conditions into the audit trail before the agent retries verification:

await client.post(`/consents/${consentId}/resolve`, {
decision: "APPROVED",
reason: "Reviewed and confirmed within project budget",
conditions: {
valid_until: "2026-06-01T00:00:00Z",
},
});

Rejection permanently blocks the specific action attempt. The agent must create a new verification request if it wishes to retry. Applications can retrieve the current request state through GET /consents/{id} before rendering an approval screen, which prevents stale or already-resolved requests from being approved twice.

All consent requests for a specific mandate can be retrieved:

GET /mandates/{id}/consents

This provides a complete audit trail of all human-in-the-loop decisions made for a given mandate.

info

The Consent UX system is currently Stable. The policy engine and approval flows are production-ready. Escalation timing and notification channels may evolve based on feedback.