@@ -193,18 +193,43 @@ async def execute(
193193 if tool_calls :
194194 # Add assistant message with tool calls BEFORE executing them
195195 if hasattr (context , "add_message" ):
196- assistant_msg = {
197- "role" : "assistant" ,
198- "content" : content if content else "" ,
199- "tool_calls" : [
200- {
201- "id" : getattr (tc , "id" , None ) or tc .get ("id" ),
202- "tool" : getattr (tc , "name" , None ) or tc .get ("tool" ),
203- "arguments" : getattr (tc , "arguments" , None ) or tc .get ("arguments" ) or {},
204- }
205- for tc in tool_calls
206- ],
207- }
196+ # Store structured content from response.content (our Pydantic models)
197+ response_content = getattr (response , "content" , None )
198+ if response_content and isinstance (response_content , list ):
199+ assistant_msg = {
200+ "role" : "assistant" ,
201+ "content" : [
202+ block .model_dump () if hasattr (block , "model_dump" ) else block
203+ for block in response_content
204+ ],
205+ "tool_calls" : [
206+ {
207+ "id" : getattr (tc , "id" , None ) or tc .get ("id" ),
208+ "tool" : getattr (tc , "name" , None ) or tc .get ("tool" ),
209+ "arguments" : getattr (tc , "arguments" , None ) or tc .get ("arguments" ) or {},
210+ }
211+ for tc in tool_calls
212+ ],
213+ }
214+ else :
215+ assistant_msg = {
216+ "role" : "assistant" ,
217+ "content" : content if content else "" ,
218+ "tool_calls" : [
219+ {
220+ "id" : getattr (tc , "id" , None ) or tc .get ("id" ),
221+ "tool" : getattr (tc , "name" , None ) or tc .get ("tool" ),
222+ "arguments" : getattr (tc , "arguments" , None ) or tc .get ("arguments" ) or {},
223+ }
224+ for tc in tool_calls
225+ ],
226+ }
227+
228+ # Preserve provider metadata (provider-agnostic passthrough)
229+ # This enables providers to maintain state across steps (e.g., OpenAI reasoning items)
230+ if hasattr (response , "metadata" ) and response .metadata :
231+ assistant_msg ["metadata" ] = response .metadata
232+
208233 await context .add_message (assistant_msg )
209234
210235 # Execute tools in parallel (user guidance: assume parallel intent when multiple tool calls)
@@ -320,7 +345,22 @@ async def execute_single_tool(tc: Any, group_id: str) -> tuple[str, str]:
320345 if content :
321346 final_content = content
322347 if hasattr (context , "add_message" ):
323- await context .add_message ({"role" : "assistant" , "content" : content })
348+ # Store structured content from response.content (our Pydantic models)
349+ response_content = getattr (response , "content" , None )
350+ if response_content and isinstance (response_content , list ):
351+ assistant_msg = {
352+ "role" : "assistant" ,
353+ "content" : [
354+ block .model_dump () if hasattr (block , "model_dump" ) else block
355+ for block in response_content
356+ ],
357+ }
358+ else :
359+ assistant_msg = {"role" : "assistant" , "content" : content }
360+ # Preserve provider metadata (provider-agnostic passthrough)
361+ if hasattr (response , "metadata" ) and response .metadata :
362+ assistant_msg ["metadata" ] = response .metadata
363+ await context .add_message (assistant_msg )
324364 break
325365
326366 # No content and no tool calls - this shouldn't happen but handle it
@@ -387,11 +427,27 @@ async def execute_single_tool(tc: Any, group_id: str) -> tuple[str, str]:
387427
388428 response = await provider .complete (chat_request , ** kwargs )
389429 content = getattr (response , "content" , None )
430+ content_blocks = getattr (response , "content_blocks" , None )
390431
391432 if content :
392433 final_content = content
393434 if hasattr (context , "add_message" ):
394- await context .add_message ({"role" : "assistant" , "content" : content })
435+ # Store structured content from response.content (our Pydantic models)
436+ response_content = getattr (response , "content" , None )
437+ if response_content and isinstance (response_content , list ):
438+ assistant_msg = {
439+ "role" : "assistant" ,
440+ "content" : [
441+ block .model_dump () if hasattr (block , "model_dump" ) else block
442+ for block in response_content
443+ ],
444+ }
445+ else :
446+ assistant_msg = {"role" : "assistant" , "content" : content }
447+ # Preserve provider metadata (provider-agnostic passthrough)
448+ if hasattr (response , "metadata" ) and response .metadata :
449+ assistant_msg ["metadata" ] = response .metadata
450+ await context .add_message (assistant_msg )
395451
396452 except Exception as e :
397453 logger .error (f"Error getting final response after max iterations: { e } " )
0 commit comments