Skip to content

Feature Request: Declarative guard/skip predicate on InputMessageNode to bypass user prompt #147

@groganz

Description

@groganz

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions