Skip to content

feat: suppress SSE events for internal graph nodes#204

Open
skattoju wants to merge 5 commits into
rh-ai-quickstart:mainfrom
skattoju:feat/internal-node-suppression
Open

feat: suppress SSE events for internal graph nodes#204
skattoju wants to merge 5 commits into
rh-ai-quickstart:mainfrom
skattoju:feat/internal-node-suppression

Conversation

@skattoju
Copy link
Copy Markdown
Contributor

@skattoju skattoju commented Mar 3, 2026

Summary

  • Add an internal: true flag for graph node configs. Internal nodes still execute and pass data through graph state to downstream nodes, but their SSE events (node_started, response, node_completed) are suppressed so intermediate data (e.g. raw JSON arrays) never appears in the user's chat.
  • Fix node dependency ordering in the vacation planner graph — add explicit depends_on for destination_research_task, hotel_research_task, and flight_research_task so the pipeline executes in the correct sequence.
  • Mark places_list_task as internal: true in the vacation planner template since it only exists to feed the downstream destination_research_task fan-out.

Test plan

  • Run pytest tests/unit/test_graph_engine.py — all 38 tests pass including the new test_internal_node_suppressed
  • Deploy and run the vacation planner agent — the raw JSON places list should no longer appear in the chat output
  • Verify that destination research still works (the internal node output is consumed by destination_research_task via items_path)

Made with Cursor

skattoju added 5 commits March 3, 2026 15:12
Add explicit depends_on for destination_research, hotel_research, and
flight_research nodes so the pipeline executes sequentially instead of
fan-out racing ahead of its data source.

Made-with: Cursor
Add an `internal` flag to graph node configs. When set to true, the
node still executes and its output flows through graph state to
downstream nodes, but no node_started/response/node_completed SSE
events are emitted to the frontend. This keeps intermediate data
(e.g. the places_list_task JSON array) out of the user-facing chat.

Mark places_list_task as internal in the vacation planner template.

Made-with: Cursor
Internal node outputs were still leaking to users because
_run_llm_node dumps all prior outputs into the prompt as
"Outputs so far". Downstream LLMs (e.g. itinerary_options_task)
would see the raw places JSON and echo it in their response.

Filter internal node IDs out of the outputs dict before passing
it to LLM nodes. MCP tool nodes still receive the full outputs
so items_path resolution continues to work.

Made-with: Cursor
Nodes that exist solely to produce a list for mcp_tool_map fan-out
(referenced via items_path) are now automatically treated as internal
even when the graph_config stored in the database lacks the explicit
internal: true flag. This fixes the case where agents created before
the YAML update still expose intermediate data to users.

Also consolidates the internal flag in task output to use the merged
_internal_ids set (explicit + auto-detected) instead of only checking
the step config.

Made-with: Cursor
Both tasks only depend on itinerary_options_task, not on each other.
Changing flight_research_task to depend on itinerary_options_task
instead of hotel_research_task lets them fan out concurrently.

Made-with: Cursor
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.

1 participant