@@ -4130,6 +4130,142 @@ async def areason(self, run_messages: RunMessages, session_id: Optional[str] = N
41304130 session_id = session_id ,
41314131 )
41324132
4133+ def update_reasoning_content_from_tool_call (
4134+ self , tool_name : str , tool_args : Dict [str , Any ]
4135+ ) -> Optional [ReasoningStep ]:
4136+ """Update reasoning_content based on tool calls that look like thinking or reasoning tools."""
4137+
4138+ # Case 1: ReasoningTools.think (has title, thought, optional action and confidence)
4139+ if tool_name .lower () == "think" and "title" in tool_args and "thought" in tool_args :
4140+ title = tool_args ["title" ]
4141+ thought = tool_args ["thought" ]
4142+ action = tool_args .get ("action" , "" )
4143+ confidence = tool_args .get ("confidence" , None )
4144+
4145+ # Create a reasoning step
4146+ reasoning_step = ReasoningStep (
4147+ title = title ,
4148+ reasoning = thought ,
4149+ action = action ,
4150+ next_action = NextAction .CONTINUE ,
4151+ confidence = confidence ,
4152+ )
4153+
4154+ # Add the step to the run response
4155+ self ._add_reasoning_step_to_extra_data (reasoning_step )
4156+
4157+ formatted_content = f"## { title } \n { thought } \n "
4158+ if action :
4159+ formatted_content += f"Action: { action } \n "
4160+ if confidence is not None :
4161+ formatted_content += f"Confidence: { confidence } \n "
4162+ formatted_content += "\n "
4163+
4164+ self ._append_to_reasoning_content (formatted_content )
4165+ return reasoning_step
4166+
4167+ # Case 2: ReasoningTools.analyze (has title, result, analysis, optional next_action and confidence)
4168+ elif tool_name .lower () == "analyze" and "title" in tool_args :
4169+ title = tool_args ["title" ]
4170+ result = tool_args .get ("result" , "" )
4171+ analysis = tool_args .get ("analysis" , "" )
4172+ next_action = tool_args .get ("next_action" , "" )
4173+ confidence = tool_args .get ("confidence" , None )
4174+
4175+ # Map string next_action to enum
4176+ next_action_enum = NextAction .CONTINUE
4177+ if next_action .lower () == "validate" :
4178+ next_action_enum = NextAction .VALIDATE
4179+ elif next_action .lower () in ["final" , "final_answer" , "finalize" ]:
4180+ next_action_enum = NextAction .FINAL_ANSWER
4181+
4182+ # Create a reasoning step
4183+ reasoning_step = ReasoningStep (
4184+ title = title ,
4185+ result = result ,
4186+ reasoning = analysis ,
4187+ next_action = next_action_enum ,
4188+ confidence = confidence ,
4189+ )
4190+
4191+ # Add the step to the run response
4192+ self ._add_reasoning_step_to_extra_data (reasoning_step )
4193+
4194+ formatted_content = f"## { title } \n "
4195+ if result :
4196+ formatted_content += f"Result: { result } \n "
4197+ if analysis :
4198+ formatted_content += f"{ analysis } \n "
4199+ if next_action and next_action .lower () != "continue" :
4200+ formatted_content += f"Next Action: { next_action } \n "
4201+ if confidence is not None :
4202+ formatted_content += f"Confidence: { confidence } \n "
4203+ formatted_content += "\n "
4204+
4205+ self ._append_to_reasoning_content (formatted_content )
4206+ return reasoning_step
4207+
4208+ # Case 3: ThinkingTools.think (simple format, just has 'thought')
4209+ elif tool_name .lower () == "think" and "thought" in tool_args :
4210+ thought = tool_args ["thought" ]
4211+ reasoning_step = ReasoningStep (
4212+ title = "Thinking" ,
4213+ reasoning = thought ,
4214+ confidence = None ,
4215+ )
4216+ formatted_content = f"## Thinking\n { thought } \n \n "
4217+ self ._add_reasoning_step_to_extra_data (reasoning_step )
4218+ self ._append_to_reasoning_content (formatted_content )
4219+ return reasoning_step
4220+
4221+ return None
4222+
4223+ def _append_to_reasoning_content (self , content : str ) -> None :
4224+ """Helper to append content to the reasoning_content field."""
4225+ if not hasattr (self .run_response , "reasoning_content" ) or not self .run_response .reasoning_content : # type: ignore
4226+ self .run_response .reasoning_content = content # type: ignore
4227+ else :
4228+ self .run_response .reasoning_content += content # type: ignore
4229+
4230+ def _add_reasoning_step_to_extra_data (self , reasoning_step : ReasoningStep ) -> None :
4231+ if hasattr (self , "run_response" ) and self .run_response is not None :
4232+ if self .run_response .extra_data is None :
4233+ from agno .run .response import RunResponseExtraData
4234+
4235+ self .run_response .extra_data = RunResponseExtraData ()
4236+
4237+ if self .run_response .extra_data .reasoning_steps is None :
4238+ self .run_response .extra_data .reasoning_steps = []
4239+
4240+ self .run_response .extra_data .reasoning_steps .append (reasoning_step )
4241+
4242+ def _add_reasoning_metrics_to_extra_data (self , reasoning_time_taken : float ) -> None :
4243+ try :
4244+ if hasattr (self , "run_response" ) and self .run_response is not None :
4245+ if self .run_response .extra_data is None :
4246+ from agno .run .response import RunResponseExtraData
4247+
4248+ self .run_response .extra_data = RunResponseExtraData ()
4249+
4250+ # Initialize reasoning_messages if it doesn't exist
4251+ if self .run_response .extra_data .reasoning_messages is None :
4252+ self .run_response .extra_data .reasoning_messages = []
4253+
4254+ metrics_message = Message (
4255+ role = "assistant" ,
4256+ content = self .run_response .reasoning_content ,
4257+ metrics = {"time" : reasoning_time_taken },
4258+ )
4259+
4260+ # Add the metrics message to the reasoning_messages
4261+ self .run_response .extra_data .reasoning_messages .append (metrics_message )
4262+
4263+ except Exception as e :
4264+ # Log the error but don't crash
4265+ from agno .utils .log import log_error
4266+
4267+ log_error (f"Failed to add reasoning metrics to extra_data: { str (e )} " )
4268+
41334269 ###########################################################################
41344270 # Default Tools
41354271 ###########################################################################
@@ -5266,142 +5402,6 @@ async def aprint_response(
52665402 panels = [p for p in panels if not isinstance (p , Status )]
52675403 live_log .update (Group (* panels ))
52685404
5269- def update_reasoning_content_from_tool_call (
5270- self , tool_name : str , tool_args : Dict [str , Any ]
5271- ) -> Optional [ReasoningStep ]:
5272- """Update reasoning_content based on tool calls that look like thinking or reasoning tools."""
5273-
5274- # Case 1: ReasoningTools.think (has title, thought, optional action and confidence)
5275- if tool_name .lower () == "think" and "title" in tool_args and "thought" in tool_args :
5276- title = tool_args ["title" ]
5277- thought = tool_args ["thought" ]
5278- action = tool_args .get ("action" , "" )
5279- confidence = tool_args .get ("confidence" , None )
5280-
5281- # Create a reasoning step
5282- reasoning_step = ReasoningStep (
5283- title = title ,
5284- reasoning = thought ,
5285- action = action ,
5286- next_action = NextAction .CONTINUE ,
5287- confidence = confidence ,
5288- )
5289-
5290- # Add the step to the run response
5291- self ._add_reasoning_step_to_extra_data (reasoning_step )
5292-
5293- formatted_content = f"## { title } \n { thought } \n "
5294- if action :
5295- formatted_content += f"Action: { action } \n "
5296- if confidence is not None :
5297- formatted_content += f"Confidence: { confidence } \n "
5298- formatted_content += "\n "
5299-
5300- self ._append_to_reasoning_content (formatted_content )
5301- return reasoning_step
5302-
5303- # Case 2: ReasoningTools.analyze (has title, result, analysis, optional next_action and confidence)
5304- elif tool_name .lower () == "analyze" and "title" in tool_args :
5305- title = tool_args ["title" ]
5306- result = tool_args .get ("result" , "" )
5307- analysis = tool_args .get ("analysis" , "" )
5308- next_action = tool_args .get ("next_action" , "" )
5309- confidence = tool_args .get ("confidence" , None )
5310-
5311- # Map string next_action to enum
5312- next_action_enum = NextAction .CONTINUE
5313- if next_action .lower () == "validate" :
5314- next_action_enum = NextAction .VALIDATE
5315- elif next_action .lower () in ["final" , "final_answer" , "finalize" ]:
5316- next_action_enum = NextAction .FINAL_ANSWER
5317-
5318- # Create a reasoning step
5319- reasoning_step = ReasoningStep (
5320- title = title ,
5321- result = result ,
5322- reasoning = analysis ,
5323- next_action = next_action_enum ,
5324- confidence = confidence ,
5325- )
5326-
5327- # Add the step to the run response
5328- self ._add_reasoning_step_to_extra_data (reasoning_step )
5329-
5330- formatted_content = f"## { title } \n "
5331- if result :
5332- formatted_content += f"Result: { result } \n "
5333- if analysis :
5334- formatted_content += f"{ analysis } \n "
5335- if next_action and next_action .lower () != "continue" :
5336- formatted_content += f"Next Action: { next_action } \n "
5337- if confidence is not None :
5338- formatted_content += f"Confidence: { confidence } \n "
5339- formatted_content += "\n "
5340-
5341- self ._append_to_reasoning_content (formatted_content )
5342- return reasoning_step
5343-
5344- # Case 3: ThinkingTools.think (simple format, just has 'thought')
5345- elif tool_name .lower () == "think" and "thought" in tool_args :
5346- thought = tool_args ["thought" ]
5347- reasoning_step = ReasoningStep (
5348- title = "Thinking" ,
5349- reasoning = thought ,
5350- confidence = None ,
5351- )
5352- formatted_content = f"## Thinking\n { thought } \n \n "
5353- self ._add_reasoning_step_to_extra_data (reasoning_step )
5354- self ._append_to_reasoning_content (formatted_content )
5355- return reasoning_step
5356-
5357- return None
5358-
5359- def _append_to_reasoning_content (self , content : str ) -> None :
5360- """Helper to append content to the reasoning_content field."""
5361- if not hasattr (self .run_response , "reasoning_content" ) or not self .run_response .reasoning_content : # type: ignore
5362- self .run_response .reasoning_content = content # type: ignore
5363- else :
5364- self .run_response .reasoning_content += content # type: ignore
5365-
5366- def _add_reasoning_step_to_extra_data (self , reasoning_step : ReasoningStep ) -> None :
5367- if hasattr (self , "run_response" ) and self .run_response is not None :
5368- if self .run_response .extra_data is None :
5369- from agno .run .response import RunResponseExtraData
5370-
5371- self .run_response .extra_data = RunResponseExtraData ()
5372-
5373- if self .run_response .extra_data .reasoning_steps is None :
5374- self .run_response .extra_data .reasoning_steps = []
5375-
5376- self .run_response .extra_data .reasoning_steps .append (reasoning_step )
5377-
5378- def _add_reasoning_metrics_to_extra_data (self , reasoning_time_taken : float ) -> None :
5379- try :
5380- if hasattr (self , "run_response" ) and self .run_response is not None :
5381- if self .run_response .extra_data is None :
5382- from agno .run .response import RunResponseExtraData
5383-
5384- self .run_response .extra_data = RunResponseExtraData ()
5385-
5386- # Initialize reasoning_messages if it doesn't exist
5387- if self .run_response .extra_data .reasoning_messages is None :
5388- self .run_response .extra_data .reasoning_messages = []
5389-
5390- metrics_message = Message (
5391- role = "assistant" ,
5392- content = self .run_response .reasoning_content ,
5393- metrics = {"time" : reasoning_time_taken },
5394- )
5395-
5396- # Add the metrics message to the reasoning_messages
5397- self .run_response .extra_data .reasoning_messages .append (metrics_message )
5398-
5399- except Exception as e :
5400- # Log the error but don't crash
5401- from agno .utils .log import log_error
5402-
5403- log_error (f"Failed to add reasoning metrics to extra_data: { str (e )} " )
5404-
54055405 def cli_app (
54065406 self ,
54075407 message : Optional [str ] = None ,
0 commit comments