This feature is in preview. The API may change before general availability. To try it out, contact support@intunedhq.com and we’ll enable it for your workspace.
Overview
Some automations can’t be fully automated. A portal asks a security question only your customer can answer, a document needs a judgment call, or a final submission needs a person to review it. Human in the loop lets an automation stop, involve a person, and carry on. Intuned gives you two runtime helpers:
Both work the same way: Intuned posts a request to an endpoint on your system, then waits. You own the operator experience—who gets asked, what the UI looks like, how requests are queued and escalated. Intuned supplies the trigger, the callback, and the browser stream.
Waiting on a person does not count toward the attempt’s
requestTimeout. The timeout you pass to the helper is the only limit on the wait, so a Run can sit waiting for hours without its automation timeout expiring.When to use which
UsehumanInTheLoop when you need a value and your automation can take it from there:
- A security question, a one-time code read off a device, or a CAPTCHA your solver can’t handle
- A classification or approval decision—“is this the right invoice?”
- Disambiguation—three accounts matched, which one is it?
handOverControlToHuman when the remaining work is easier to do than to describe:
- A multi-step identity verification flow that changes every time
- A final submission someone must review on screen before confirming
- An exception path that’s too rare to be worth automating
Prerequisites
- A backend service that accepts HTTP POST requests from Intuned, on a publicly accessible HTTPS URL.
- For
handOverControlToHuman: the project must run in headful mode ("headful": true). There’s no browser to stream otherwise.
Configure your endpoints
Register your endpoints inIntuned.json. The two helpers use separate endpoints—the payloads have little in common, and the handoff flow has no callback at all.
Intuned.json
How it works
Asking a person for data
- Your automation calls
humanInTheLoopwith a prompt, a data schema, and optional supporting material. - Intuned POSTs a request to your
requestEndpoint, including a callback URL. - Your endpoint returns
2xxto acknowledge it. The automation stays paused—acknowledging is not answering. - A person answers in your application. Your backend POSTs the answer to the callback URL.
- Intuned validates the answer against the schema and resumes the automation, which receives the data as the helper’s return value.
timeout, the call throws HumanInTheLoopTimeoutError.
Handing over control
- Your automation calls
handOverControlToHumanas its final step. - Intuned POSTs a request to your
handoffEndpoint, including a stream URL. - Your application shows the stream URL to an operator—in an iframe, or a new tab. They see the live browser and have full keyboard and mouse control.
- The operator finishes the task and selects Complete in the top-right corner of the stream. The stream UI also shows how much time is left.
- The helper returns and the Run completes.
timeout, the stream closes and the call throws HumanInTheLoopTimeoutError.
Request payloads
human_in_the_loop
control_handoff
Same envelope, with streamUrl in place of callbackUrl and dataSchema:
Image supporting material passed as a buffer—for example a
page.screenshot() result—is uploaded by the runtime and delivered as a short-lived signed URL. Fetch it promptly or copy it into your own storage.The callback contract
ForhumanInTheLoop only. POST the answer to the callbackUrl from the request, with the data under a data key:
A
400 doesn’t consume the request, so you can validate interactively—post, show the person the error, let them correct it.
Implementing the endpoints
Your endpoint’s only job is to accept the request quickly and queue it. Return2xx within 5 seconds; do the work of finding a person afterward.
- Express (Node.js)
- Flask (Python)
streamUrl and surface it to an operator. There’s no callback to make.
If your endpoint doesn’t return
2xx, Intuned retries with exponential backoff while the request is still within its timeout. A request that’s never acknowledged times out like one that’s never answered.Timeouts and retries
timeoutis per call, in seconds, defaulting to one hour. Set it from how long a person realistically needs—a queued review might be hours, a live handoff minutes.- The attempt timeout doesn’t apply to the wait.
requestTimeoutkeeps governing your automation’s own execution time. - A timeout fails the attempt. If the Run has retries left, the next attempt runs from the top and issues a new request—the person gets asked again. Wrap the call and throw
NonRetryableErrorif asking twice would be wrong. - Requests are tied to an attempt. The
attemptfield inapiInfolets you detect and collapse duplicates in your queue.
Security
- Authenticate inbound requests. Intuned sends the
headersyou configure on every request. Verify them before acting, and reject anything else. - Treat
callbackUrlandstreamUrlas secrets. Both carry a bearer token. Anyone with the callback URL can answer on your behalf; anyone with the stream URL can drive the browser. Don’t log them, don’t put them in URLs you render to untrusted users, and scope them to the operator who’s handling the request. - Both URLs expire with the request and are single-use.
- A handoff exposes whatever is on screen. The operator sees the live session, including any data already loaded. Only hand control to people authorized to see it.
- Pause tracing around a handoff if the person might type a password or a one-time code. The trace keeps recording while they work. See Pause tracing.
Best practices
- Write prompts for a person who lacks your context. “Pick the account ending 4471” beats “disambiguate account”.
- Attach a screenshot. A
page.screenshot()as supporting material is usually the difference between a fast answer and a wrong one. - Keep schemas small. Ask for the decision, not a transcription of the page. Fewer fields means fewer rejected callbacks.
- Use
metadatafor routing, so your endpoint doesn’t have to parse prompts to decide who should handle a request. - Make your endpoint idempotent on
requestId. Retries and attempt-level retries both produce repeat deliveries. - Alert on requests nearing
expiresAt, so a forgotten review doesn’t silently fail a Run.
Limitations
- You build the operator UI. Intuned doesn’t provide a review queue or an inbox. The endpoint contract is the integration point.
- Your endpoint must be publicly reachable over HTTPS. There’s no polling alternative during preview.
- Handoff requires headful mode, which uses more resources than headless—see the machine
sizeguidance in Intuned.json. - A handoff has no return value. The person’s work shows up as page state, not as data. Call it last.
- Waiting occupies a machine. A Run paused on a person still holds its slot against your project’s
maxCount, so a queue of waiting Runs can block new ones. Sizereplicationwith that in mind. - One request at a time per automation. Both helpers block until they resolve; concurrent requests from a single Run aren’t supported.
FAQs
Is handOverControlToHuman a separate feature from humanInTheLoop?
Is handOverControlToHuman a separate feature from humanInTheLoop?
They’re two helpers for the same problem, documented together because they share project configuration and the same request envelope. They use separate endpoints, and you can adopt either on its own.
What does the person see during a handoff?
What does the person see during a handoff?
The live browser session, streamed over VNC and embeddable in an iframe, with full keyboard and mouse control. A Complete button sits in the top-right corner, next to the time remaining on the handoff
timeout.Can I cancel a request that's waiting?
Can I cancel a request that's waiting?
Cancel the Run with the Run cancel endpoint. The pending request is invalidated and a later callback gets
410.Does the automation keep the same page and session state?
Does the automation keep the same page and session state?
Yes. The browser stays open and the attempt stays alive for the whole wait. When the helper returns, your code continues against the same
page—though after a handoff, the person may have changed what’s on it.Can I use this inside a Job?
Can I use this inside a Job?
Yes, but think about the shape of it. A JobRun that stalls on dozens of human requests will hold machines and run long. Prefer human in the loop on Runs triggered by your application, where a person is already involved.
What if my endpoint is down when a request fires?
What if my endpoint is down when a request fires?
Intuned retries with exponential backoff for as long as the request’s
timeout allows. If it’s never acknowledged, the helper throws HumanInTheLoopTimeoutError and the attempt fails.