From dcf3155a9a80301be02c2cbaaa0dc113ec56d595 Mon Sep 17 00:00:00 2001 From: 0xallam Date: Mon, 8 Jun 2026 03:17:23 +0300 Subject: [PATCH] Use function-tool schema for non-reasoning OpenAI models OpenAI's Responses API rejects tools[i].type="custom" on non-reasoning models like gpt-4o (400 with code=unknown_parameter, param=tools). Strix's SDK-native Filesystem capability registers CustomTool entries by default, so a bare STRIX_LLM=gpt-4o run failed at the first tool invocation even though warm-up (a tool-less call) succeeded. uses_chat_completions_tool_schema now consults litellm.model_cost[].supports_reasoning for OpenAI routes and flips to the chat-completions function-tool schema for models that don't carry the reasoning flag. Same registry-lookup pattern as is_known_openai_bare_model. Non-OpenAI prefixes and configs with LLM_API_BASE are unchanged (still function tools). --- strix/config/models.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/strix/config/models.py b/strix/config/models.py index b686743..7b18c90 100644 --- a/strix/config/models.py +++ b/strix/config/models.py @@ -117,7 +117,17 @@ def uses_chat_completions_tool_schema(model_name: str, settings: Settings) -> bo model = model_name.strip().lower() if "/" in model and not model.startswith("openai/"): return True - return bool(settings.llm.api_base) + if settings.llm.api_base: + return True + return not _supports_responses_custom_tools(model_name) + + +def _supports_responses_custom_tools(model_name: str) -> bool: + import litellm + + name = model_name.strip().lower().removeprefix("openai/") + entry = litellm.model_cost.get(name) or {} + return bool(entry.get("supports_reasoning")) def is_known_openai_bare_model(model_name: str) -> bool: