TabSailTabSail

Human handoff

Transfer control, let a person act, then reconnect automation.

Automation → Request handoff → Human control → Return → Reconnect automation

Request control

With an initialized client and a ready session:

const handoff = await client.sessions.handoffs.create(sessionId, {
  reason: "Complete the website's sign-in step",
});
ParameterTypeRequiredDefaultDescription
reasonstringNoEmptyUp to 256 characters
idempotencyKeystringNo in SDKGeneratedRequest option; 1–128 characters

Wait until the handoff is active and the session reports human control, then issue the control grant:

const control = await client.sessions.connections.create(sessionId, {
  type: "live",
  mode: "control",
  handoffId: handoff.id,
});

Deliver control.url only to the authorized person. Old control channels are revoked.

Return control

await client.sessions.handoffs.complete(sessionId, handoff.id);
await client.sessions.handoffs.waitUntilCompleted(sessionId, handoff.id);

returning is still in progress. Leaving the viewer does not complete a handoff.

Resume automation

Record a checkpoint while ready and controlled by automation:

import { handoffCheckpoint } from "tabsail";

const after = handoffCheckpoint(await client.sessions.get(sessionId));
const resumed = await client.sessions.waitForHandoff(sessionId, {
  after,
  timeoutMs: 300_000,
});
const grant = await client.sessions.connections.create(resumed.id, { type: "cdp" });

Take this checkpoint before the human step starts. Reconnect and acquire context, page, and locator objects again. Inspect the person's changes before continuing.

Handoff waiting does not replay your task or stop the browser on timeout. Human work still uses lifetime, concurrency, and credits.

See the complete human-assisted example.

On this page