User Approval in Flows
The User Approval feature allows flows to pause execution and wait for human confirmation before proceeding with critical actions. This provides a "human-in-the-loop" capability for workflows that require manual oversight.
Overview
User Approval enables you to:
- Pause Execution: Stop flow execution at any point
- Request Confirmation: Show users a custom approval message
- Branch on Decision: Route flow based on approve/reject choice
- Resume Safely: Continue execution exactly where it paused
- Maintain Context: All variables and state are preserved
When to Use
User Approval is ideal for:
- ✅ Critical operations (deleting data, financial transactions)
- ✅ Compliance requirements (approval workflows, audit trails)
- ✅ User consent (GDPR, privacy confirmations)
- ✅ Cost-sensitive actions (API calls with charges)
- ✅ Irreversible operations (sending emails, publishing content)
Quick Start
1. Add User Approval Step
- Open your flow in the Flow Editor
- Click Add Step where you want to pause for approval
- Select User Approval from the Workflow category
- Configure the approval message
2. Configure the Step
Basic Configuration:
{
"type": "user-approval",
"name": "Confirm Action",
"data": {
"message": "Are you sure you want to proceed?"
}
}With Context Variables:
{
"type": "user-approval",
"name": "Confirm Deletion",
"data": {
"message": "Delete {{count}} items from {{category}}? This cannot be undone."
}
}3. Connect Paths
The User Approval step automatically creates two output paths:
- ✅ Approve Path (Green): Connect to steps that should run if approved
- ❌ Reject Path (Red): Automatically goes to a final step (or connect to custom rejection logic)
4. Test Your Flow
- Assign the flow to a peer
- Send a message that triggers the flow
- When the approval step is reached:
- Flow execution pauses
- User sees the approval message with buttons
- Click Approve or Reject
- Flow resumes and completes
User Experience
In Chat Interface
When a flow reaches a user approval step, users see:
┌─────────────────────────────────────┐
│ Delete 50 items from Electronics? │
│ This cannot be undone. │
│ │
│ [Approve ✓] [Reject ✗] │
└─────────────────────────────────────┘After clicking:
- Button shows loading state
- Flow resumes execution
- Final result is displayed
In WebChat
The approval UI integrates seamlessly with WebChat:
<!-- Approval appears inline in conversation -->
<div class="approval-box">
<p>Approve payment of $1,250.00 to vendor?</p>
<button onclick="approve()">Approve</button>
<button onclick="reject()">Reject</button>
</div>Flow Examples
Example 1: Simple Approval
Trigger: User message
↓
Parse Request (extract item details)
↓
User Approval: "Delete item {{itemName}}?"
├─ Approve → Delete Item → Final (Deleted successfully)
└─ Reject → Final (Deletion cancelled)Example 2: Multi-Step with Approval
Trigger: Form submission
↓
Validate Data
↓
Calculate Cost ({{totalCost}})
↓
User Approval: "Process payment of {{totalCost}}?"
├─ Approve → Charge Payment
│ ↓
│ Send Confirmation Email
│ ↓
│ Final (Payment successful)
└─ Reject → Final (Payment cancelled)Example 3: Multiple Approvals
Trigger: Complex workflow
↓
Prepare Action
↓
User Approval 1: "Approve data changes?"
├─ Approve → Apply Changes
│ ↓
│ User Approval 2: "Finalize and publish?"
│ ├─ Approve → Publish → Final (Published)
│ └─ Reject → Final (Not published)
└─ Reject → Final (Changes not applied)Example 4: Conditional Approval
Trigger: Process order
↓
Calculate Total ({{total}})
↓
Condition: If {{total}} > 1000
├─ True → User Approval: "Approve {{total}} order?"
│ ├─ Approve → Process Order → Final
│ └─ Reject → Final (Order cancelled)
└─ False → Process Order → Final (Auto-processed)Using Context Variables
You can use any context variables in your approval message:
Available Variables
// From trigger
{{input.fieldName}}
// From previous steps
{{stepOutput.value}}
// Current item in loops
{{item.property}}
// Custom variables
{{customVariable}}Examples
"Approve transfer of {{amount}} {{currency}} to {{recipient}}?"
"Delete {{count}} items?"
"Send email to {{email}} with subject '{{subject}}'?"
"Publish {{title}} to {{platform}}?"
"Grant {{role}} access to {{userName}}?"API Integration
For Custom Implementations
If you're building a custom UI or integration, you can interact with the approval system via API:
Resume Message Endpoint
POST /api/v1/peer/message/:messageId/resumeRequest:
{
"decision": "approve" // or "reject"
}Response:
{
"success": true,
"message": {
"_id": "msg_123",
"status": "completed",
"content": "Action completed successfully",
"approval": {
"decision": "approve",
"timestamp": "2025-10-23T00:51:05Z"
}
}
}JavaScript Example
async function resumeMessage(messageId, decision) {
const response = await fetch(`/api/v1/peer/message/${messageId}/resume`, {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ decision })
});
return response.json();
}
// Usage
await resumeMessage('msg_123', 'approve');Technical Details
State Management
When a flow pauses for approval:
- State Saved: Current execution context is serialized and saved to database
- Message Updated: Message status changes to
pending_approval - User Notified: Approval UI is displayed
- Flow Paused: Execution stops, resources are released
When user responds:
- State Loaded: Saved context is retrieved from database
- Flow Resumed: Execution continues from the exact point it paused
- Decision Applied: Flow branches based on approve/reject
- Completion: Remaining steps execute and final result is returned
Performance
- State Size: Context is efficiently serialized (~5-50KB typical)
- Resume Time: <500ms from approval click to flow resumption
- Scalability: Can handle thousands of pending approvals
- Timeout: No automatic timeout (approval can wait indefinitely)
Best Practices
Message Design
✅ Good Messages:
- Clear and concise
- Include relevant context
- State consequences
- Use action verbs
"Delete 50 products? This cannot be undone."
"Approve $1,250 payment to Vendor XYZ?"
"Send invoice #12345 to customer@email.com?"❌ Avoid:
- Vague messages: "Continue?"
- Missing context: "Approve?"
- Too much text: Long paragraphs
- Technical jargon: "Execute DELETE operation?"
Flow Design
✅ Do:
- Place approval before critical actions
- Test both approve and reject paths
- Provide meaningful final messages
- Use for genuinely important decisions
❌ Don't:
- Chain too many approvals (hurts UX)
- Use for trivial confirmations
- Forget to handle reject path
- Block non-critical operations
Error Handling
Always handle potential issues:
User Approval: "Proceed with action?"
├─ Approve → Try Action
│ ├─ Success → Final (Completed)
│ └─ Error → Final (Failed: {{error}})
└─ Reject → Final (Cancelled by user)Troubleshooting
Approval Not Showing
Possible Causes:
- Flow hasn't reached approval step yet
- Frontend not properly integrated
- WebSocket connection issues
Solutions:
- Check flow execution logs
- Verify message status is
pending_approval - Test WebSocket connectivity
Resume Fails
Possible Causes:
- Invalid message ID
- Message already completed
- State data corrupted
Solutions:
- Verify message ID is correct
- Check message status before resuming
- Review server logs for errors
Flow Doesn't Continue
Possible Causes:
- Next step not connected properly
- Error in subsequent step
- Missing required variables
Solutions:
- Verify step connections in Flow Editor
- Check step validation
- Review execution context
Advanced Use Cases
Approval with Timeout
User Approval: "Approve within 5 minutes?"
├─ Approve → Execute Action
└─ Reject → Cancel
(External timeout mechanism)
After 5 minutes → Auto-reject via APIApproval with Delegation
User Approval 1: "Manager approval required"
├─ Approve → User Approval 2: "Director approval required"
│ ├─ Approve → Execute
│ └─ Reject → Cancel
└─ Reject → CancelApproval with Conditions
Calculate Risk Score
↓
Condition: If {{riskScore}} > 7
├─ High Risk → User Approval: "High risk detected!"
│ ├─ Approve → Execute with Extra Validation
│ └─ Reject → Cancel
└─ Low Risk → Auto ExecuteRelated Documentation
- Flow Steps Overview - All available flow steps
- Flow Editor Guide - How to create flows
- WebChat Integration - Embedding approvals in websites
- API Reference - Resume endpoint details
Summary
User Approval adds a human-in-the-loop capability to your flows:
- Pause & Resume: Stop execution, wait for user input, continue safely
- Flexible: Use anywhere in your flow with any context variables
- Branching: Different paths for approve vs. reject
- Persistent: State is saved, can wait indefinitely
- User-Friendly: Clean UI in chat and webchat interfaces
Common Pattern:
Action Preparation → User Approval → Execute if Approved → Final ResultUse User Approval to add safety, compliance, and human oversight to your automated workflows!

