@@ -406,9 +406,10 @@ async def _handle_tool_result_submission(
406
406
"""
407
407
thread_id = input .thread_id
408
408
409
- # Extract tool results first
409
+ # Extract tool results that is send by the frontend
410
410
tool_results = await self ._extract_tool_results (input )
411
411
412
+ # if the tool results are not send by the fronted then call the tool function
412
413
if not tool_results :
413
414
logger .error (f"Tool result submission without tool results for thread { thread_id } " )
414
415
yield RunErrorEvent (
@@ -714,16 +715,25 @@ async def _start_background_execution(
714
715
# Create dynamic toolset if tools provided and prepare tool updates
715
716
toolset = None
716
717
if input .tools :
717
- toolset = ClientProxyToolset (
718
- ag_ui_tools = input .tools ,
719
- event_queue = event_queue
720
- )
721
718
722
719
# Get existing tools from the agent
723
720
existing_tools = []
724
721
if hasattr (adk_agent , 'tools' ) and adk_agent .tools :
725
722
existing_tools = list (adk_agent .tools ) if isinstance (adk_agent .tools , (list , tuple )) else [adk_agent .tools ]
726
723
724
+ # if same tool is defined in frontend and backend then agent will only use the backend tool
725
+ input_tools = []
726
+ for input_tool in input .tools :
727
+ # Check if this input tool's name matches any existing tool
728
+ if not any (hasattr (existing_tool , '__name__' ) and input_tool .name == existing_tool .__name__
729
+ for existing_tool in existing_tools ):
730
+ input_tools .append (input_tool )
731
+
732
+ toolset = ClientProxyToolset (
733
+ ag_ui_tools = input_tools ,
734
+ event_queue = event_queue
735
+ )
736
+
727
737
# Combine existing tools with our proxy toolset
728
738
combined_tools = existing_tools + [toolset ]
729
739
agent_updates ['tools' ] = combined_tools
@@ -859,15 +869,16 @@ async def _run_adk_in_background(
859
869
logger .debug (f"Emitting event to queue: { type (ag_ui_event ).__name__ } (thread { input .thread_id } , queue size before: { event_queue .qsize ()} )" )
860
870
await event_queue .put (ag_ui_event )
861
871
logger .debug (f"Event queued: { type (ag_ui_event ).__name__ } (thread { input .thread_id } , queue size after: { event_queue .qsize ()} )" )
862
- else :
863
- final_state = await self ._session_manager .get_session_state (input .thread_id ,app_name ,user_id )
864
- ag_ui_event = event_translator ._create_state_snapshot_event (final_state )
865
- await event_queue .put (ag_ui_event )
872
+
866
873
867
874
# Force close any streaming messages
868
875
async for ag_ui_event in event_translator .force_close_streaming_message ():
869
876
await event_queue .put (ag_ui_event )
870
-
877
+ # moving states snapshot events after the text event clousure to avoid this error https://github.com/Contextable/ag-ui/issues/28
878
+ final_state = await self ._session_manager .get_session_state (input .thread_id ,app_name ,user_id )
879
+ if final_state :
880
+ ag_ui_event = event_translator ._create_state_snapshot_event (final_state )
881
+ await event_queue .put (ag_ui_event )
871
882
# Signal completion - ADK execution is done
872
883
logger .debug (f"Background task sending completion signal for thread { input .thread_id } " )
873
884
await event_queue .put (None )
0 commit comments