1717import copy
1818from typing import Any
1919
20+ from google .adk .agents .context import Context
2021from google .adk .agents .llm_agent import LlmAgent
2122from google .adk .apps .app import App
2223from google .adk .apps .app import ResumabilityConfig
2324from google .adk .events .event import Event
25+ from google .adk .events .request_input import RequestInput
2426from google .adk .tools ._node_tool import NodeTool
2527from google .adk .tools .long_running_tool import LongRunningFunctionTool
2628from google .adk .workflow import JoinNode
@@ -57,7 +59,6 @@ def test_node_tool_requires_input_schema():
5759 NodeTool (node = wf )
5860
5961
60- @pytest .mark .skip (reason = 'Requires CL 2 subagent branch refactor' )
6162@pytest .mark .asyncio
6263async def test_workflow_as_tool_hitl_resume (request : pytest .FixtureRequest ):
6364 """Workflow-as-a-tool suspends on RequestInput and resumes successfully.
@@ -176,7 +177,6 @@ def format_response(node_input: dict[str, Any]):
176177 assert 'Thank you! I received the user details.' in text_responses
177178
178179
179- @pytest .mark .skip (reason = 'Requires CL 2 subagent branch refactor' )
180180@pytest .mark .asyncio
181181async def test_workflow_as_tool_hitl_resume_non_resumable_app (
182182 request : pytest .FixtureRequest ,
@@ -517,7 +517,6 @@ async def test_workflow_tool_with_nested_workflows(
517517 ].function_response .response == {'result' : 'inner_output' }
518518
519519
520- @pytest .mark .skip (reason = 'Requires CL 2 subagent branch refactor' )
521520@pytest .mark .asyncio
522521async def test_workflow_tool_with_dynamic_node_hitl_resume (
523522 request : pytest .FixtureRequest ,
@@ -603,21 +602,30 @@ async def parent_node(*, ctx, node_input):
603602 assert 'Task completed.' in text_responses
604603
605604
606- @pytest .mark .skip (
607- reason = 'Known framework issue with MockModel nested HITL in sub-workflow'
608- )
609605@pytest .mark .asyncio
610606async def test_workflow_as_tool_nested_hitl (request : pytest .FixtureRequest ):
611607 """Parent LLM agent -> workflow -> LLM agent -> NodeTool(HITL) propagation."""
608+
612609 # 1. Define the deepest node that raises RequestInput
613- input_node = RequestInputNode (
614- name = 'deep_input_node' ,
615- message = 'Give me some input:' ,
616- response_schema = {
617- 'type' : 'object' ,
618- 'properties' : {'val' : {'type' : 'string' }},
619- },
620- )
610+ @node (name = 'deep_input_node' , rerun_on_resume = True )
611+ def input_node (ctx : Context ):
612+ resume_input = ctx .resume_inputs .get ('deep_input_id' )
613+ if not resume_input :
614+ yield RequestInput (
615+ interrupt_id = 'deep_input_id' ,
616+ message = 'Give me some input:' ,
617+ response_schema = {
618+ 'type' : 'object' ,
619+ 'properties' : {'val' : {'type' : 'string' }},
620+ },
621+ )
622+ return
623+ user_val = (
624+ resume_input .get ('val' )
625+ if isinstance (resume_input , dict )
626+ else resume_input
627+ )
628+ yield Event (output = f'Processed: { user_val } ' )
621629
622630 # 2. Wrap it as a NodeTool
623631 input_node .input_schema = DummyRequest
@@ -708,22 +716,45 @@ async def test_workflow_as_tool_nested_hitl(request: pytest.FixtureRequest):
708716
709717
710718@pytest .mark .skip (
711- reason = 'Known framework issue with MockModel multi-HITL in nested workflow '
719+ reason = 'Requires Step 2 LRO pause resolution in base_llm_flow.py '
712720)
713721@pytest .mark .asyncio
714722async def test_workflow_as_tool_nested_multi_hitl (
715723 request : pytest .FixtureRequest ,
716724):
717725 """Parent LLM agent -> workflow -> LLM agent -> NodeTool(HITL) twice."""
726+
718727 # 1. Define the deepest node that raises RequestInput
719- input_node = RequestInputNode (
720- name = 'deep_input_node' ,
721- message = 'Give me some input:' ,
722- response_schema = {
723- 'type' : 'object' ,
724- 'properties' : {'val' : {'type' : 'string' }},
725- },
726- )
728+ @node (name = 'deep_input_node' , rerun_on_resume = True )
729+ def input_node (ctx : Context ):
730+ resume_input_1 = ctx .resume_inputs .get ('deep_input_id_1' )
731+ resume_input_2 = ctx .resume_inputs .get ('deep_input_id_2' )
732+ if not resume_input_1 :
733+ yield RequestInput (
734+ interrupt_id = 'deep_input_id_1' ,
735+ message = 'Give me some input:' ,
736+ response_schema = {
737+ 'type' : 'object' ,
738+ 'properties' : {'val' : {'type' : 'string' }},
739+ },
740+ )
741+ return
742+ if not resume_input_2 :
743+ yield RequestInput (
744+ interrupt_id = 'deep_input_id_2' ,
745+ message = 'Give me some input:' ,
746+ response_schema = {
747+ 'type' : 'object' ,
748+ 'properties' : {'val' : {'type' : 'string' }},
749+ },
750+ )
751+ return
752+ user_val = (
753+ resume_input_2 .get ('val' )
754+ if isinstance (resume_input_2 , dict )
755+ else resume_input_2
756+ )
757+ yield Event (output = f'Processed: { user_val } ' )
727758
728759 # 2. Wrap it as a NodeTool
729760 input_node .input_schema = DummyRequest
@@ -734,10 +765,6 @@ async def test_workflow_as_tool_nested_multi_hitl(
734765 name = 'child_agent' ,
735766 model = testing_utils .MockModel .create (
736767 responses = [
737- types .Part .from_function_call (
738- name = 'my_node_tool' ,
739- args = {},
740- ),
741768 types .Part .from_function_call (
742769 name = 'my_node_tool' ,
743770 args = {},
@@ -802,6 +829,7 @@ async def test_workflow_as_tool_nested_multi_hitl(
802829 new_message = testing_utils .UserContent (user_input1 ),
803830 invocation_id = invocation_id ,
804831 )
832+
805833 request_input_event2 = workflow_testing_utils .find_function_call_event (
806834 events2 , REQUEST_INPUT_FUNCTION_CALL_NAME
807835 )
@@ -825,7 +853,6 @@ async def test_workflow_as_tool_nested_multi_hitl(
825853 assert 'Parent agent finished successfully.' in text_responses
826854
827855
828- @pytest .mark .skip (reason = 'Requires CL 2 subagent branch refactor' )
829856@pytest .mark .asyncio
830857async def test_workflow_as_tool_nested_lro (request : pytest .FixtureRequest ):
831858 """Parent LLM agent -> workflow -> LLM agent -> LRO tool."""
0 commit comments