From 275ce34d0590d3bf2cb1f599b0d44ce6aabdf695 Mon Sep 17 00:00:00 2001 From: hobokenchicken Date: Wed, 18 Mar 2026 13:51:36 +0000 Subject: [PATCH] fix(openai): fix missing tools and instructions in Responses API - Add 'tools' and 'tool_choice' parameters to streaming Responses API - Include 'name' field in message items for Responses API input - Use string content for text-only messages to improve instruction following - Fix subagents not triggering and files not being created --- src/providers/openai.rs | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/providers/openai.rs b/src/providers/openai.rs index 5665e6be..e64d6ad7 100644 --- a/src/providers/openai.rs +++ b/src/providers/openai.rs @@ -190,15 +190,20 @@ impl super::Provider for OpenAIProvider { } } } else if let Some(text) = content.as_str() { - let new_type = if mapped_role == "assistant" { "output_text" } else { "input_text" }; - content = serde_json::json!([{ "type": new_type, "text": text }]); + // If it's just a string, send it as a string instead of an array of objects + // as it's safer for standard conversational messages. + content = serde_json::json!(text); } - input_parts.push(serde_json::json!({ + let mut msg_item = serde_json::json!({ "type": "message", "role": mapped_role, "content": content - })); + }); + if let Some(name) = m.get("name") { + msg_item["name"] = name.clone(); + } + input_parts.push(msg_item); } let mut body = serde_json::json!({ @@ -223,6 +228,9 @@ impl super::Provider for OpenAIProvider { if let Some(tools) = &request.tools { body["tools"] = serde_json::json!(tools); } + if let Some(tool_choice) = &request.tool_choice { + body["tool_choice"] = serde_json::json!(tool_choice); + } let resp = self .client @@ -529,15 +537,20 @@ impl super::Provider for OpenAIProvider { } } } else if let Some(text) = content.as_str() { - let new_type = if mapped_role == "assistant" { "output_text" } else { "input_text" }; - content = serde_json::json!([{ "type": new_type, "text": text }]); + // If it's just a string, send it as a string instead of an array of objects + // as it's safer for standard conversational messages. + content = serde_json::json!(text); } - input_parts.push(serde_json::json!({ + let mut msg_item = serde_json::json!({ "type": "message", "role": mapped_role, "content": content - })); + }); + if let Some(name) = m.get("name") { + msg_item["name"] = name.clone(); + } + input_parts.push(msg_item); } let mut body = serde_json::json!({ @@ -560,6 +573,13 @@ impl super::Provider for OpenAIProvider { } } + if let Some(tools) = &request.tools { + body["tools"] = serde_json::json!(tools); + } + if let Some(tool_choice) = &request.tool_choice { + body["tool_choice"] = serde_json::json!(tool_choice); + } + let url = format!("{}/responses", self.config.base_url); let api_key = self.api_key.clone(); let model = request.model.clone();