From f221a6c85c427757df547cce71f92fdf0861b5f5 Mon Sep 17 00:00:00 2001 From: rltakashige Date: Wed, 11 Mar 2026 18:10:12 +0000 Subject: [PATCH] Normalise Responses API tool call format (#1704) ## Motivation The responses API often does not provide tool args nested under a "function" field. Since we follow the chat completions format of tools in the backend (for MLX chat templates), we need to normalise to this format. ## Test Plan ### Manual Testing Works on n8n! image --- src/exo/master/adapters/responses.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/exo/master/adapters/responses.py b/src/exo/master/adapters/responses.py index 0a40c016..c92c4e37 100644 --- a/src/exo/master/adapters/responses.py +++ b/src/exo/master/adapters/responses.py @@ -128,6 +128,28 @@ def responses_request_to_text_generation( effort_from_reasoning, request.enable_thinking ) + # The responses API often does not provide tool args nested under a "function" field. + # Since we follow the chat completions format of tools in the backend (for MLX chat templates) + # we need to normalise to this format. + normalised_tools: list[dict[str, Any]] | None = None + if request.tools: + normalised_tools = [] + for tool in request.tools: + if "function" in tool: + normalised_tools.append(tool) + else: + normalised_tools.append( + { + "type": "function", + "function": { + "name": tool.get("name", ""), + "description": tool.get("description", ""), + "parameters": tool.get("parameters", {}), + **({"strict": tool["strict"]} if "strict" in tool else {}), + }, + } + ) + return TextGenerationTaskParams( model=request.model, input=input_value, @@ -136,7 +158,7 @@ def responses_request_to_text_generation( temperature=request.temperature, top_p=request.top_p, stream=request.stream, - tools=request.tools, + tools=normalised_tools, top_k=request.top_k, stop=request.stop, seed=request.seed,