@@ -580,6 +580,103 @@ async def test_unsetting_timeout():
580580 assert model ._activity_config .get ("start_to_close_timeout" , None ) is None
581581
582582
583+ class SummaryFnModel (TestModel ):
584+ """Returns a single text response for summary_fn testing."""
585+
586+ def responses (self ) -> list [LlmResponse ]:
587+ return [
588+ LlmResponse (content = Content (role = "model" , parts = [Part (text = "response" )])),
589+ ]
590+
591+ @classmethod
592+ def supported_models (cls ) -> list [str ]:
593+ return ["summary_fn_model" ]
594+
595+
596+ @workflow .defn
597+ class SummaryTestWorkflow :
598+ @workflow .run
599+ async def run (self , model_name : str ) -> None :
600+ modes = [
601+ ("dynamic" , lambda req : f"Invoking { req .model } " ),
602+ ("none" , lambda req : None ),
603+ ("empty" , lambda req : "" ),
604+ ("label_fallback" , None ),
605+ ]
606+ for mode_name , summary_fn in modes :
607+ agent = Agent (
608+ name = f"summary_test_{ mode_name } " ,
609+ model = TemporalModel (model_name , summary_fn = summary_fn ),
610+ )
611+ runner = InMemoryRunner (agent = agent , app_name = f"summary_{ mode_name } " )
612+ session = await runner .session_service .create_session (
613+ app_name = f"summary_{ mode_name } " , user_id = "test"
614+ )
615+ async with Aclosing (
616+ runner .run_async (
617+ user_id = "test" ,
618+ session_id = session .id ,
619+ new_message = types .Content (
620+ role = "user" , parts = [types .Part (text = "hi" )]
621+ ),
622+ )
623+ ) as agen :
624+ async for _ in agen :
625+ pass
626+
627+
628+ @pytest .mark .asyncio
629+ async def test_summary_fn_variants (client : Client ):
630+ """Test summary_fn with dynamic, None, empty string, and label fallback."""
631+ new_config = client .config ()
632+ new_config ["plugins" ] = [GoogleAdkPlugin ()]
633+ client = Client (** new_config )
634+ LLMRegistry .register (SummaryFnModel )
635+
636+ async with Worker (
637+ client ,
638+ task_queue = "adk-summary-test" ,
639+ workflows = [SummaryTestWorkflow ],
640+ max_cached_workflows = 0 ,
641+ ):
642+ handle = await client .start_workflow (
643+ SummaryTestWorkflow .run ,
644+ "summary_fn_model" ,
645+ id = f"summary-test-{ uuid .uuid4 ()} " ,
646+ task_queue = "adk-summary-test" ,
647+ execution_timeout = timedelta (seconds = 60 ),
648+ )
649+ await handle .result ()
650+
651+ summaries = []
652+ async for e in handle .fetch_history_events ():
653+ if e .HasField ("activity_task_scheduled_event_attributes" ):
654+ attrs = e .activity_task_scheduled_event_attributes
655+ if attrs .activity_type .name == "invoke_model" :
656+ summaries .append (e .user_metadata .summary .data )
657+
658+ assert len (summaries ) == 4
659+ assert summaries [0 ] == b'"Invoking summary_fn_model"' # dynamic
660+ assert summaries [1 ] == b"" # none
661+ assert summaries [2 ] == b"" # empty
662+ assert (
663+ summaries [3 ] == b'"summary_test_label_fallback"'
664+ ) # label fallback agent name
665+
666+
667+ def test_summary_and_summary_fn_raises ():
668+ """Cannot specify both summary and summary_fn."""
669+ with pytest .raises (
670+ ValueError ,
671+ match = "Cannot specify both ActivityConfig 'summary' and 'summary_fn'" ,
672+ ):
673+ TemporalModel (
674+ "m" ,
675+ activity_config = ActivityConfig (summary = "static" ),
676+ summary_fn = lambda req : "dynamic" ,
677+ )
678+
679+
583680@pytest .mark .asyncio
584681async def test_agent_outside_workflow ():
585682 """Test that an agent using TemporalModel and activity_tool works outside a Temporal workflow."""
0 commit comments