Approval Policies (Human-in-the-Loop)
Set up human-in-the-loop approval workflows for risky tool operations.
Overview
Approval policies require user confirmation before executing sensitive tool operations. This provides:
- Safety layer for destructive operations (delete, transfer funds, etc.)
- Compliance with regulations requiring human oversight
- Audit trail of approved/rejected operations
- User control over high-stakes AI actions
When to Use Approval Policies
Use approval policies for:
- Destructive operations (delete records, close accounts)
- Financial transactions (transfer funds, process payments)
- Data modifications with compliance requirements
- Administrative functions (create users, modify permissions)
- Any operation that should not be fully automated
User Experience
When an approval is required:
- AI attempts tool execution → Policy intercepts
- Dialog appears showing tool name, parameters, countdown timer
- User chooses:
- Approve - Execute with original parameters
- Edit & Approve - Modify parameters first, then execute
- Reject - Cancel operation, AI receives rejection message
- AI continues with result or handles rejection
Core Concepts
Tool Pattern Matching
Policies use glob patterns to match tool names:
| Pattern | Matches | Use Case |
|---|---|---|
delete_* | delete_user, delete_record, delete_order | All deletions |
transfer_* | transfer_funds, transfer_ownership | Financial transfers |
*_admin_* | create_admin_user, modify_admin_settings | Admin operations |
[!get]* | Everything except get_* | Non-read operations |
close_account | close_account (exact match) | Specific operation |
Policy Priority
When multiple policies could match, highest priority wins (1-100 scale):
[
{
"toolPattern": "delete_user",
"priority": 100,
"timeoutSeconds": 300
},
{
"toolPattern": "delete_*",
"priority": 50,
"timeoutSeconds": 120
}
]
Result: delete_user uses 300s timeout (priority 100 overrides priority 50)
Timeout Behavior
- Range: 10-600 seconds (default: 120)
- On timeout: Treated as rejection
- AI receives: Timeout message, should acknowledge and offer alternatives
Approval Dialog Components
Users see:
- Tool name (e.g., "delete_user")
- Parameters (e.g.,
{ userId: "emp_123", reason: "offboarding" }) - Countdown timer (e.g., "2:00 remaining")
- Description (if policy has
descriptionfield) - Severity badge (auto-assigned based on tool pattern)
Creating Approval Policies
Via Admin API (REST)
Create a policy:
POST /admin/assistants/{assistantId}/approval-policies
Content-Type: application/json
X-Admin-Token: your-admin-token
{
"assistantId": "ast_abc123",
"toolPattern": "delete_*",
"timeoutSeconds": 180,
"priority": 50,
"enabled": true,
"description": "Deletion operations require confirmation to prevent accidental data loss"
}
Response:
{
"success": true,
"data": {
"id": "policy_xyz",
"toolPattern": "delete_*",
"timeoutSeconds": 180,
"priority": 50,
"enabled": true,
"description": "Deletion operations require confirmation...",
"createdAt": "2025-01-15T10:30:00Z"
}
}
List policies:
GET /admin/assistants/{assistantId}/approval-policies
X-Admin-Token: your-admin-token
Update a policy:
PATCH /admin/assistants/{assistantId}/approval-policies/{policyId}
Content-Type: application/json
{
"timeoutSeconds": 300,
"description": "Updated description"
}
Delete a policy:
DELETE /admin/assistants/{assistantId}/approval-policies/{policyId}
X-Admin-Token: your-admin-token
Via MCP Admin Server (Natural Language)
With Claude Desktop + MCP Admin Server configured:
Create policies:
Create an approval policy for all delete operations with a 3-minute timeout
Require approval for transfer_funds with 5-minute timeout and description "Financial transactions require supervisor approval"
Add approval policy for pattern "*_admin_*" to require confirmation for all admin tools
List policies:
Show me all approval policies for this assistant
What approval policies are active?
Update:
Update the delete_* approval policy to have a 5-minute timeout
Disable the transfer_funds approval policy temporarily
Delete:
Remove the approval policy for create_user
Policy Configuration
Tool Patterns
Exact match:
{
"toolPattern": "close_account"
}
Matches: close_account only
Prefix wildcard:
{
"toolPattern": "delete_*"
}
Matches: delete_user, delete_record, delete_anything
Suffix wildcard:
{
"toolPattern": "*_admin"
}
Matches: create_admin, user_admin, system_admin
Contains:
{
"toolPattern": "*_sensitive_*"
}
Matches: get_sensitive_data, update_sensitive_record
Negation:
{
"toolPattern": "[!get]*"
}
Matches: Everything EXCEPT tools starting with get_
Timeout Settings
| Timeout | Use Case |
|---|---|
| 30s | Quick confirmations (archive, mark complete) |
| 120s (default) | Standard operations (delete, update) |
| 300s | Financial operations (transfer, process payment) |
| 600s | Critical admin functions (delete database, revoke access) |
Guideline: Set timeout based on:
- How much time user needs to verify parameters
- Risk level of operation
- Whether user might need to consult documentation
Too short → Users feel rushed, approval fatigue Too long → Users forget, timeouts happen, AI flow breaks
Priority Configuration
Use priority to:
- Override generic patterns with specific rules
- Control which policy applies when multiple match
Example:
[
{
"toolPattern": "delete_production_database",
"priority": 100,
"timeoutSeconds": 600,
"description": "CRITICAL: This will delete the production database!"
},
{
"toolPattern": "delete_*",
"priority": 50,
"timeoutSeconds": 120,
"description": "Standard deletion confirmation"
}
]
Result: delete_production_database gets 600s timeout and critical warning. All other deletes get 120s.
Description Field
The description appears in the approval dialog. Use it to:
- Explain why approval is needed
- Provide context for the operation
- Link to documentation or policies
- Warn about consequences
Good descriptions:
"Financial transactions require supervisor approval per company policy FIN-301"
"Deletion operations cannot be undone. Please verify you want to permanently remove this data."
"Admin functions affect all users. Ensure you have proper authorization before proceeding."
Bad descriptions:
"Needs approval" // Not helpful
"Be careful" // Too vague
"" // Empty - user doesn't know why they're seeing this
User Experience
Approval Dialog
What users see:
┌─────────────────────────────────────────┐
│ Tool Approval Required │
├─────────────────────────────────────────┤
│ Tool: delete_user │
│ │
│ Parameters: │
│ { │
│ "userId": "emp_12345", │
│ "reason": "offboarding" │
│ } │
│ │
│ This operation requires your approval. │
│ Time remaining: 1:45 │
│ │
│ [Reject] [Edit & Approve] [Approve] │
└─────────────────────────────────────────┘
After Approval
If approved:
- Tool executes with approved parameters
- AI receives result (success or error)
- AI continues conversation with result
Example AI flow:
User: Delete John's account
AI: [Triggers delete_user tool]
[Approval dialog appears]
User: [Approves]
AI: "I've deleted John's account (emp_12345). The account and all associated data have been permanently removed."
After Rejection
If rejected:
- Tool execution is canceled
- AI receives rejection message
- AI should acknowledge and offer alternatives
Example AI flow:
User: Delete John's account
AI: [Triggers delete_user tool]
[Approval dialog appears]
User: [Rejects]
AI: "I understand you've chosen not to delete John's account. Would you like me to:
- Archive the account instead?
- Suspend the account temporarily?
- Show you the account details first?"
Edit & Approve
Users can modify parameters before approving:
Example:
User wants to: delete_user(userId: "emp_wrong", reason: "offboarding")
Dialog shows parameters
User edits: userId: "emp_12345" (corrects ID)
Approves with edited params
Tool executes: delete_user(userId: "emp_12345", reason: "offboarding")
Monitoring & Audit
Approval Logs
Every approval request is logged with:
- Tool name and parameters
- User who approved/rejected
- Decision (approved/rejected/timeout)
- Timestamp
- Execution result (if approved)
Query logs:
POST /admin/assistants/{assistantId}/approval-logs/query
Content-Type: application/json
{
"toolName": "delete_user",
"decision": "rejected",
"fromDate": "2025-01-01",
"toDate": "2025-01-31",
"limit": 100
}
Response:
{
"logs": [
{
"approvalId": "appr_123",
"toolName": "delete_user",
"toolParameters": { "userId": "emp_12345" },
"decision": "rejected",
"requesterUserId": "user_456",
"decidedAt": "2025-01-15T14:30:00Z",
"reason": "Wrong user ID"
}
],
"total": 1
}
Query by decision:
# All timeouts (might indicate timeout too short)
{ "decision": "timeout" }
# All rejections (might indicate AI misbehavior)
{ "decision": "rejected" }
# All approvals (for compliance audit)
{ "decision": "approved" }
Query by user:
# See what one user approved/rejected
{ "requesterUserId": "user_123" }
Query by date range:
# Last month's activity
{
"fromDate": "2025-12-01",
"toDate": "2025-12-31"
}
Statistics
Get aggregate stats:
GET /admin/assistants/{assistantId}/approval-stats
Response:
{
"totalRequests": 1250,
"approved": 980,
"rejected": 200,
"timedOut": 70,
"pending": 0,
"approvalRate": 0.784,
"avgDecisionTimeMs": 8500,
"byTool": {
"delete_user": {
"total": 500,
"approved": 450,
"rejected": 40,
"timedOut": 10
},
"transfer_funds": {
"total": 300,
"approved": 250,
"rejected": 30,
"timedOut": 20
}
}
}
Use stats to:
- Identify tools with high rejection rates (AI might be misbehaving)
- Find timeouts (might need longer timeout)
- Track approval patterns (is someone rubber-stamping?)
- Generate compliance reports
Common Patterns
Destructive Operations
{
"toolPattern": "delete_*",
"timeoutSeconds": 120,
"priority": 50,
"description": "Deletion operations are permanent and cannot be undone."
}
Financial Operations
{
"toolPattern": "transfer_*",
"timeoutSeconds": 300,
"priority": 80,
"description": "Financial transactions require supervisor approval per company policy."
}
{
"toolPattern": "process_payment",
"timeoutSeconds": 300,
"priority": 80,
"description": "Payment processing requires confirmation of amount and recipient."
}
Admin Functions
{
"toolPattern": "*_admin",
"timeoutSeconds": 180,
"priority": 70,
"description": "Administrative functions affect all users. Ensure proper authorization."
}
Specific High-Risk Operations
{
"toolPattern": "drop_database",
"timeoutSeconds": 600,
"priority": 100,
"description": "CRITICAL: This will permanently delete the entire database! Contact senior admin before proceeding."
}
Entity Context (Diff Display)
When approval is configured with entity context, the dialog shows the current state of the affected entity alongside the proposed changes. This helps users make informed decisions.
How Entity Context Works
For update operations, the dialog shows a side-by-side diff of current values vs. proposed changes.
Configuring Entity Context
Entity context is configured at the MCP instance level. When adding approval requirements to an MCP server, you can specify:
| Setting | Description |
|---|---|
| Companion Tool | A read/get tool to fetch entity state (e.g., get_user for delete_user) |
| Operation Type | create, read, update, or delete |
| Entity Type | Human-readable label (e.g., "User", "Order") |
| Entity ID Param | Which tool parameter contains the entity ID |
| Parameter Mapping | Map action tool params to companion tool params |
| Include Fields | Only show these fields in the dialog |
| Exclude Fields | Hide these fields (for sensitive data like passwords, SSNs) |
Example configuration:
{
"toolName": "delete_user",
"companionTool": "get_user",
"operationType": "delete",
"entityType": "User",
"entityIdParam": "userId",
"parameterMapping": { "userId": "id" },
"includeFields": ["name", "email", "department", "status"],
"excludeFields": ["passwordHash", "ssn"]
}
Field Filtering
Field filtering controls what entity data appears in the approval dialog:
- MCP level: Sets default
includeFieldsandexcludeFields - Assistant level: Can override
includeFields(to show fewer fields) and add toexcludeFields(for additional privacy) - Security rule:
excludeFieldsfrom both levels are merged (union) — you can only hide more, never less
Always exclude sensitive fields like passwords, API keys, and personal identifiers from approval dialogs.
Pause, Resume & Timeout Behavior
Countdown Pause/Resume
When a user opens the approval dialog to review details, the countdown timer pauses automatically. This prevents timeouts while the user is actively reviewing the request.
- Pause: Timer stops when user interacts with the dialog
- Resume: Timer restarts with remaining time when user dismisses or navigates away
- Safety limit: If paused for more than 1 hour, the approval is auto-rejected
Page Refresh Recovery
If the user refreshes the page or temporarily loses connection while an approval is pending:
- The approval is suspended (timer paused, state preserved)
- When the user reconnects, the approval dialog is restored with the remaining countdown
- If the user doesn't reconnect within 1 hour, the approval is auto-rejected
This means users never lose an approval request due to accidental page refreshes or brief network interruptions.
Disconnect Handling
Timeout Actions
When an approval times out (countdown reaches zero), the configured timeout action determines what happens:
| Action | Description |
|---|---|
| Reject (default) | Treat timeout as rejection — tool does not execute |
| Approve | Treat timeout as approval — tool executes automatically |
Use the approve timeout action sparingly. It should only be used for low-risk operations where the default behavior is acceptable.
Retry Limiting
To prevent infinite loops when the AI repeatedly calls a tool with incorrect parameters, DioscHub limits retries to 3 attempts per tool per session. After the third rejection or timeout, the tool is blocked for the remainder of the session and the AI is informed.
Best Practices
1. Start with High-Risk Operations Only
Don't require approval for everything:
Good:
delete_*,transfer_funds,close_account
Bad:
*(every single tool - approval fatigue)
2. Use Descriptive Policy Descriptions
Users need context when they see the dialog:
Good:
{
"description": "Financial transfers require dual approval per SOX compliance policy FIN-402. Verify recipient and amount before approving."
}
Bad:
{
"description": "Needs approval"
}
3. Set Reasonable Timeouts
Consider what user needs to do:
| Operation | Timeout | Reason |
|---|---|---|
| Simple delete | 120s | Quick verification |
| Financial transfer | 300s | Need to check amount, recipient |
| Admin function | 180s | May need to consult policy |
| Critical operation | 600s | May need supervisor approval |
Too short = Frustrated users, more timeouts Too long = Users forget, AI session stalls
4. Review Rejection Patterns
High rejection rate might mean:
- AI is calling tools inappropriately
- Tool parameters are incorrect
- User doesn't understand what's happening
Example:
50% rejection rate for delete_user
→ Investigate: Is AI suggesting deletions when user wants archive?
→ Solution: Update AI prompt to clarify delete vs archive
5. Don't Over-Approve
Approval fatigue is real:
- Too many approvals → Users stop reading, just click "Approve"
- Defeats the purpose of human oversight
Solution:
- Only require approval for truly risky operations
- Use roles to filter out inappropriate tools instead
- Combine with AI prompt engineering to reduce unnecessary attempts
6. Provide Audit Trail
Use approval logs for:
- Compliance reporting (who approved what, when)
- Security investigations (unusual approval patterns)
- AI behavior analysis (which operations trigger approvals most)
Export logs regularly:
POST /admin/assistants/{assistantId}/approval-logs/export
{
"format": "csv",
"fromDate": "2025-01-01",
"toDate": "2025-01-31"
}
7. Test End-to-End
After creating a policy:
- Trigger the tool operation
- Verify dialog appears with correct timeout
- Test all three options (approve, reject, edit & approve)
- Check logs to verify recording
Troubleshooting
Policy Not Triggering
Symptoms: Tool executes without approval dialog
Checks:
- Verify policy is
enabled: true - Check pattern matches tool name exactly
- Verify priority (higher priority policy might override)
- Check assistant ID is correct
Debug:
# List all policies
GET /admin/assistants/{assistantId}/approval-policies
# Check if pattern matches
# (mentally test: does "delete_user" match "delete_*"? Yes)
Timeout Too Fast
Symptoms: Dialogs timing out before users can read them
Solution:
Increase timeoutSeconds:
PATCH /admin/assistants/{assistantId}/approval-policies/{policyId}
{
"timeoutSeconds": 300 # Increase from 120 to 300
}
Users Confused by Dialog
Symptoms: High rejection rate, user complaints
Solution:
Improve description field:
PATCH /admin/assistants/{assistantId}/approval-policies/{policyId}
{
"description": "This will permanently delete the user account and all associated data. This action cannot be undone. Verify the user ID before approving."
}
AI Not Handling Rejections Well
Symptoms: AI stops responding or doesn't offer alternatives after rejection
Solution: Update assistant system prompt:
When a tool execution is rejected, acknowledge the rejection gracefully and offer alternative approaches. Never retry the same tool without user permission. Example: "I understand you've chosen not to proceed with that action. Would you like me to suggest alternatives?"
API Reference
| Method | Endpoint | Description |
|---|---|---|
POST | /admin/assistants/{id}/approval-policies | Create policy |
GET | /admin/assistants/{id}/approval-policies | List policies |
GET | /admin/assistants/{id}/approval-policies/{policyId} | Get policy |
PATCH | /admin/assistants/{id}/approval-policies/{policyId} | Update policy |
DELETE | /admin/assistants/{id}/approval-policies/{policyId} | Delete policy |
POST | /admin/assistants/{id}/approval-logs/query | Query logs |
GET | /admin/assistants/{id}/approval-stats | Get statistics |
Policy Fields
| Field | Type | Required | Default | Range | Description |
|---|---|---|---|---|---|
toolPattern | string | Yes | - | Glob pattern | Tool name pattern to match |
timeoutSeconds | number | No | 120 | 10-600 | Approval timeout in seconds |
priority | number | No | 5 | 1-100 | Priority for matching (higher first) |
enabled | boolean | No | true | - | Whether policy is active |
description | string | No | - | - | Human-readable description for dialog |
Next: Sitemap & Navigation - Configure intelligent navigation for your application.