Skip to content

Commit 9787e97

Browse files
GWealecopybara-github
authored andcommitted
test: cover after_run_callback dispatch on Workflow node root
The Runner already dispatches run_after_run_callback on the BaseNode (_run_node_async) path; add an end-to-end regression test that a plugin's after_run_callback fires once on a Workflow root. Close #5282 Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 943530150
1 parent 53a8ab1 commit 9787e97

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

tests/unittests/runners/test_runner_node.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@
2626

2727
from google.adk.agents.callback_context import CallbackContext
2828
from google.adk.agents.context import Context
29+
from google.adk.agents.invocation_context import InvocationContext
2930
from google.adk.agents.llm_agent import LlmAgent
3031
from google.adk.agents.run_config import RunConfig
32+
from google.adk.apps.app import App
3133
from google.adk.events.event import Event
34+
from google.adk.plugins.base_plugin import BasePlugin
3235
from google.adk.runners import Runner
3336
from google.adk.sessions.in_memory_session_service import InMemorySessionService
3437
from google.adk.workflow import node
@@ -1393,3 +1396,43 @@ async def _run_impl(
13931396
assert call_counts['child'] == 2
13941397
outputs2 = [e.output for e in events2 if e.output is not None]
13951398
assert 'child_out_2' in outputs2
1399+
1400+
1401+
# ---------------------------------------------------------------------------
1402+
# Plugin lifecycle on the node path
1403+
# ---------------------------------------------------------------------------
1404+
1405+
1406+
class _AfterRunCountingPlugin(BasePlugin):
1407+
"""Counts how many times after_run_callback is dispatched."""
1408+
1409+
def __init__(self) -> None:
1410+
super().__init__(name='after_run_counter')
1411+
self.after_run_calls = 0
1412+
1413+
async def after_run_callback(
1414+
self, *, invocation_context: InvocationContext
1415+
) -> None:
1416+
self.after_run_calls += 1
1417+
1418+
1419+
@pytest.mark.asyncio
1420+
async def test_after_run_callback_dispatched_on_workflow_root():
1421+
"""Runner dispatches plugin after_run_callback on a Workflow(BaseNode) root."""
1422+
1423+
def terminal(node_input: str) -> str:
1424+
return node_input.upper()
1425+
1426+
plugin = _AfterRunCountingPlugin()
1427+
workflow = Workflow(name='wf', edges=[(START, terminal)])
1428+
app = App(name='test', root_agent=workflow, plugins=[plugin])
1429+
ss = InMemorySessionService()
1430+
runner = Runner(app=app, session_service=ss)
1431+
session = await ss.create_session(app_name='test', user_id='u')
1432+
1433+
async for _ in runner.run_async(
1434+
user_id='u', session_id=session.id, new_message=_user_message('hi')
1435+
):
1436+
pass
1437+
1438+
assert plugin.after_run_calls == 1

0 commit comments

Comments
 (0)