Approval workflows are easy to implement and hard to design well. A poorly designed workflow creates bottlenecks (too many approvals), alert fatigue (reviewers stop paying attention), or security gaps (wrong things are auto-approved). This guide covers design patterns that work.
Not all actions need the same level of review. Tier your approvals by risk:
# Low risk: automatic
- tool: "search.web"
action: allow
# Medium risk: one approver
- tool: "file.write"
action: escalate
metadata:
required_approvals: 1
sla_minutes: 30
# High risk: two approvers
- tool: "payment.send"
action: escalate
when:
args.amount:
gt: 1000
metadata:
required_approvals: 2
approver_roles: ["finance-lead", "security"]
sla_minutes: 60
Start with aggressive escalation and relax over time as you build confidence:
Week 1: Escalate all file writes, all API calls, all emails. Week 2: Auto-allow file writes to /output/. Still escalate API calls and emails. Week 4: Auto-allow internal API calls. Escalate external API calls and emails. Month 2: Auto-allow internal emails. Escalate external emails.
Track the approval rate at each stage. If 98% of escalations are approved, it is safe to convert that rule to auto-allow.
Give reviewers enough information to make a good decision:
const approval = {
tool: 'payment.send',
args: { to: 'vendor@example.com', amount: 2500 },
reason: 'Payments over $1000 require approval',
context: {
user: 'John (john@company.com)',
conversation: 'User requested payment for Q1 invoice',
sessionActions: 12,
sessionDenials: 0,
riskScore: 0.15,
},
actions: ['approve', 'deny', 'modify_amount'],
};
A reviewer who sees the full context can make a decision in seconds. A reviewer who sees only "payment.send: $2500" cannot.
Every approval request needs a timeout. Design timeout behavior:
metadata:
sla_minutes: 30
timeout_action: deny # Safe default
escalation_on_timeout: true # Notify a backup reviewer
If the primary reviewer does not respond in 30 minutes, deny the action and notify a backup. This prevents actions from hanging indefinitely.
When the primary reviewer is unavailable, route to a delegate:
metadata:
primary_reviewer: "finance-lead"
delegates:
- "finance-team"
- "engineering-lead"
delegation_after_minutes: 15
Too many escalations: If reviewers see 50 approval requests per hour, they will rubber-stamp them. Keep escalation volume manageable.
Vague approval context: "Approve this action?" with no context leads to uninformed decisions.
No timeout: Actions that wait forever for approval create cascading delays.
Same reviewer for everything: Distribute approvals across a team to avoid single points of failure and prevent one person from approving everything.
Explore more guides on AI agent safety, prompt injection, and building secure systems.
View All Guides