Human in the Loop

The Human in the Loop block pauses a run and waits for a person before it continues. Use it for approval gates, to collect feedback, or to gather input at a decision point. The run stays paused — with no timeout — until someone responds through the approval portal, the API, or a webhook.

Configuration

Display Data

What the approver sees — the context shown in the portal to help them decide. Build it field by field or as JSON, referencing earlier outputs with <blockName.output>.

{
  "customerName": "<agent1.content.name>",
  "proposedAction": "<router1.selectedPath>",
  "confidenceScore": "<evaluator1.score>",
  "generatedEmail": "<agent2.content>"
}

Notification

How approvers are alerted that a decision is waiting. Include the approval URL (<blockId.url>) in the message so they can open the portal. Available channels:

  • Slack — a message to a channel or DM
  • Gmail — an email with the approval link
  • Microsoft Teams — a channel notification
  • SMS — a text alert via Twilio
  • Webhook — a request to your own notification system

Resume Form

The fields the approver fills in when responding. Each becomes available to downstream blocks once the run resumes.

{
  "approved": {
    "type": "boolean",
    "description": "Approve or reject this request"
  },
  "comments": {
    "type": "string",
    "description": "Optional feedback or explanation"
  }
}

Access resume data in downstream blocks using <blockId.fieldName>.

Approval Methods

Approval Portal

Every block generates a unique portal URL (<blockId.url>) with a visual interface showing all paused output data and form fields for resume input. Mobile-responsive and secure.

Share this URL in notifications for approvers to review and respond.

REST API

Programmatically resume workflows through the v2 run resource. The contextId is available from the block's resumeEndpoint output or from the _resume object in the paused run response.

POST /api/v2/workflows/{workflowId}/runs/{runId}/resume
Content-Type: application/json
X-API-Key: your-api-key

{
  "contextId": "<contextId>",
  "input": {
    "approved": true,
    "comments": "Looks good to proceed"
  }
}

The resume endpoint automatically respects the execution mode used in the original execute call:

  • Sync mode (default) — The response waits for the remaining workflow to complete and returns the full result:
{
  "data": {
    "runId": "<resumeRunId>",
    "workflowId": "<workflowId>",
    "status": "completed",
    "output": { ... },
    "error": null,
    "startedAt": "...",
    "endedAt": "...",
    "durationMs": 1234
  }
}

If the resumed workflow hits another HITL block, the response returns "status": "paused" with new _resume URLs in the output.

  • Stream mode (stream: true on the original execute call) — The resume response streams SSE events with selectedOutputs chunks, just like the initial execution.

  • Async mode (async: true on the original v2 execute call) — The resume dispatches the run to a background worker and returns immediately with 202, including the resume attempt's runId and v2 statusUrl for polling:

{
  "data": {
    "runId": "<resumeRunId>",
    "statusUrl": "/api/v2/workflows/<workflowId>/runs/<resumeRunId>"
  }
}

Polling run status

Poll the statusUrl from the async response to check when the resume completes:

GET /api/v2/workflows/{workflowId}/runs/{resumeRunId}?includeOutput=true
X-API-Key: your-api-key

Returns the run status and, when completed, the full workflow output.

The legacy endpoint remains available without behavior changes for existing integrations:

POST /api/resume/{workflowId}/{executionId}/{contextId}

Its async response continues to expose jobId and the legacy /api/jobs/{jobId} polling URL.

To check on a paused execution's pause points and resume links:

GET /api/resume/{workflowId}/{executionId}
X-API-Key: your-api-key

Returns the paused execution detail with all pause points, their statuses, and resume links. Returns 404 when the execution has completed and is no longer paused.

Webhook

Add a webhook tool to the Notification section to send approval requests to external systems. Integrate with ticketing systems like Jira or ServiceNow.

API Execute Behavior

When triggering a workflow through POST /api/v2/workflows/{workflowId}/execute, HITL blocks cause the execution to pause and return the _resume data in the v2 response envelope. The legacy POST /api/workflows/{id}/execute endpoint remains available for existing integrations.

The response includes the full pause data with resume URLs:

{
  "data": {
    "runId": "<runId>",
    "workflowId": "<workflowId>",
    "status": "paused",
    "output": {
      "data": {
        "operation": "human",
        "_resume": {
          "apiUrl": "/api/resume/{workflowId}/{executionId}/{contextId}",
          "uiUrl": "/resume/{workflowId}/{executionId}",
          "contextId": "<contextId>",
          "executionId": "<executionId>",
          "workflowId": "<workflowId>"
        }
      }
    },
    "error": null
  }
}

Blocks before the HITL stream their selectedOutputs normally. When execution pauses, the final SSE event includes status: "paused" and the _resume data:

data: {"blockId":"agent1","chunk":"streamed content..."}
data: {"event":"final","data":{"success":true,"output":{...,"_resume":{...}},"status":"paused"}}
data: "[DONE]"

On resume, blocks after the HITL stream their selectedOutputs the same way.

HITL blocks are automatically excluded from the selectedOutputs dropdown since their data is always included in the pause response.

Returns 202 immediately. Use the polling endpoint to check when the execution pauses.

Examples

Approve content before it ships

The run pauses at the Human in the Loop block until someone approves; on resume, the API publishes. The same gate works before any action, like sending a customer email.

Chain multiple approvals

For a high-stakes change, chain two approval steps — a manager, then a director — before the workflow executes.

Verify extracted data

A reviewer checks the data an Agent extracted before a Function processes it.

Outputs

OutputWhat it is
urlThe approval portal URL
resumeEndpointThe resume API endpoint
responseThe display data shown to the approver
submissionThe approver's form submission
submittedAtISO timestamp of when the run resumed
<fieldName>Each Resume Form field, by name, after the run resumes

Read them downstream as <blockName.output> — for a block named approval, that's <approval.approved>.

The approval portal

The example below shows an approval portal as seen by an approver after the workflow is paused. Approvers can review the data and provide inputs as a part of the workflow resumption. The approval portal can be accessed directly via the unique URL, <blockId.url>.

  • Condition - Branch based on approval decisions
  • Variables - Store approval history and metadata
  • Response - Return workflow results to API callers