Summary
InputMessageNode is a useful HITL gate for collecting user input mid-flow, but it has no node-level guard or pre-execution condition. To skip the prompt when required values are already present in flow state, the only available pattern is a BranchingNode with a 3-step predicate chain: PluginRegexNode (in list mode for empty-detection) → PluginTemplateNode (collapsing to "present" / "missing") → BranchingNode (mapping {"present": "skip"} to a label that bypasses the InputMessageNode).
This works, but is verbose: every skippable HITL gate requires four extra nodes plus the wiring edges. For flows with multiple optional HITL gates this multiplies into noise that obscures the actual control flow.
Reproduction (current pattern, abbreviated)
{
"child_agent_a-uuid_match": { "component_type": "PluginRegexNode", "regex_pattern": "^[0-9a-fA-F]{8}-…$", "return_first_match_only": false },
"child_agent_a-predicate": { "component_type": "PluginTemplateNode", "template": "{{ value | length }}" },
"child_agent_a-check_inputs": { "component_type": "BranchingNode", "branch_name_mapping": { "present": "skip" } },
"child_agent_a-data_gate": { "component_type": "InputMessageNode", "...": "..." },
"child_agent_a-generate": { "component_type": "ApiNode", "...": "..." }
}
…plus six edges to wire the four-node predicate chain into the existing data_gate → generate flow.
Feature request
Add an optional guard (or skip_when) field on InputMessageNode that accepts a JSON-pointer / Jinja predicate against flow state. When the predicate evaluates to true, the runtime skips the node without raising, and downstream DataFlowEdges resolve from existing flow state.
{
"child_agent_a-data_gate": {
"component_type": "InputMessageNode",
"guard": {
"kind": "all_present",
"inputs": ["dataRefA", "dataRefB"]
}
}
}
This collapses 4 nodes + 6 edges into 1 node + 0 extra edges per skippable gate, dramatically improving flow readability.
Suggested implementation
InputMessageNode.execute() checks self.guard first; if the predicate is truthy against the conversation's input state, the executor returns immediately with no UserMessageRequestStatus — proceeding to whichever node the existing control flow edges target next.
The predicate language can start minimal: { "kind": "all_present", "inputs": [name, ...] } and { "kind": "any_present", "inputs": [name, ...] }. Jinja support can come later.
Related
Distinct from #145 (input-required propagation across A2A boundary) — that concerns runtime state communication. This issue concerns declaring an inline guard predicate so the runtime can skip the prompt entirely without a separate BranchingNode chain.
Environment
wayflowcore[a2a]==26.1.1
- Python 3.11
Summary
InputMessageNodeis a useful HITL gate for collecting user input mid-flow, but it has no node-level guard or pre-execution condition. To skip the prompt when required values are already present in flow state, the only available pattern is aBranchingNodewith a 3-step predicate chain:PluginRegexNode(in list mode for empty-detection) →PluginTemplateNode(collapsing to "present" / "missing") →BranchingNode(mapping{"present": "skip"}to a label that bypasses theInputMessageNode).This works, but is verbose: every skippable HITL gate requires four extra nodes plus the wiring edges. For flows with multiple optional HITL gates this multiplies into noise that obscures the actual control flow.
Reproduction (current pattern, abbreviated)
{ "child_agent_a-uuid_match": { "component_type": "PluginRegexNode", "regex_pattern": "^[0-9a-fA-F]{8}-…$", "return_first_match_only": false }, "child_agent_a-predicate": { "component_type": "PluginTemplateNode", "template": "{{ value | length }}" }, "child_agent_a-check_inputs": { "component_type": "BranchingNode", "branch_name_mapping": { "present": "skip" } }, "child_agent_a-data_gate": { "component_type": "InputMessageNode", "...": "..." }, "child_agent_a-generate": { "component_type": "ApiNode", "...": "..." } }…plus six edges to wire the four-node predicate chain into the existing
data_gate → generateflow.Feature request
Add an optional
guard(orskip_when) field onInputMessageNodethat accepts a JSON-pointer / Jinja predicate against flow state. When the predicate evaluates totrue, the runtime skips the node without raising, and downstreamDataFlowEdges resolve from existing flow state.{ "child_agent_a-data_gate": { "component_type": "InputMessageNode", "guard": { "kind": "all_present", "inputs": ["dataRefA", "dataRefB"] } } }This collapses 4 nodes + 6 edges into 1 node + 0 extra edges per skippable gate, dramatically improving flow readability.
Suggested implementation
InputMessageNode.execute()checksself.guardfirst; if the predicate is truthy against the conversation's input state, the executor returns immediately with noUserMessageRequestStatus— proceeding to whichever node the existing control flow edges target next.The predicate language can start minimal:
{ "kind": "all_present", "inputs": [name, ...] }and{ "kind": "any_present", "inputs": [name, ...] }. Jinja support can come later.Related
Distinct from #145 (
input-requiredpropagation across A2A boundary) — that concerns runtime state communication. This issue concerns declaring an inline guard predicate so the runtime can skip the prompt entirely without a separateBranchingNodechain.Environment
wayflowcore[a2a]==26.1.1