Skip to content

fix(runners): honor before_run_callback early-exit on the node execution path - #6829

Closed
Dratatus wants to merge 1 commit into
google:mainfrom
Dratatus:fix/honor-before-run-early-exit-node-path
Closed

fix(runners): honor before_run_callback early-exit on the node execution path#6829
Dratatus wants to merge 1 commit into
google:mainfrom
Dratatus:fix/honor-before-run-early-exit-node-path

Conversation

@Dratatus

@Dratatus Dratatus commented Aug 20, 2026

Copy link
Copy Markdown

Fixes #6828 (reopen of #6013, which was closed by the stale bot without a fix).

Supersedes #6032, which no longer merges cleanly and has had no author activity since 2026-07-03. The core change is adapted from that PR with credit to @garyzava; this PR rebases it onto current main and extends coverage.

Problem

_run_node_async calls plugin_manager.run_before_run_callback(...) and discards the return value. A plugin returning types.Content (the documented signal to halt the run) is silently ignored and execution continues. The legacy path (_exec_with_plugin) honors the contract. Affected shapes: root Workflow and root LlmAgent — i.e. plugin-based guardrails are bypassed for the most common application shape.

Fix

Mirror the _exec_with_plugin early-exit contract on the node path: the returned Content becomes the final response event (author model, with RunConfig.custom_metadata applied), is appended to the session, and the run returns. after_run callbacks and post-invocation compaction are run explicitly before returning (the finally that normally runs them belongs to the main loop, which a halted run never enters), matching both the success path and the legacy early-exit behavior — the regression tests assert after_run fires on a halted run.

Testing Plan

Two regression tests in tests/unittests/workflow/test_workflow_failures.py:

  • test_workflow_halts_when_before_run_callback_returns_content — root Workflow: the node never executes, the plugin content is the final event.
  • test_llm_agent_root_halts_when_before_run_callback_returns_content — root LlmAgent with a mock model: the model is never called (mock_model.requests stays empty), the plugin content is the final event.

Both tests fail without the fix (verified) and pass with it. Full local runs: tests/unittests/test_runners.py + tests/unittests/workflow/ → 738 passed, 11 skipped, 10 xfailed. No API surface changes; a plugin returning None behaves exactly as before.

@google-cla

google-cla Bot commented Aug 20, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

…ion path

The node execution path (_run_node_async) invoked
plugin_manager.run_before_run_callback but discarded its return value,
so a plugin returning types.Content (the documented signal to halt the
run) was ignored and execution continued. The legacy path
(_exec_with_plugin) already honors this contract.

This affects every root that dispatches through the node path: a
Workflow root and a root LlmAgent (chat/task mode), which means
plugin-based guardrails (e.g. safety filters that block a turn in
before_run_callback) are silently bypassed for those shapes.

Fix mirrors the _exec_with_plugin early-exit contract: the returned
Content becomes the final response event (with RunConfig
custom_metadata applied), is appended to the session, and the run ends.
after_run callbacks and post-invocation compaction are run explicitly (the
finally that normally runs them belongs to the main loop, which a halted run never enters), matching the success path and the legacy early-exit behavior.

Adapted from the stale PR google#6032 by @garyzava (rebased onto current main
and extended with a root-LlmAgent regression test).

Fixes google#6828
@Dratatus
Dratatus force-pushed the fix/honor-before-run-early-exit-node-path branch from 3173ae7 to 847b851 Compare August 20, 2026 11:46
@Dratatus Dratatus closed this Aug 20, 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.

before_run_callback early-exit is silently ignored on the node execution path (root LlmAgent and Workflow) — reopen of #6013

2 participants