|
27 | 27 | from google.adk.tools.long_running_tool import LongRunningFunctionTool |
28 | 28 | from google.adk.workflow import BaseNode |
29 | 29 | from google.adk.workflow import JoinNode |
| 30 | +from google.adk.workflow import node |
| 31 | +from google.adk.workflow import Workflow |
30 | 32 | from google.adk.workflow._base_node import START |
31 | 33 | from google.adk.workflow._node_status import NodeStatus |
32 | | -from google.adk.workflow._workflow import Workflow |
33 | 34 | from google.adk.workflow.utils._workflow_hitl_utils import create_request_input_response |
34 | 35 | from google.adk.workflow.utils._workflow_hitl_utils import get_request_input_interrupt_ids |
35 | 36 | from google.adk.workflow.utils._workflow_hitl_utils import has_request_input_function_call |
@@ -1122,3 +1123,52 @@ async def _run_impl( |
1122 | 1123 | if e.long_running_tool_ids: |
1123 | 1124 | final_interrupts.update(e.long_running_tool_ids) |
1124 | 1125 | assert not final_interrupts |
| 1126 | + |
| 1127 | + |
| 1128 | +@pytest.mark.asyncio |
| 1129 | +async def test_nested_workflow_with_task_agent(request: pytest.FixtureRequest): |
| 1130 | + """Tests that a task-mode LlmAgent inside a nested Workflow re-runs on user reply.""" |
| 1131 | + mock_model = testing_utils.MockModel.create( |
| 1132 | + responses=[ |
| 1133 | + types.Part.from_text(text='Please provide the secret code:'), |
| 1134 | + types.Part.from_function_call( |
| 1135 | + name='finish_task', |
| 1136 | + args={'result': 'Success with secret'}, |
| 1137 | + ), |
| 1138 | + ] |
| 1139 | + ) |
| 1140 | + task_agent = LlmAgent( |
| 1141 | + name='inner_task_agent', |
| 1142 | + model=mock_model, |
| 1143 | + mode='task', |
| 1144 | + ) |
| 1145 | + inner_wf = Workflow( |
| 1146 | + name='inner_wf', |
| 1147 | + edges=[('START', task_agent)], |
| 1148 | + ) |
| 1149 | + |
| 1150 | + @node(rerun_on_resume=True) |
| 1151 | + async def outer_driver(ctx: Context, node_input: Any): |
| 1152 | + res = await ctx.run_node(inner_wf, node_input='start', raise_on_wait=True) |
| 1153 | + yield Event(output=f'outer: {res}') |
| 1154 | + |
| 1155 | + outer_wf = Workflow( |
| 1156 | + name='outer_wf', |
| 1157 | + edges=[('START', outer_driver)], |
| 1158 | + ) |
| 1159 | + |
| 1160 | + app = App(name=request.function.__name__, root_agent=outer_wf) |
| 1161 | + runner = testing_utils.InMemoryRunner(app=app) |
| 1162 | + |
| 1163 | + events1 = await runner.run_async('hello') |
| 1164 | + texts1 = [ |
| 1165 | + p.text |
| 1166 | + for e in events1 |
| 1167 | + if e.content and e.content.parts |
| 1168 | + for p in e.content.parts |
| 1169 | + if p.text |
| 1170 | + ] |
| 1171 | + assert 'Please provide the secret code:' in texts1 |
| 1172 | + |
| 1173 | + events2 = await runner.run_async('secret_code_123') |
| 1174 | + assert any('outer: ' in str(e.output) for e in events2) |
0 commit comments