Define who can approve actions, configure multi-signature requirements, and set up delegation rules.
// Approver configuration options
hitl({
id: "payment-approval",
approvers: {
// Option 1: By role
roles: ["finance-manager", "cfo"],
// Option 2: By specific users
users: ["user_abc123", "user_def456"],
// Option 3: Dynamic based on context
dynamic: async (ctx) => {
const amount = ctx.steps["calculate-payment"].output.amount
if (amount > 10000) {
return { roles: ["cfo", "ceo"] }
} else if (amount > 1000) {
return { roles: ["finance-manager"] }
} else {
return { roles: ["accountant"] }
}
},
// Option 4: By department/team
teams: ["finance-team"],
// Option 5: Hierarchical (manager chain)
hierarchy: {
startFrom: "requester", // The person who triggered the workflow
levels: 1, // How many levels up
skipSelf: true
}
}
})Require multiple approvers for high-stakes decisions.
First approver to respond wins.
minApprovals: 1
Every eligible approver must approve.
minApprovals: "all"
Minimum number or percentage.
minApprovals: 2 or "50%"
// Multi-signature configurations
hitl({
id: "large-expense-approval",
approvers: {
roles: ["finance-manager", "department-head", "cfo"]
},
// Require 2 of 3 approvers
minApprovals: 2,
// Or require specific combinations
requiredApprovers: {
// Must have at least one from finance
anyOf: [{ roles: ["finance-manager", "cfo"] }],
// And the department head
allOf: [{ roles: ["department-head"] }]
},
// Sequential approval (chain)
sequential: true, // Each approver sees previous approvals
// Weighted voting
weights: {
"cfo": 2, // CFO approval counts double
"finance-manager": 1,
"department-head": 1
},
minWeight: 3 // Need combined weight of 3 to approve
})Allow approvers to delegate their approval authority when unavailable.
// Delegation configuration
hitl({
id: "contract-approval",
approvers: {
roles: ["legal-counsel"]
},
delegation: {
// Allow delegation
enabled: true,
// Who can be delegated to
allowedDelegates: {
roles: ["senior-paralegal", "associate-counsel"],
sameTeam: true // Must be in same team as delegator
},
// Delegation limits
limits: {
maxDelegationDepth: 1, // Can't delegate to someone who delegated
maxAmountLimit: 50000, // Delegates can only approve up to $50k
excludeActions: ["reject"] // Delegates can only approve, not reject
},
// Automatic delegation
auto: {
// Auto-delegate when approver is OOO
onOutOfOffice: true,
// Default delegate
defaultDelegate: "backup-counsel",
// Notify original approver
notifyOriginal: true
}
}
})
// Setting up delegation (user action)
await hitl.setDelegation({
from: "user_legal_counsel",
to: "user_senior_paralegal",
startDate: "2024-01-15",
endDate: "2024-01-22",
reason: "Vacation",
limits: {
maxAmount: 25000,
categories: ["standard-contracts"]
}
})// Escalation configuration
hitl({
id: "urgent-approval",
approvers: { roles: ["manager"] },
escalation: {
// Time-based escalation
rules: [
{
after: "2h",
action: "remind",
target: "current" // Remind current approvers
},
{
after: "4h",
action: "escalate",
target: { roles: ["senior-manager"] },
reason: "No response from primary approver"
},
{
after: "8h",
action: "escalate",
target: { roles: ["director"] },
keepPrevious: true // Previous approvers can still approve
},
{
after: "24h",
action: "auto-reject",
reason: "Approval timeout exceeded"
}
],
// Priority-based escalation
priorityRules: {
critical: {
initialApprovers: { roles: ["director", "vp"] },
timeout: "1h"
},
high: {
initialApprovers: { roles: ["senior-manager"] },
timeout: "4h"
},
normal: {
initialApprovers: { roles: ["manager"] },
timeout: "24h"
}
}
}
})// Notification configuration
hitl({
id: "approval-with-notifications",
notifications: {
// Channels to use
channels: ["email", "slack", "push", "sms"],
// When to notify
events: {
// When approval is requested
onRequest: {
channels: ["email", "slack", "push"],
template: "approval-request",
urgent: (ctx) => ctx.priority === "critical"
},
// Reminders
onReminder: {
enabled: true,
schedule: ["4h", "8h", "20h"], // Remind at these intervals
channels: ["slack", "push"],
template: "approval-reminder"
},
// When approved/rejected
onDecision: {
notify: ["requester", "stakeholders"],
channels: ["email", "slack"],
template: (decision) => `approval-${decision.action}`
},
// On escalation
onEscalation: {
notify: ["original-approvers", "escalation-target"],
channels: ["email", "slack", "sms"],
template: "approval-escalated"
},
// On timeout
onTimeout: {
notify: ["requester", "approvers", "admin"],
channels: ["email", "slack"],
template: "approval-timeout"
}
},
// Notification preferences
respectUserPreferences: true, // Honor user notification settings
quietHours: {
enabled: true,
except: ["critical"] // Always notify for critical
}
}
})