Skip to main content
Put a person’s yes or no into the run as a step, so the work waits for the answer and carries on from it. Use it before anything irreversible: a release, a migration, money leaving an account. When the judgement can be a model’s, use a review panel with a threshold instead and keep the person for the last word. This is human-in-the-loop as a step that can say no, not a slide: yes passes the step, no carries the person’s note to the step that owns the fix, and no answer pauses the run until one arrives.

Shape

The step

approval asks one question through the run’s callbacks client, and target names the step a no goes to:
examples/approval.ts (excerpt)
The question is about what came before: by default the request’s input is the outcomes of the steps this one depends on, so a changed attempt upstream is a new question, and the same question about the same thing is the same request. Give input to say otherwise, or bind the approval to the exact files it approved with proof acceptance. A no needs a home and a budget. With target, the refusal goes to that step as a revision request with the note as its one finding, and the graph’s maxKickbacks must allow it, or the run fails with the note instead. Without a target, a refusal fails the step with the note as its summary:
examples/approval.ts (excerpt)
Nobody answering is a pause, not a failure. Without answer, the step posts the request and returns paused with the request as its data. A router claims the request and submits { approved, note? }. Run the job again with the same client and the step finds the answer in the client’s history. run takes that client as callbacks: the in-memory one that lives for the run, the default, or the stored client over a directory, which lets a paused run find its answer after a restart. Use one approval label per workflow; two steps with the same label ask the same question and supersede each other. A question that is neither pending nor answered fails the step plainly instead of waiting for nothing.

What the run did

The writer here is a function that leaves the header row out once, and the person answers from the file itself, so it runs offline. Run it with npx tsx approval.ts:
Output
The person said no to the first attempt and yes to the second. implement ran twice: the refusal went there as a revision request with the note as its finding, the writer ran again with the note in hand, and the question was asked again about the new attempt. In a real team the answer arrives through the callbacks client, from a surface in a browser or a host.
examples/approval.ts

Next steps

  • Feature delivery: a person’s decision as the eighth stage of a real team, where the run pauses on the record.
  • Callback gates: the client, the routers and the stored history the step is built on.
  • Runtime: approval, pipeline and maxKickbacks.