diff --git a/lib/req_llm/providers/openai/responses_api.ex b/lib/req_llm/providers/openai/responses_api.ex index f292786c..cb58a7a7 100644 --- a/lib/req_llm/providers/openai/responses_api.ex +++ b/lib/req_llm/providers/openai/responses_api.ex @@ -619,6 +619,7 @@ defmodule ReqLLM.Providers.OpenAI.ResponsesAPI do |> maybe_put_string("reasoning", reasoning) |> maybe_put_string("tools", tools) |> maybe_put_string("tool_choice", tool_choice) + |> maybe_put_string("parallel_tool_calls", opts_map[:parallel_tool_calls]) |> maybe_put_string("service_tier", service_tier) |> maybe_put_string("text", text_format) diff --git a/test/provider/openai/responses_api_unit_test.exs b/test/provider/openai/responses_api_unit_test.exs index 6eb126d1..e6477c4e 100644 --- a/test/provider/openai/responses_api_unit_test.exs +++ b/test/provider/openai/responses_api_unit_test.exs @@ -235,6 +235,33 @@ defmodule Provider.OpenAI.ResponsesAPIUnitTest do assert body["tool_choice"] == %{"type" => "function", "name" => "search"} end + test "encodes parallel_tool_calls true" do + request = build_request(parallel_tool_calls: true) + + encoded = ResponsesAPI.encode_body(request) + body = Jason.decode!(encoded.body) + + assert body["parallel_tool_calls"] == true + end + + test "encodes parallel_tool_calls false" do + request = build_request(parallel_tool_calls: false) + + encoded = ResponsesAPI.encode_body(request) + body = Jason.decode!(encoded.body) + + assert body["parallel_tool_calls"] == false + end + + test "omits parallel_tool_calls when not set" do + request = build_request([]) + + encoded = ResponsesAPI.encode_body(request) + body = Jason.decode!(encoded.body) + + refute Map.has_key?(body, "parallel_tool_calls") + end + test "encodes reasoning effort with atom" do request = build_request(reasoning_effort: :medium) @@ -1430,6 +1457,7 @@ defmodule Provider.OpenAI.ResponsesAPIUnitTest do max_tokens: Keyword.get(opts, :max_tokens), tools: Keyword.get(opts, :tools), tool_choice: Keyword.get(opts, :tool_choice), + parallel_tool_calls: Keyword.get(opts, :parallel_tool_calls), reasoning_effort: Keyword.get(opts, :reasoning_effort), provider_options: provider_opts }