feat: add HITL pause primitives to workflow engine#829
Open
wolo-lab wants to merge 1 commit into
Open
Conversation
652b345 to
6b8ac3d
Compare
6b8ac3d to
c499ec0
Compare
Adds the engine-side scaffolding for human-in-the-loop pauses: a workflow node can now emit a session.RequestInput, and the scheduler will park the node in NodeWaiting and stop scheduling its successors instead of finalising the run. This is the pause half of HITL only; the resume half (Workflow.Resume, the agent.Agent wrapper, schema validation, handoff vs. re-entry modes) is left for follow-up PRs. Type names and field names are aligned with adk-python's RequestInput in src/google/adk/events/request_input.py: interrupt_id / message / response_schema / payload. API additions: * session.RequestInput carries the prompt: InterruptID (stable correlation key), Message (UI text), ResponseSchema (reserved for the future validator), Payload (opaque UI context). * session.Event.RequestedInput field, parallel to Routes; populated by the node, consumed by the scheduler and forwarded to the UI surface unchanged. * workflow.NewRequestInputEvent(ctx, req) constructor, including UUID auto-generation when InterruptID is empty. * workflow.NodeState.PendingRequest, persisted on the per-node state when the waiting branch fires. * workflow.ErrMultipleInputRequests sentinel for the single-request-per-activation invariant. Scheduler changes: * nodeRun gains an inputRequest field with a setInputRequest method that mirrors the existing setRoutingEvent / setOutput pattern. * handleEvent dispatches on ev.RequestedInput exactly parallel to the existing dispatch on ev.Routes. * handleCompletion gains a waiting branch checked AFTER the error/cancel branches: a clean activation that recorded a request transitions to NodeWaiting, persists the request on NodeState, and skips successor scheduling. Failures take precedence so a node that recorded a request and then errored out lands in NodeFailed, not NodeWaiting. * The scheduler.run loop is unchanged: it terminates when the runsByName map empties, which now happens when every live node has either completed or moved into NodeWaiting. Tests: * TestScheduler_HitlNode_PausesAndForwardsRequest pins the happy-path single-waiting-node behaviour. * TestScheduler_HitlNode_AutoGeneratesInterruptID and TestScheduler_HitlNode_PreservesExplicitInterruptID lock in the InterruptID contract. * TestScheduler_HitlNode_MultipleRequestsFails surfaces ErrMultipleInputRequests at completion. * TestScheduler_HitlNode_ErrorAfterRequestFails pins the fail-over-park precedence in handleCompletion. * TestScheduler_HitlNode_ConcurrentBranches_PausesOnlyWhenAllNonRunning exercises a parallel-branch graph: the non-HITL branch finishes normally while the HITL branch parks; the workflow ends only when both reach a terminal state. All existing workflow tests still pass; the suite is race-free under go test -race.
c499ec0 to
a1543d7
Compare
hanorik
approved these changes
May 14, 2026
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the engine-side scaffolding for human-in-the-loop pauses. A node can now
emit a
session.RequestInputevent; the scheduler parks the node inNodeWaiting, persists the request onNodeState.PendingRequest, and stopsscheduling its successors instead of finalising the run. Pause-only; resume
(
Workflow.Resume, schema validation, handoff/re-entry modes) lands infollow-up PRs.
API additions:
session.RequestInput,session.Event.RequestedInput,workflow.NewRequestInputEvent,workflow.NodeState.PendingRequest,workflow.ErrMultipleInputRequests(one request per activation).Mirrors the existing
Routes/setRoutingEventdispatch pattern in thescheduler. The waiting branch in
handleCompletionruns after error/cancel,so a node that requested input and then errored lands in
NodeFailed, notNodeWaiting.