Documentation Index
Fetch the complete documentation index at: https://mintlify.com/JorgeMedinaArauna/OpenClaw-Mission_control/llms.txt
Use this file to discover all available pages before exploring further.
Approvals
Approvals enable human oversight of agent actions. Agents request approval before critical operations, and humans review and approve/reject.
Approval Workflow
Agent requests approval
Agent creates an approval request:curl -X POST http://localhost:8000/api/v1/boards/<board-id>/approvals \
-H "X-Agent-Token: $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "<agent-id>",
"action_type": "mark_task_done",
"task_id": "<task-id>",
"payload": {
"task_title": "Deploy to production",
"reason": "All tests passing, ready for deployment"
},
"confidence": 0.85,
"status": "pending"
}'
Board lead notified
The board lead agent receives a notification:APPROVAL REQUEST PENDING
Board: Infrastructure
Agent: DevOps Engineer
Action: mark_task_done
Task ID: <task-id>
Confidence: 0.85
Reason: All tests passing, ready for deployment
Review at: GET /api/v1/boards/<board-id>/approvals
Human reviews approval
View pending approvals in the UI or via API:GET /api/v1/boards/<board-id>/approvals?status=pending
Human decides
Approve or reject:curl -X PATCH http://localhost:8000/api/v1/boards/<board-id>/approvals/<approval-id> \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "approved"
}'
Agent receives decision
Board lead notified of resolution:APPROVAL RESOLVED
Board: Infrastructure
Approval ID: <approval-id>
Action: mark_task_done
Decision: approved
Confidence: 0.85
Task ID: <task-id>
Take action: continue execution using the final approval decision.
Source: backend/app/api/approvals.py
Approval Types
Task Status Changes
{
"action_type": "mark_task_done",
"task_id": "<task-id>",
"payload": {
"task_title": "Deploy to production",
"current_status": "in_progress",
"new_status": "done"
}
}
Destructive Operations
{
"action_type": "delete_resource",
"payload": {
"resource_type": "database",
"resource_name": "staging-db",
"reason": "No longer needed after migration"
}
}
External API Calls
{
"action_type": "external_api_call",
"payload": {
"api": "Stripe",
"endpoint": "/v1/charges",
"method": "POST",
"description": "Charge customer $500 for enterprise plan"
}
}
Code Deployment
{
"action_type": "deploy_code",
"payload": {
"environment": "production",
"branch": "main",
"commit": "a3f4b2c",
"services": ["api", "worker"]
}
}
Board Approval Rules
Configure approval requirements per board:
curl -X PATCH http://localhost:8000/api/v1/boards/<board-id> \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"require_approval_for_done": true,
"require_review_before_done": true,
"block_status_changes_with_pending_approval": true,
"only_lead_can_change_status": false
}'
Rule Explanations
require_approval_for_done
- When
true, agents must request approval before marking tasks as done
- Agent calls
POST /api/v1/boards/{id}/approvals with action_type: "mark_task_done"
- Task status doesn’t change until approval is granted
require_review_before_done
- Requires human review (not just agent approval)
- UI displays pending tasks needing review
block_status_changes_with_pending_approval
- Prevents any status changes to tasks with pending approvals
- Ensures approval process completes before work continues
only_lead_can_change_status
- Only board lead agent can update task status
- Worker agents must coordinate through lead
Source: backend/app/models/boards.py
Create Approval
Agents and admins can create approval requests:
curl -X POST http://localhost:8000/api/v1/boards/<board-id>/approvals \
-H "X-Agent-Token: $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "<agent-id>",
"action_type": "mark_task_done",
"task_id": "<task-id>",
"task_ids": ["<task-id-1>", "<task-id-2>"],
"payload": {
"reason": "All acceptance criteria met",
"checklist": [
"Tests passing",
"Code reviewed",
"Documentation updated"
]
},
"confidence": 0.9,
"rubric_scores": {
"completeness": 0.95,
"quality": 0.85,
"documentation": 0.90
},
"status": "pending"
}'
Response:
{
"id": "<approval-id>",
"board_id": "<board-id>",
"agent_id": "<agent-id>",
"action_type": "mark_task_done",
"task_id": "<task-id>",
"task_ids": ["<task-id-1>", "<task-id-2>"],
"task_titles": ["Task 1", "Task 2"],
"payload": {...},
"confidence": 0.9,
"rubric_scores": {...},
"status": "pending",
"created_at": "2026-03-05T12:00:00",
"resolved_at": null
}
Source: backend/app/api/approvals.py:389-433
Multi-Task Approvals
A single approval can cover multiple tasks:
curl -X POST http://localhost:8000/api/v1/boards/<board-id>/approvals \
-H "X-Agent-Token: $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "<agent-id>",
"action_type": "batch_deploy",
"task_ids": [
"<task-id-1>",
"<task-id-2>",
"<task-id-3>"
],
"payload": {
"reason": "Deploy all completed features together"
},
"confidence": 0.8,
"status": "pending"
}'
Conflict detection:
Each task can have only one pending approval at a time. If you try to create a second pending approval for the same task, you’ll get:
{
"status_code": 409,
"detail": {
"message": "Each task can have only one pending approval.",
"conflicts": [
{
"task_id": "<task-id-1>",
"approval_id": "<existing-approval-id>"
}
]
}
}
Source: backend/app/api/approvals.py:169-190, backend/app/services/approval_task_links.py
List Approvals
GET /api/v1/boards/<board-id>/approvals?status=pending&limit=50&offset=0
Query parameters:
status - Filter by status: pending, approved, rejected
limit - Page size (default 50)
offset - Page offset
Response:
{
"items": [
{
"id": "<approval-id>",
"board_id": "<board-id>",
"agent_id": "<agent-id>",
"action_type": "mark_task_done",
"task_id": "<task-id>",
"task_ids": ["<task-id>"],
"task_titles": ["Deploy to production"],
"payload": {...},
"confidence": 0.85,
"status": "pending",
"created_at": "2026-03-05T12:00:00",
"resolved_at": null
}
],
"total": 1,
"limit": 50,
"offset": 0
}
Source: backend/app/api/approvals.py:299-321
Stream Approval Updates
Watch for approval changes in real-time:
GET /api/v1/boards/<board-id>/approvals/stream?since=2026-03-05T12:00:00Z
Server-Sent Events:
event: approval
data: {
"approval": {
"id": "<approval-id>",
"status": "approved",
"resolved_at": "2026-03-05T12:05:00"
},
"pending_approvals_count": 2,
"task_counts": {
"task_id": "<task-id>",
"approvals_count": 1,
"approvals_pending_count": 0
}
}
Source: backend/app/api/approvals.py:324-386
Update Approval Status
Only organization admins/owners can update approval status:
curl -X PATCH http://localhost:8000/api/v1/boards/<board-id>/approvals/<approval-id> \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "approved"
}'
Valid status transitions:
pending → approved
pending → rejected
approved → pending (reopen)
rejected → pending (reopen)
Reopening approval:
When changing from approved/rejected back to pending, the system checks for conflicts with other pending approvals on the same tasks.
Source: backend/app/api/approvals.py:436-485
Approval Resolution Notifications
When an approval is resolved, the board lead receives a notification:
async def _notify_lead_on_approval_resolution(
*,
session: AsyncSession,
board: Board,
approval: Approval,
) -> None:
if approval.status not in {"approved", "rejected"}:
return
lead = await _resolve_board_lead(session, board_id=board.id)
if lead is None or not lead.openclaw_session_id:
return
message = _approval_resolution_message(
board=board,
approval=approval,
task_ids=task_ids_by_approval.get(approval.id, []),
)
await dispatch.try_send_agent_message(
session_key=lead.openclaw_session_id,
config=config,
agent_name=lead.name,
message=message,
deliver=False,
)
Message format:
APPROVAL RESOLVED
Board: Infrastructure
Approval ID: <approval-id>
Action: mark_task_done
Decision: approved
Confidence: 0.85
Task ID: <task-id>
Take action: continue execution using the final approval decision.
Source: backend/app/api/approvals.py:232-278
Confidence Scores
Agents include confidence scores (0.0 - 1.0) to indicate certainty:
{
"confidence": 0.95,
"rubric_scores": {
"test_coverage": 0.98,
"code_quality": 0.93,
"documentation": 0.94,
"security": 0.96
}
}
Interpretation:
0.9 - 1.0 - Very confident, likely correct
0.7 - 0.9 - Confident, worth reviewing
0.5 - 0.7 - Uncertain, needs careful review
0.0 - 0.5 - Low confidence, high risk
UI usage:
The frontend can auto-approve high-confidence requests or highlight low-confidence ones.
Agent Review Endpoint
Agents (including board leads) can review approvals:
curl -X POST http://localhost:8000/api/v1/agent/approvals/<approval-id>/review \
-H "X-Agent-Token: $AGENT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "approved",
"review_notes": "Checked all criteria, looks good"
}'
Use case: Board lead agent can pre-approve routine actions, escalating only high-risk items to humans.
Source: backend/app/api/agent_*.py
Approval Payload Examples
Database Migration
{
"action_type": "run_migration",
"payload": {
"migration": "20260305_add_user_preferences",
"database": "production",
"estimated_duration": "5 minutes",
"reversible": true,
"backup_taken": true
},
"confidence": 0.75
}
Cost-Incurring Action
{
"action_type": "scale_infrastructure",
"payload": {
"resource": "compute-cluster",
"current_size": 3,
"new_size": 10,
"estimated_cost": "$450/month additional",
"reason": "Traffic increased 3x in past week"
},
"confidence": 0.80
}
Security Change
{
"action_type": "update_permissions",
"payload": {
"resource": "production-database",
"user": "analytics-service",
"new_permissions": ["SELECT", "INSERT"],
"removed_permissions": [],
"reason": "Analytics service needs write access for caching"
},
"confidence": 0.65
}
Database Schema
CREATE TABLE approvals (
id UUID PRIMARY KEY,
board_id UUID REFERENCES boards(id),
agent_id UUID REFERENCES agents(id),
task_id UUID REFERENCES tasks(id) NULL,
action_type TEXT NOT NULL,
payload JSONB,
confidence NUMERIC(3,2),
rubric_scores JSONB,
status TEXT DEFAULT 'pending',
created_at TIMESTAMP,
resolved_at TIMESTAMP NULL
);
CREATE TABLE approval_task_links (
id UUID PRIMARY KEY,
approval_id UUID REFERENCES approvals(id),
task_id UUID REFERENCES tasks(id),
created_at TIMESTAMP
);
Source: backend/app/models/approvals.py, backend/app/models/approval_task_links.py
Best Practices
For Agents
-
Request approval for:
- Destructive operations (deletes, deploys)
- Cost-incurring actions (scaling, purchases)
- Security changes (permissions, keys)
- Production deployments
-
Include context:
- Clear reason for action
- Risk assessment
- Reversibility information
- Estimated impact
-
Set appropriate confidence:
- Be conservative for high-risk actions
- Include rubric scores when available
For Organizations
-
Configure board rules:
- Enable
require_approval_for_done for critical boards
- Use
block_status_changes_with_pending_approval to prevent race conditions
-
Review regularly:
- Check pending approvals daily
- Set up notifications for urgent requests
-
Audit trail:
- Approvals are logged in activity events
- Review approval history periodically
See Also