Deprecate StateGraph approval gate (ApprovalGateNode and ApprovalGate API) in favor of flowdrop_interrupt HITL nodes
Problem/Motivation
flowdrop_stategraph ships its own human-approval pause mechanism (approval_gate node
plugin plus the ApprovalGate namespace), which predates the generalized human-in-the-loop
system in flowdrop_interrupt. The two are parallel implementations of the same concept,
and the StateGraph one is non-functional in practice:
- ApprovalGateHandler stores approval requests in memory only — requests do not survive
the PHP request, so a pending approval can never be resolved later. The class docblock
itself notes a dedicated entity/table would be needed for production.
- No resolution path exists: no controller, API route, or UI calls approve() / reject().
Only tests exercise them.
- The timeout_seconds parameter is declared in the schema but auto-rejection is not
implemented.
- No subscribers exist for ApprovalGateRequested/Approved/RejectedEvent.
- Its one distinguishing feature — capturing a Checkpoint in ApprovalRequiredException —
is redundant: StateGraphOrchestrator already checkpoints via the checkpointer and restores
from the thread's latest checkpoint on resume.
Meanwhile flowdrop_interrupt provides the same capability properly: persistent interrupt
entities, a ResumableNodeProcessorInterface resume contract, REST endpoints, permissions,
playground integration, and gateway branching. The StateGraph orchestrator already handles
InterruptExceptionInterface generically, so ConfirmationNode / FormInputNode pause and
resume correctly under StateGraph today.
Keeping two pause/resume stacks doubles maintenance and confuses workflow authors about
which node to use.
Proposed resolution
Deprecate the entire StateGraph approval gate surface in 1.x, remove in 2.0.0:
Class: ApprovalGateNode (plugin approval_gate)
Current marker: @internal
Action: Deprecate; delegate execution to the interrupt system
────────────────────────────────────────
Class: ApprovalGateHandler + service flowdrop_stategraph.approval_gate_handler
Current marker: @internal
Action: Deprecate
────────────────────────────────────────
Class: ApprovalRequiredException
Current marker: @internal
Action: Deprecate; orchestrator handling collapses to the generic
InterruptExceptionInterface path
────────────────────────────────────────
Class: ApprovalGateRequestedEvent, ApprovalGateApprovedEvent, ApprovalGateRejectedEvent
Current marker: @internal
Action: Deprecate
────────────────────────────────────────
Class: ApprovalGateInterface
Current marker: @api
Action: Formal deprecation cycle (@deprecated + trigger_error(E_USER_DEPRECATED)),
pointing
implementers to flowdrop_interrupt
────────────────────────────────────────
Class: ApprovalStatus
Current marker: @api
Action: Same formal deprecation cycle
To honor workflow-author intent, existing workflows containing an approval_gate node must
keep working through 1.x: the deprecated plugin will throw InterruptRequiredException with
a confirmation-type HitlInterruptMessage instead of ApprovalRequiredException. This is
arguably a bugfix — it makes the node resolvable for the first time (via the interrupt
REST API and playground UI).
Recommended replacements for workflow authors:
arguably a bugfix — it makes the node resolvable for the first time (via the interrupt
REST API and playground UI).
Recommended replacements for workflow authors:
- Simple approve/reject → confirmation node (flowdrop_interrupt)
- Approval with notes/structured input → form_input node (flowdrop_interrupt)
Remaining tasks
1. Add @deprecated annotations and deprecation triggers to all classes above.
2. Re-route ApprovalGateNode::process() through InterruptRequiredException.
3. Collapse the ApprovalRequiredException-specific metadata handling (checkpoint_id /
thread_id) in StateGraphOrchestrator to the generic interrupt path.
4. Update tests (ApprovalGateNodeTest, StateGraphApprovalGateTest, ApprovalStatusTest) to
expect deprecations / new behavior.
5. Document the deprecation and migration path in UPGRADE.md and the flowdrop_interrupt
README.
6. Follow-up issue for 2.x: remove the deprecated code.
API changes
- ApprovalGateInterface and ApprovalStatus (both @api) are deprecated in 1.x and will be
removed in 2.0.0. Replacement: the flowdrop_interrupt interrupt system
(InterruptManagerInterface / interrupt entities).
- All @internal ApprovalGate classes are deprecated and will be removed in 2.0.0 without
further BC obligation.
- The approval_gate node plugin keeps working through 1.x (now actually resolvable via the
interrupt API) and is removed in 2.0.0.
Data model changes
None. No stored data exists for approval gates (storage was in-memory only).
issue