Detected country: US
logo
Sign InGet Early Access
GuideRecipesDeveloper
‌
‌
‌
logo

Powered by

  • Home
  • Running and Automating
  • How do I pause and resume a playbook run?

How do I pause and resume a playbook run?

2min read

Share

TL;DR: Ballet can park a playbook run as Paused (suspended) and continue it later on the same run ID. Editors can pause between steps, or a Code step can call metaphor.waitForInput to wait for a human or external signal. Continue from Studio, or wake via the API with a server-issued requestId.

Who this is for

Builders who need human approval, long waits, or a mid-run pause without losing progress.

What are the two pause modes?

In both cases:

  • The run keeps the same runId (History shows one row; the badge flips Running → Pausing → Paused → Running).
  • The sandbox is freed while parked so other runs keep processing.
  • suspended is not a final status — you can Continue or Stop.

How do I pause from Studio?

  1. Start a run from the Play tab.
  2. Click Pause while the run is running.
  3. Ballet finishes the current step, then parks before the next one (reason: operator_pause).
  4. Click Continue when you are ready. The run resumes from the next step — no reply payload is injected into that step.

Use Stop on a paused run to cancel it.

How do I wait for approval inside a step?

In a Code step, checkpoint expensive work first, then park:

const decision = await metaphor.waitForInput({
  prompt: 'Approve this invoice before posting?',
  details: extractedFields, // shown in Studio while waiting
  schema: {
    kind: 'choice',
    options: [
      { id: 'approve', label: 'Approve' },
      { id: 'reject', label: 'Reject' },
    ],
    multiSelect: false,
  },
});

if (decision?.id === 'reject') {
  const result = { ok: false, __next: 'abort' };
} else {
  const result = { ok: true, decision };
}

Rules:

  • Do not busy-wait or poll Slack/email inside the step — that holds a sandbox.
  • Always pass details so reviewers (and notifiers) can see what to approve.
  • On wake, waitForInput returns the reply payload (for example { id: 'approve', label: 'Approve' }).

How does external data arrive on Continue?

For HITL parks, the wake payload is the reply body — not a new set of step input mappings.

  • Studio Continue / choice → that choice becomes the return value of waitForInput.
  • An external system (Slack button, webhook worker) sends the same payload via POST /api/runs/:runId/reply.
  • Optionally pass input on wake to override the run's flow.input for the continued execution.

Discover wake parameters from History → run detail (or GET /api/runs/:id) while status is Paused:

Past plays also show an API resume (curl) snippet with runId and requestId filled in.

What if I need Slack or email approval?

Slack and email are notifiers for the same park — they are not a second pause API. A notifier posts Approve/Reject, then calls the wake API with the parked requestId. Studio Continue uses that same path.

For the full HTTP contract, curl examples, and notifier pattern, see How do I wake a suspended run with reply or resume?.

Related articles

  • How do I wake a suspended run with reply or resume?
  • How do I run a playbook?
  • How do I read runs and run history?
  • Recipe: Invoice and expense processing
  • Ballet glossary

Share