@@ -289,6 +289,11 @@ def merge_tool_calls(messages: List[ContextMessage]) -> List[Dict[str, Any]]:
289289 # Only add tool_calls if not empty
290290 tool_calls = merge_tool_calls (current_messages )
291291 if tool_calls :
292+ # Ensure arguments are JSON strings (OpenAI API requirement)
293+ for tc in tool_calls :
294+ if "function" in tc and "arguments" in tc ["function" ]:
295+ if isinstance (tc ["function" ]["arguments" ], dict ):
296+ tc ["function" ]["arguments" ] = json .dumps (tc ["function" ]["arguments" ])
292297 msg_dict ["tool_calls" ] = tool_calls
293298
294299 # Add tool_call_id if present (for tool role messages)
@@ -310,6 +315,11 @@ def merge_tool_calls(messages: List[ContextMessage]) -> List[Dict[str, Any]]:
310315 # Only add tool_calls if not empty
311316 tool_calls = merge_tool_calls (current_messages )
312317 if tool_calls :
318+ # Ensure arguments are JSON strings (OpenAI API requirement)
319+ for tc in tool_calls :
320+ if "function" in tc and "arguments" in tc ["function" ]:
321+ if isinstance (tc ["function" ]["arguments" ], dict ):
322+ tc ["function" ]["arguments" ] = json .dumps (tc ["function" ]["arguments" ])
313323 msg_dict ["tool_calls" ] = tool_calls
314324
315325 # Add tool_call_id if present (for tool role messages)
@@ -321,6 +331,34 @@ def merge_tool_calls(messages: List[ContextMessage]) -> List[Dict[str, Any]]:
321331 return messages
322332
323333
334+ def build_tools (tools : Optional [List [Dict [str , Any ]]]) -> Optional [List [Dict [str , Any ]]]:
335+ """Build tools in OpenAI API format.
336+
337+ Ensures tools are properly formatted:
338+ - Wrapped in {"type": "function", "function": {...}}
339+ - Parameters is never None (OpenAI API requirement)
340+ """
341+ if not tools :
342+ return None
343+
344+ result = []
345+ for tool in tools :
346+ # Extract function definition
347+ if "type" in tool and "function" in tool :
348+ func_def = tool ["function" ].copy ()
349+ else :
350+ func_def = tool .copy ()
351+
352+ # Ensure parameters is not None (OpenAI API requirement)
353+ if func_def .get ("parameters" ) is None :
354+ func_def ["parameters" ] = {"type" : "object" , "properties" : {}}
355+
356+ # Wrap in OpenAI format
357+ result .append ({"type" : "function" , "function" : func_def })
358+
359+ return result
360+
361+
324362class StreamResponse :
325363 """Holds a single chunk of streamed response."""
326364 def __init__ (self ):
0 commit comments