Skip to content

fix(uipath-maestro-flow): a HITL form collects input; it does not display output - #3093

Merged
rockymadden merged 3 commits into
mainfrom
fix/flow-hitl-not-for-display
Sep 4, 2026
Merged

fix(uipath-maestro-flow): a HITL form collects input; it does not display output#3093
rockymadden merged 3 commits into
mainfrom
fix/flow-hitl-not-for-display

Conversation

@rockymadden

Copy link
Copy Markdown
Collaborator

Stacked on #3091#3090#3088. Retarget as each lands.

Problem

skill-flow-cli-dice-roller-simulated asked for a die roll "displayed somewhere the user can actually see it, not buried in a log". The agent built script → uipath.human-in-the-loop.quick-form → End, wired correctly, and the run never finished:

Status: Running (2/3 elements completed)
  v start        [Completed]
  v rollDice     [Completed]
  > displayRoll1 [InProgress]
Still polling... status: Running (282s elapsed)

The checker gave up at its 600s cap with the instance still Running. The Action Center task sat unassigned — nobody was ever going to submit it.

The agent then read the roll out of the task by hand and reported "It rolled 4". True, and not the flow working.

Why the skill let it happen

planning.md's "When to Select" table had no row for this case. Every No row was about a human not being involved:

Situation Select?
Fully automated processing, no human involvement No

Here a human plainly was involved — they asked to see the number. Nothing said the form is the wrong instrument for showing them something.

Fix

New row and the rule behind it:

A form collects input from a human. It does not display output to one. "Show me the result", "display the number", "surface it where I can see it" is an out variable mapped on the End node, which is what the run returns — not a form to look at.

Plus why the symptom misleads: the outcome-completed port can be wired correctly and the flow still never reaches End, so it looks nothing like the existing unwired-port failure mode already documented two rows above.

impl.md's Debug table gains the matching symptom: run never finishes, instance stays Running to the timeout, ports all wired.

Covers the second half too

That flow also declared globals: [] with no outputs on its End node. Even with the form removed, the roll would not have surfaced. The new text answers that directly — the out variable is the display mechanism.

Verification

  • All maintenance checkers clean apart from the anchor pre-existing on main; the new planning.md#when-to-select cross-reference resolves.
  • Both flavors compose.
  • Docs only. No task file changed — the task's ask is reasonable and the agent's reading of it was not.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Claude finished @rockymadden's task in 1m 58s —— View job


PR Review: fix(uipath-maestro-flow): HITL form collects input, not display output

  • Read review criteria and project conventions
  • Read the full diff
  • Read changed files in full context
  • Check relative links resolve
  • Check for cross-skill references and secrets
  • Post review

Summary

Adds a "When to Select → No" row to planning.md for the case where a user wants to see output (not provide input), with an explanatory paragraph. Adds the matching debug symptom to impl.md's error table. Both additions are well-motivated by the failure mode described in the PR body.

Change-by-Change Review

1. skills/uipath-maestro-flow/references/author/plugins/hitl/planning.md — +5/−0

Severity: OK

New table row at line 33 and two explanatory paragraphs (lines 35–37) are clear, prescriptive, and well-scoped. The rule ("a form collects input; it does not display output") is the right abstraction — it covers the concrete dice-roller failure and generalizes to any "show me X" prompt. The explanation of why the symptom is misleading (ports wired correctly, but flow never reaches End) is valuable because it distinguishes this from the existing unwired-port row.

No issues found.

2. skills/uipath-maestro-flow/references/author/plugins/hitl/impl.md — +2/−1

Severity: Low (pre-existing)

New debug table row at line 178 matches the planning guidance and cross-links with [planning.md](planning.md#when-to-select). The anchor resolves to the correct heading (line 23 of planning.md).

The file still lacks a trailing newline — this is pre-existing from the base branch (the -1 in the diff is just the no-newline marker moving down), so not introduced by this PR.

What's Missing

Nothing identified.

Area Ratings

Area Status Notes
Frontmatter OK No frontmatter changes
E2E Tests OK Docs-only change; PR description explains why no task change is needed
Skill Body OK No SKILL.md changes
References & Assets OK Both changed files are correct, links resolve
Repo Hygiene OK No secrets, no cross-skill deps, changes scoped to one skill

Issues for Manual Review

None found.

Conclusion

Clean docs-only fix. The new planning row and debug symptom close a real gap — the skill had no guidance for the "display output via form" anti-pattern, leading an agent to build a flow that hangs forever. The writing is concise and correctly distinguishes this from the existing unwired-port failure mode. Approve.


@rockymadden

Copy link
Copy Markdown
Collaborator Author

Reframed — the first version optimised for the checker

Pushback on review, correctly. The original rule said:

A form collects input from a human. It does not display output to one. ... is an out variable mapped on the End node

Both halves are wrong.

A quick-form renders fields to a person, so it does display. That was a claim about the node that is not true.

An out variable is the run's return value. For a user who asked to see the result "not buried in a log", that is a log by another name. The guidance would have made this eval pass while giving a real user precisely the thing they said they did not want.

The actual constraint

Not what a form can show — that a HITL node blocks until a human completes its task, so it belongs only where a human will. An unassigned task, or any unattended run, leaves the instance Running to the caller's timeout with no output.

"Show me the result" is now a choice between three mechanisms, compared on the two axes that decide it:

Mechanism Reaches Completes unattended
HITL form a person who opens Action Center No — blocks until submitted
Message to a channel or mailbox a person wherever they already are Yes
out variable on the End node whoever or whatever invoked the flow Yes

Ask which is meant. With nobody to ask, take one that terminates and record the choice. And: "do not reach for a form because the request said display — that word describes the goal, not the node."

Note the middle row. For the dice task a Slack or email node is arguably the best answer and the first version ruled it out by implication, which is how you can tell the rule was written backwards from the assertion.

Why this matters beyond one task

The dice-roller failure was the agent producing a confident wrong build. My first fix was me doing the same thing one layer up: writing a rule that satisfies the grader and misleads the user. Worth flagging since this PR series exists to stop exactly that.

Base automatically changed from fix/flow-stray-scaffold-check to main September 4, 2026 18:44
rockymadden and others added 3 commits September 4, 2026 12:45
…play output

skill-flow-cli-dice-roller-simulated asked for a die roll "displayed
somewhere the user can actually see it, not buried in a log". The agent
built script -> uipath.human-in-the-loop.quick-form -> End, wired
correctly, and the run never finished:

  Status: Running (2/3 elements completed)
    v start [Completed]
    v rollDice [Completed]
    > displayRoll1 [InProgress]
  Still polling... status: Running (282s elapsed)

The checker gave up at its 600s cap with the instance still Running. The
Action Center task sat unassigned — nobody was ever going to submit it.
The agent then read the roll out of the task by hand and reported "It
rolled 4", which is true and is not the flow working.

planning.md's "When to Select" table had no row for this. Every No row
was about a human not being involved, and here a human plainly was — they
asked to see the number. Nothing said the form is the wrong instrument
for showing them.

Added the row plus the rule: "show me the result" is an `out` variable
mapped on the End node, which is what the run returns. Also named why the
symptom misleads — the port can be wired correctly and the flow still
never reaches End, so it does not look like the existing unwired-port
failure mode.

impl.md's Debug table gains the matching symptom: run never finishes,
instance stays Running to the timeout, ports all wired.

This also covers the second half of that failure. The flow declared
`globals: []` and its End node had no outputs, so even with the form
removed the roll would not have surfaced.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… not display

The first version said "a form collects input from a human, it does not
display output to one", and told the agent to return an `out` variable
instead. Both halves are wrong.

A quick-form renders fields to a person, so it does display. And an `out`
variable is the run's return value — for a user who asked to see the
result "not buried in a log", that is a log by another name. That
guidance would have passed the eval and given a real user the thing they
said they did not want.

The actual constraint is not what a form can show. It is that a HITL node
blocks until a human completes its task, so it belongs only where a human
will: an unassigned task, or any unattended run, leaves the instance
Running to the caller's timeout with no output.

"Show me the result" is now a choice between three mechanisms, compared on
who they reach and whether they complete unattended: a form, a message to
a channel or mailbox, or an `out` variable. Ask which is meant. With
nobody to ask, take one that terminates and record the choice.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
SKILL.md loads in full on every invocation, so a byte there costs more
than a byte in a reference doc. Rule #2 had grown 136 -> 1006 bytes.

Cut what did not change behaviour: three illustrative phrasings of the
same mandate where one carries it, a parenthetical list of three
non-mandate requests where naming them plainly is shorter, and a pointer
to inline-voice-agent/impl.md that duplicated the sentence above it —
that doc keeps its own gate and this rule already says third-party
effects need an explicit ask.

Rule #2 is 773 bytes; SKILL.md is +719 over main, from +949.

Also trimmed greenfield's stray-scaffold check by 233 bytes: a
three-clause list of tools that fail to warn you where one clause does,
and a cross-reference restating rule #6.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@rockymadden
rockymadden force-pushed the fix/flow-hitl-not-for-display branch from 8bdd917 to 8fc910a Compare September 4, 2026 18:46
@rockymadden
rockymadden merged commit b7e33d8 into main Sep 4, 2026
19 checks passed
@rockymadden
rockymadden deleted the fix/flow-hitl-not-for-display branch September 4, 2026 18:54
tmatup added a commit that referenced this pull request Sep 4, 2026
Clean sync, no conflicts. Brings in main #3093 (HITL form collects input,
does not display output): skill-doc edits in SKILL.md, greenfield.md and the
hitl plugin references; no task or checker files touched.

Verified: uipath-maestro-flow 1159 passed, uipath-maestro-case 124 passed /
14 skipped, tests/scripts 109 passed / 26 skipped, uipath-maestro-bpmn 12
passed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JSsrfZwCh4tJeqpzjMeixP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants