Skip to content
Get started

Human-in-the-loop

#Why a run pauses

A run's Assess phase can decide it needs a person before continuing, moving it out of running into one of three paused statuses (see Runs lifecycle & statuses). Each has its own resume endpoint and its own expected answer shape. While paused, GET /v1/runs/:id includes the pending request under humanRequest:

json
{
  "id": "5e6a7b8c-...-9d0e",
  "status": "needs_input",
  "humanRequest": {
    "id": "9c0a1b2d-...",
    "type": "input",
    "question": "The invoice doesn't state a currency — which should I assume?",
    "status": "pending"
  }
}

#needs_inputPOST /v1/runs/:id/input

The agent asked a free-form question (humanRequest.question) and is waiting on an answer:

bash
curl -X POST "https://api.agentflowbind.com/v1/runs/5e6a7b8c-...-9d0e/input" \
  -H "Authorization: Bearer afb_live_xxxxxxxxxxxx" -H "Content-Type: application/json" \
  -d '{ "answer": "EUR" }'

Returns 202 { "id", "status": "needs_input" } immediately — the run is re-enqueued and moves back to running asynchronously (poll or subscribe to events to see the transition). Calling this when the run isn't currently needs_input returns 409 run_not_awaiting_input. This route accepts an Idempotency-Key header, same semantics as POST /v1/runs.

#needs_approvalPOST /v1/runs/:id/approve

The agent planned an irreversible action (e.g. send_email) and needs explicit sign-off before executing it:

bash
curl -X POST "https://api.agentflowbind.com/v1/runs/5e6a7b8c-...-9d0e/approve" \
  -H "Authorization: Bearer afb_live_xxxxxxxxxxxx" -H "Content-Type: application/json" \
  -d '{ "approved": true, "note": "Confirmed with the supplier by phone" }'

approved: false resumes the run down its rejection path (typically ending in failed or a revised plan, depending on the preset) rather than continuing the approved action. approved is required and must be a boolean; a missing/wrong type gets 400 invalid_request. Wrong status gets 409 run_not_awaiting_approval. This route also accepts Idempotency-Key.

#needs_reviewPOST /v1/runs/:id/review

The agent produced a draft output it isn't confident enough in to finalize on its own, and wants a person to accept it as-is or supply a corrected version:

bash
curl -X POST "https://api.agentflowbind.com/v1/runs/5e6a7b8c-...-9d0e/review" \
  -H "Authorization: Bearer afb_live_xxxxxxxxxxxx" -H "Content-Type: application/json" \
  -d '{
    "accept": false,
    "correctedOutput": { "supplier": { "name": "Acme GmbH" }, "total": 1249.50 },
    "note": "Total had a rounding error"
  }'

accept is required (boolean). accept: true finalizes the agent's own draft; accept: false requires correctedOutput, which becomes the run's final output instead. Wrong status gets 409 run_not_awaiting_review. Unlike /input and /approve, this route does not currently support Idempotency-Key — avoid blind client-side retries on it.

#Building a UI around this

A typical integration:

  1. Create the run, then either poll GET /v1/runs/:id or subscribe to GET /v1/runs/:id/events (listen for the status_changed event).
  2. When status is one of the three needs_* values, read humanRequest and show the right form — a text answer, an approve/reject choice, or an accept/correct-and-submit editor.
  3. POST the answer to the matching endpoint above; go back to step 1 — the run either resumes to running or lands on a terminal status directly (e.g. a rejected approval that has no fallback plan).

If a human step is subscribed via a webhook instead (run.needs_input / run.needs_approval / run.needs_review), the same three endpoints are how you send the answer back once a person has responded out-of-band (a ticket, a Slack message, ...).