Approval-Required Tool Calls
Set policy=approval_required and tool calls pause mid-step until a human reviewer approves. The SDK exposes a single helper that handles the full 202 → poll → resume / throw lifecycle.
Features
Four-eyes enforced
Reviewer must differ from requester. Enforced at three layers: DB CHECK constraint, service-layer guard, and the operator UI disable.
TTL auto-deny
Pending approvals past 1h auto-expire via a worker scheduled sweep. The SDK throws CloudVeraApprovalExpired so your agent can fall back without the tool.
Denial-of-wallet quota
Max 25 pending approvals per agent. Beyond that, the SDK throws CloudVeraQuotaError — protects operators from being drowned in a runaway-agent queue.
Code Examples
recordToolCallAndWait — full lifecycle in one call
import {
CloudVeraApprovalDenied,
CloudVeraApprovalExpired,
CloudVeraQuotaError,
} from '@cloudvera/agent-sdk';
try {
const call = await sessions.recordToolCallAndWait(
agent.id,
session.id,
{
toolName: 'deploy_rule',
inputPreview: JSON.stringify({ ruleId: 'r-42' }),
},
{ timeoutMs: 5 * 60_000 }, // 5 min reviewer SLA
);
// call.status === 'executed' — your real handler now runs
await deployRuleToProd(call);
} catch (err) {
if (err instanceof CloudVeraApprovalDenied) {
// err.reviewNotes carries the human reason
} else if (err instanceof CloudVeraApprovalExpired) {
// nobody answered in time — retry later or pick a different action
} else if (err instanceof CloudVeraQuotaError) {
// too many pending — backoff
} else {
throw err;
}
}
Reviewer side — /dashboard/agent-approvals
Operators see every pending tool call at:
https://cloudvera.io/dashboard/agent-approvals
Each row shows: tool name, agent, session, args preview, expiry
countdown, and inline approve / deny buttons. Reviewers must hold
owner / admin / editor role; viewers cannot enumerate the queue.
The decision is audit-logged with reviewer email + free-text notes.