Add a human approval step
Some flows shouldn't auto-complete. When the LLM's output needs human sign-off — a refund decision, an outbound message, a compliance call — @checkpoint is the primitive. The runtime pauses the flow, persists its scope, and surfaces a request to whatever the host wired up. Resume happens later, with a human decision flowing back into the flow.
This tutorial builds on add an LLM call. It adds a @checkpoint between the @flexible and the return, asks the human to approve the greeting, and routes based on the answer.
1. Insert the @checkpoint#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
Three things to notice: the @checkpoint is bound to decision so the resolution becomes a value, the options list constrains what the human can pick, and a @match block routes on the decision. on_timeout = "escalate" tells the runtime to surface a longer-lived signal rather than failing outright if the timeout elapses with no answer.
2. Run it and see SUSPENDED#
1 | |
Output:
1 2 3 4 | |
The runtime ran the @flexible block, hit the @checkpoint, serialized the flow's scope (including candidate), and stopped. The checkpoint id is what the host needs to resume with.
3. Resume from the host#
The CLI is invocation-only; resume happens through the host you're embedding the runtime in. The shape:
1 2 3 4 5 6 | |
The resolution dict is matched against the checkpoint block's on_response arms (or, with no arms, bound directly to the checkpoint's decision variable). The flow continues from the block immediately after the @checkpoint. The @rigid block's @match runs, the right branch returns, and result.status is COMPLETED.
4. Route to a queue (v1.0.0+)#
If your host has a queue system like ScaiQueue, @checkpoint hitl_review plus a hitl_target ships the decision directly to that queue, instead of through the generic checkpoint handler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
The runtime evaluates hitl_target and passes it to the host's checkpoint handler. The host is expected to publish a hitl_request to the addressed (scope, queue) carrying hitl_spec, subscribe to its completion event, and invoke engine.resume when the message resolves. See the changelog for the full v1.0.0 wire-up.
What you gained#
A flow that doesn't auto-complete on the model's output. The runtime persists everything before the pause; whatever in-flight LLM context, memory, or partial work the flow had is restored intact on resume. Combined with :entity instance mode, you get a per-entity workflow that can wait days for a human and pick up exactly where it left off.