OpenAIChatCompletionsModel sends tool_choice without tools, which the API rejects, on turns with no tools
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 82/100
Hướng nghiên cứu
Bắt đầu từ src/agents/models/openai_chatcompletions.py, nơi tool_choice được chuyển đổi và truyền đi, trong khi parallel_tool_calls đã được kiểm soát bởi converted_tools. Cần cùng điều kiện kiểm soát đó cho tool_choice trong src/agents/extensions/models/litellm_model.py. Chạy tests/models trước và sau khi thay đổi. Hoàn thành khi tool_choice bị bỏ qua khi không có tool và một test được thêm vào kiểm tra nội dung request.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Please read this first
- Have you read the docs? Yes
- Have you searched for related issues? Yes. #4326 (fixed by #4359 and #4330) covered the same API rule for
parallel_tool_calls.tool_choicewas left out.
Describe the bug
OpenAIChatCompletionsModel always sends ModelSettings.tool_choice, even when the converted tool list is empty and tools is left out of the request. The Chat Completions API rejects that combination:
Invalid value for 'tool_choice': 'tool_choice' is only allowed when 'tools' are specified.
So an app-wide RunConfig(model_settings=ModelSettings(tool_choice="auto")) breaks every turn of an agent that has no function tools and no handoffs in that turn. Examples are a final summarizer agent after a handoff, or an agent whose tools are all switched off with is_enabled. parallel_tool_calls is already omitted in this case. LitellmModel sends the same request; I checked the body LiteLLM actually posts. AnyLLMModel's chat path has the same line, but I didn't run it.
Debug information
- Agents SDK version:
main(e355d69), also 0.24.0 - Related library versions: openai 3.29.0, litellm 1.83.0
- Python version: 3.14.7
- Operating system: macOS
- Model and model provider: any Chat Completions model (
OpenAIChatCompletionsModel,LitellmModel) - Does the issue reproduce with the latest Agents SDK release? Yes
- Does the issue occur consistently or intermittently? Consistently
Repro steps
A real AsyncOpenAI client on an httpx2.MockTransport, printing what's sent:
import asyncio, json
import httpx2
from openai import AsyncOpenAI
from agents import Agent, ModelSettings, OpenAIChatCompletionsModel, RunConfig, Runner
def handler(request: httpx2.Request) -> httpx2.Response:
body = json.loads(request.content)
print("tools in request:", "tools" in body, "| tool_choice:", body.get("tool_choice"),
"| parallel_tool_calls in request:", "parallel_tool_calls" in body)
return httpx2.Response(200, json={
"id": "chatcmpl-1", "object": "chat.completion", "created": 0, "model": "gpt-4o-mini",
"choices": [{"index": 0, "finish_reason": "stop",
"message": {"role": "assistant", "content": "OK"}}],
})
async def main() -> None:
client = AsyncOpenAI(api_key="x", http_client=httpx2.AsyncClient(transport=httpx2.MockTransport(handler)))
agent = Agent(name="Summarizer", instructions="Reply OK",
model=OpenAIChatCompletionsModel("gpt-4o-mini", client))
cfg = RunConfig(tracing_disabled=True,
model_settings=ModelSettings(tool_choice="auto", parallel_tool_calls=False))
await Runner.run(agent, "Say OK.", run_config=cfg)
asyncio.run(main())
tools in request: False | tool_choice: auto | parallel_tool_calls in request: False
Expected behavior
tool_choice is left out when the request has no tools, the same way parallel_tool_calls already is.
Root cause and a possible fix
tool_choice is converted at openai_chatcompletions.py#L642 and sent at #L709, while only parallel_tool_calls is gated on converted_tools (#L652-L656). LiteLLM: litellm_model.py#L646. AnyLLM: any_llm_model.py#L951.
--- a/src/agents/models/openai_chatcompletions.py
+++ b/src/agents/models/openai_chatcompletions.py
@@ -654,6 +654,9 @@ class OpenAIChatCompletionsModel(Model):
parallel_tool_calls: bool | Omit = (
self._non_null_or_omit(model_settings.parallel_tool_calls) if converted_tools else omit
)
+ # The API rejects tool_choice without tools, the same as parallel_tool_calls.
+ if not converted_tools:
+ tool_choice = omit
--- a/src/agents/extensions/models/litellm_model.py
+++ b/src/agents/extensions/models/litellm_model.py
@@ -643,7 +643,7 @@ class LitellmModel(Model):
- tool_choice=self._remove_not_given(tool_choice),
+ tool_choice=self._remove_not_given(tool_choice) if converted_tools else None,
With that change, both repros send no tool_choice, and tests/models passes (1023 passed, 1 skipped). The placeholder Response.tool_choice built for streaming is separate and unchanged.
- Ngôn ngữ chính
- Python
- Star
- 30.5k
- Fork
- 5k
- Merge trung bình
- 22 giờ 21 phút
- Pull request đã merge (30 ngày)
- 98
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của openai/openai-agents-python
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
openai/openai-agents-python#5498 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Preserve wire aliases when converting Responses output items to inputCó thể đã có người làm @LVsarff đã nhận 1 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
openai/openai-agents-python#5477 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Voice: default sentence splitter never splits Chinese/Japanese, so TTS waits for the whole replyĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
openai/openai-agents-python#5475 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
tool_choice naming a function tool called web_search, file_search, mcp, etc. selects the built-in tool insteadCó thể đã có người làm @LVsarff đã nhận 1 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
openai/openai-agents-python#5472 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
OpenAIConversationsSession and OpenAIResponsesCompactionSession ignore set_default_openai_key()Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
openai/openai-agents-python#5471 ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của openai/openai-agents-python
Issue tương tự
-
flow-measurement measurement
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 76/100
MichaelYcJo/SpecSeal#1366 ·
-
bug c/evals c/ui size:L
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
Arize-ai/phoenix#17633 · 2 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
TransformerLensOrg/TransformerLens#1980 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Module: Solr Needs: Lead Needs: Triage Theme: Search Type: Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
internetarchive/openlibrary#14284 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 69/100
SpaceCowMedia/commander-spellbook-backend#1292 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày