Fix(agentflow) - Add iteration node full functionality#6324
Conversation
…eAI/Flowise into fix/agentflow-node-output
…s code, rich text, and source
There was a problem hiding this comment.
Code Review
This pull request enhances the iteration node functionality by implementing real-time result streaming, recursive deletion of child nodes and their associated edges, and improved variable scoping with the introduction of the $iteration variable. Additionally, it improves the canvas UI by enabling double-click access to the node editor and adjusting the z-index for edges within iteration groups. Feedback was provided to ensure that empty iteration results are correctly captured for observability and to optimize the performance of the recursive deletion logic by using a parent-to-children map to avoid
| const collectDescendants = (parentId: string) => { | ||
| state.nodes | ||
| .filter((n) => n.parentNode === parentId) | ||
| .forEach((child) => { | ||
| toDelete.add(child.id) | ||
| collectDescendants(child.id) | ||
| }) | ||
| } |
There was a problem hiding this comment.
The collectDescendants function performs a full scan of state.nodes at each level of recursion, resulting in
| const collectDescendants = (parentId: string) => { | |
| state.nodes | |
| .filter((n) => n.parentNode === parentId) | |
| .forEach((child) => { | |
| toDelete.add(child.id) | |
| collectDescendants(child.id) | |
| }) | |
| } | |
| const nodesByParent = new Map<string, string[]>() | |
| state.nodes.forEach((n) => { | |
| if (n.parentNode) { | |
| const children = nodesByParent.get(n.parentNode) || [] | |
| children.push(n.id) | |
| nodesByParent.set(n.parentNode, children) | |
| } | |
| }) | |
| const collectDescendants = (parentId: string) => { | |
| nodesByParent.get(parentId)?.forEach((childId) => { | |
| toDelete.add(childId) | |
| collectDescendants(childId) | |
| }) | |
| } |
There was a problem hiding this comment.
Since the topology can only be 1 level deep (iteration inside iteration is not supported) the optimization does not add much value
| iterationResults, | ||
| content: iterationResults.join('\n') | ||
| iterationResults, // full record (errors included) for observability | ||
| content: successfulIterationResults.join('\n') // successful only — matches what was streamed and saved to chat history |
There was a problem hiding this comment.
Thanks for fixing the streaming issue. The changes would affect existing-flow in the chat-visibility (errors no longer visible to user in chat) and worth reviewing:
- Mixed success/failure run: errors silently dropped from chat content
- All-failed run: chat content goes from "list of error strings" to empty string. If the iteration is the last node and every item errors, the user previously saw error text in the chat; now they see nothing.
Could we keep content = iterationResults.join('\n') (errors included, as before) and stream the same items pushed to iterationResults? That way the streaming addition is purely additive and doesn't change what the chat ultimately shows.
There was a problem hiding this comment.
So for every other node, the errors are not displayed in the chat content and it is only stored in the execution log and now with this change, iteration node also follows the same behavior as every other node in v2.
There was a problem hiding this comment.
Looking at the code path more carefully, the content change isn't actually streaming-only — content flows into result.text which becomes the HTTP response body for non-streaming callers (controllers/predictions/index.ts:94-95) and the persisted chat history row. So a caller hitting POST /api/v1/prediction/:id without streaming: true would see a different response body for the same iteration flow before vs after this PR.
Could we keep content = iterationResults.join('\n') (errors included, matching pre-PR behavior) and just add streaming on top from the same source? That fixes the streaming gap without altering the non-streaming API contract.
There was a problem hiding this comment.
Yes this makes sense to avoid changing results as it is affecting the API responses.
There was a problem hiding this comment.
Moving this code change into a separate PR - #6328
…wiseAI/Flowise into fix-agentflow-iteration-node
Fixed the following:
Before:
Edges.conecting.error.mov
After:

Node.Execution.status.mov
Delete.Iteration.Node.mov
Before:
Edit.button.before.mov
After:
Edit.button.After.mov