Skip to main content

Approvals & Human Tasks

Put humans in the loop at any point in an AI workflow. Approvals let a person review and authorise an AI decision before it takes effect. Human Tasks present structured forms that collect input from a user and feed the response into downstream workflow nodes.

Overview

Both Approvals and Human Tasks are backed by the same ApprovalRequest model. The distinction is in how they are created and completed:

  • Approvals — generated automatically by the platform when an action requires human sign-off. A reviewer approves or rejects the request.
  • Human Tasks — generated by a workflow human_task node. A form schema defines the fields the user must fill in. The submitted data is passed as input to downstream nodes.
An ApprovalRequest becomes a Human Task when it is linked to a workflow node and carries a form_schema. Standard approvals have no form schema — they only require an approve or reject decision.

When Approvals are Required

Approvals are triggered in the following scenarios:

  • Experiment AwaitingApproval state — when an experiment transitions to AwaitingApproval, execution is halted until a team member approves the plan. On approval the experiment advances to Approved and then to Executing. On rejection it returns to Planning.
  • Outbound delivery — certain outbound connectors can be configured to require approval before messages are sent, preventing automated sending without human review.
  • Workflow human_task nodes — a node of this type pauses the workflow graph and creates a Human Task for a designated user or role.
  • Budget threshold alerts — when spending approaches plan limits the platform may pause an experiment and request manual review before continuing.

Approval Inbox

The Approval Inbox is available at /approvals. It lists all pending requests for the current team, ordered by creation time.

  • Each request shows the context payload — what the AI was about to do and why approval is needed.
  • Inline Approve and Reject buttons act immediately without a page reload.
  • For Human Tasks, an Open Form button opens the HumanTaskForm Livewire component in a slide-over panel.
  • A status filter lets you review historical decisions (approved, rejected, expired).
Pending approvals also appear in the notification bell in the top navigation bar. Clicking a notification takes you directly to the relevant request.

Approval Statuses

Every ApprovalRequest moves through the following statuses:

Status Meaning Next action
pending Awaiting a human decision. Approve, reject, or wait for expiry.
approved A team member approved the request. The blocked workflow or experiment resumes automatically. Terminal — no further action.
rejected A team member rejected the request. Dependent experiments return to their previous state for revision. Terminal — no further action.
expired No decision was made within the configured window. The platform treats this as a rejection. Re-trigger the source workflow or experiment if needed.

The approvals:expire-stale scheduled command runs every hour and moves overdue pending requests to expired.

Human Tasks

A Human Task is an ApprovalRequest that carries a form_schema JSON Schema. The schema defines the fields that must be completed before the workflow can continue.

When a workflow reaches a human_task node:

  1. The platform creates an ApprovalRequest linked to the node, with the node's form_schema and the assigned user or role.
  2. The workflow execution pauses — no downstream nodes run.
  3. The assigned user sees the task in the Approval Inbox and opens the HumanTaskForm Livewire slide-over.
  4. On submission the form data is validated against form_schema and stored on the request.
  5. The workflow resumes, and the next node receives the submitted data as its input payload.

Example form_schema

bash
{
  "type": "object",
  "required": ["decision", "notes"],
  "properties": {
    "decision": {
      "type": "string",
      "title": "Decision",
      "enum": ["approve", "revise", "discard"],
      "description": "Select the outcome for this campaign draft."
    },
    "notes": {
      "type": "string",
      "title": "Notes",
      "description": "Provide feedback for the AI agent.",
      "minLength": 10
    },
    "budget_override": {
      "type": "number",
      "title": "Budget Override (€)",
      "description": "Optional: override the proposed budget ceiling."
    }
  }
}
The HumanTaskForm component renders each property as a form field using its JSON Schema type and title. String enums become dropdowns. Boolean fields become checkboxes.

SLA Enforcement

Human Tasks can carry an SLA deadline. If the task is not completed by that deadline, the platform escalates or expires it automatically.

The human-tasks:check-sla scheduled command runs every 5 minutes and performs two checks:

  • Escalation — if the task is approaching its deadline (configurable warning window), team admins and the assigned user receive a notification.
  • Expiry — if the deadline has passed, the task is marked expired and the blocked workflow node is failed, allowing the workflow to continue along its error path.
When a Human Task expires the associated workflow node transitions to a failed state. Make sure your workflow graph includes an error edge from human_task nodes to a recovery path, or the workflow execution will terminate.

Webhook Notifications

You can configure a webhook URL to receive real-time events whenever an approval is created, approved, rejected, or expires. This is useful for integrating approval state into external tools such as Slack, Jira, or a custom dashboard.

Events are sent as POST requests with a JSON body:

bash
{
  "event": "approval.approved",
  "approval_request_id": "019501de-...",
  "status": "approved",
  "decided_by": "user@example.com",
  "decided_at": "2026-03-21T14:05:00Z",
  "context": { ... }
}

Configure the webhook endpoint using the approval_webhook_config MCP tool or via the Team Settings page.

MCP Tools

All approval and human-task operations are available to AI agents via the FleetQ MCP server.

Tool Description
approval_list List approval requests for the team. Filter by status, type, or date range.
approval_approve Approve a pending request by ID. Accepts an optional comment.
approval_reject Reject a pending request by ID. Accepts an optional reason.
approval_complete_human_task Submit the completed form for a Human Task. Accepts a form_data object validated against the task's form_schema.
approval_webhook_config Get or update the approval webhook URL and signing secret for the team.

API Endpoints

All endpoints are under /api/v1/approvals and require a Sanctum bearer token.

Method Path Description
GET /api/v1/approvals List all approval requests. Supports ?status=, ?type=, and cursor pagination.
GET /api/v1/approvals/{id} Retrieve a single approval request including its context and form schema.
POST /api/v1/approvals/{id}/approve Approve a pending request. Body: { "comment": "..." } (optional).
POST /api/v1/approvals/{id}/reject Reject a pending request. Body: { "reason": "..." } (optional).
POST /api/v1/approvals/{id}/complete-human-task Submit a completed Human Task form. Body: { "form_data": { ... } }, validated against form_schema.
POST /api/v1/approvals/{id}/escalate Manually escalate a pending request, notifying team admins immediately.

Integration with Workflows

Human Task nodes are first-class citizens of the workflow graph. See the Workflows documentation for full details on building visual DAGs.

Key points when using Human Tasks inside a workflow:

  • A human_task node pauses workflow execution. No nodes downstream of it will run until the task is completed or expires.
  • The form_schema is defined on the workflow node configuration and may reference upstream node outputs using template variables.
  • Once the task is completed, the submitted form_data object becomes the output of the node and is available to all downstream nodes via the standard {{ node_id.field_name }} template syntax.
  • Add an error edge from every human_task node to handle the case where the task expires without a response.
bash
{
  "id": "review-copy",
  "type": "human_task",
  "label": "Review campaign copy",
  "config": {
    "assigned_role": "admin",
    "sla_hours": 24,
    "form_schema": {
      "type": "object",
      "required": ["approved"],
      "properties": {
        "approved": { "type": "boolean", "title": "Approve this copy?" },
        "feedback": { "type": "string", "title": "Feedback for the writer" }
      }
    }
  }
}
You can place multiple human_task nodes in sequence to implement multi-stage review processes — for example, a writer review followed by a legal sign-off.