Skip to content

fix(workflow): preserve messages and errors alongside delegated output - #7950

Open
1828703450qqcom-ux wants to merge 2 commits into
google:mainfrom
1828703450qqcom-ux:fix/workflow-preserve-delegated-messages
Open

1828703450qqcom-ux wants to merge 2 commits into
google:mainfrom
1828703450qqcom-ux:fix/workflow-preserve-delegated-messages

Conversation

@1828703450qqcom-ux

@1828703450qqcom-ux 1828703450qqcom-ux commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Link to Issue or Description of Change

Closes: #7949

Problem: A parent using ctx.run_node(..., use_as_output=True) can yield an event that combines the repeated output with new message content or error details. NodeRunner currently suppresses the entire event. Besides losing text and image messages, this hides and fails to persist a combined function-call/long-running-tool approval request, leaving the workflow waiting for a response the caller cannot discover. Combined output/error events also lose error_code and error_message, so callers and stored sessions cannot discover the failure. This reproduces on main after #7931 landed.

Solution: Treat non-None message content and nonempty error details as non-output content. The existing output-removal path then forwards and persists the rest of the event, while output-only duplicates remain suppressed. No public API or session schema changes.

Testing Plan

Unit Tests:

  • Added real Runner/Workflow regression tests for text and image content, each with and without output delegation. They verify streamed content, persisted content, and output counts.
  • Added a two-invocation approval test: the combined event reaches the caller and session, its duplicate output is absent, downstream waits, and the function response resumes downstream with the approved result.
  • Added error-code-only, error-message-only, and combined error cases, each with and without output delegation. They verify streamed and persisted errors, preserve normal output when not delegating, and suppress the repeated output when delegating.
  • On unmodified main 73ae69e with the same final tests: 3 failed, 2 passed. With this fix: all 5 pass on Python 3.11, 3.12, 3.13, and 3.14.
  • The six additional error cases against the preceding PR head 108e4b1: 3 failed, 3 passed. With the error fix, the combined 11 message, approval, and error cases pass on Python 3.11, 3.12, and 3.14; they also pass within the full Python 3.13 workflow suite.
  • Complete tests/unittests/workflow suite on Python 3.13: 1329 passed, 2 failed, 1 xfailed. The two failures are test_execute_bash_tool_node_runs_command_after_approval[False/True]; both reproduce in a separate unmodified 73ae69e worktree. ExecuteBashTool's POSIX-only implementation is an existing Windows limitation.
  • Pre-commit formatting, imports, Ruff, license, spelling, and whitespace checks passed. Windows cannot launch the repository's three shebang hooks directly; their equivalent Python checks are run separately.
  • Full-source mypy: both the branch and an unmodified 73ae69e worktree report the same 182 existing errors in 40 files, with zero new diagnostics after CI-style line-number normalization. No diagnostics reference the changed source file. Direct check_new_py_files.py, compliance_checks.py, and check_docs.py checks all pass.

Manual End-to-End (E2E) Tests:

Executed a standalone script using a real Runner, Workflow, InMemorySessionService, and custom BaseNode; no LLM, cloud API, or command tool is involved. Its node calls ctx.run_node(prepare, use_as_output=True) to publish draft, then yields a combined output/approval event with function call ID approval. A downstream node records its input and returns published.

Before (unmodified main):

{"approval_visible": false, "approval_persisted": false, "draft_output_count": 1, "published_before_approval": []}

After:

{"approval_visible": true, "approval_persisted": true, "draft_output_count": 1, "published_before_approval": []}
{"published_inputs_after_approval": ["approved draft"], "published_result_visible": true}

To reproduce, the added test_delegated_output_preserves_confirmation_and_resume contains the complete Runner setup. Run:

python -m pytest tests/unittests/workflow/test_workflow.py -k delegated_output_preserves -q

An additional standalone Runner scenario delegates partial result, then yields that repeated output with error_code="UPSTREAM_ERROR" and error_message="The upstream operation failed.". On unmodified 73ae69e it reports error_visible=false, error_persisted=false, and output_count=1. With the complete fix it reports both flags true, retains both exact error strings, still publishes the result once, and removes the error event's repeated output. It uses only real in-memory ADK components and custom nodes, with no model or external API.

Checklist

  • Read the contribution guide and performed a self-review.
  • Added tests proving the fix, including ordinary non-delegating controls.
  • Tested end-to-end through Runner and persisted sessions.
  • No dependency, public API, or documentation changes are needed.
  • All existing unit tests pass locally: the two baseline Windows/POSIX failures are disclosed above.

Additional context

AI assistance was used for investigation, implementation, and test preparation. All reported checks were executed locally. This change preserves messages and error details; it does not redesign suppression of other event metadata.

@1828703450qqcom-ux 1828703450qqcom-ux changed the title fix(workflow): preserve messages alongside delegated output fix(workflow): preserve messages and errors alongside delegated output Nov 3, 2026
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.

Workflow output delegation drops message content and combined approval events

2 participants