Default tool error text tells the model to "try again" after a call that may already have taken effect

Đang mở Phù hợp với người mới
#5,573 3 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

@Anurag07-crypto đang làm issue này rồi.

Từ ngày 7/11/2026.

Đánh giá

Độ khó
1/5
Thời gian dự kiến
Dưới một giờ
Mức phù hợp với người mới
72/100
Loại issue
Lỗi
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python
Lĩnh vực
ai

Hướng nghiên cứu

Tìm failure_error_function mặc định và tài liệu mô tả cách xử lý lỗi của công cụ. Bắt đầu bằng cách xác định thông báo mặc định và kiểm tra cách các ngoại lệ được chuyển thành đầu ra của công cụ. Thay đổi cách diễn đạt mặc định để cảnh báo rằng thao tác có thể đã có hiệu lực và khuyên kiểm tra trước khi thử lại; xác nhận hành vi mong đợi trong các bài kiểm thử hoặc tài liệu liên quan.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Describe the bug

An agent built on this SDK can send a write twice when a tool's reply is lost. The default failure_error_function tells the model "An error occurred while running the tool. Please try again." after every tool exception, including one raised after the effect happened. In the repro the first POST commits and the reply is lost; the model follows the text, calls again, and the service holds two orders. The SDK has no tool-retry setting, so for a tool that writes and keeps the default, this text is its retry path.

Debug information
Agents SDK version: 0.24.0 (`default_tool_error_function` is unchanged on main at 27c75c5)
Related library versions: openai 3.46.0, requests 2.34.2, pydantic 2.14.3
Python version: 3.12.14
Operating system: Linux (Ubuntu 24.04)
Model and model provider: `agents.testing.ScriptedModel`, standing in for a live model that follows the tool output
Does the issue reproduce with the latest Agents SDK release? Yes
Does the issue occur consistently or intermittently? Consistently
tool outputs the model saw: ['An error occurred while running the tool. Please try again.', 'created']
orders committed: 2
Repro steps
import http.server
import json
import os
import threading

import requests
from agents import Agent, Runner, function_tool
from agents.testing import ScriptedModel, assistant_message, function_call

os.environ.setdefault("OPENAI_AGENTS_DISABLE_TRACING", "1")
ORDERS = []  # what the order service has committed


class OrderService(http.server.BaseHTTPRequestHandler):
    def do_POST(self):
        body = self.rfile.read(int(self.headers["Content-Length"]))
        ORDERS.append(json.loads(body))  # the order is committed here
        if len(ORDERS) == 1:
            self.close_connection = True  # the reply is lost: close without answering
            return
        self.send_response(200)
        self.send_header("Content-Length", "2")
        self.end_headers()
        self.wfile.write(b"ok")

    def log_message(self, *args):
        pass


server = http.server.HTTPServer(("127.0.0.1", 0), OrderService)
threading.Thread(target=server.serve_forever, daemon=True).start()
URL = f"http://127.0.0.1:{server.server_port}/orders"


@function_tool
def create_order(sku: str, quantity: int) -> str:
    """Create an order."""
    requests.post(URL, json={"sku": sku, "quantity": quantity}).raise_for_status()
    return "created"


seen = []


def respond(call):
    # Stands in for a live model: it follows the tool output's instruction to try again.
    last = call.input[-1] if isinstance(call.input, list) else {}
    if isinstance(last, dict) and last.get("type") == "function_call_output":
        seen.append(last["output"])
        if "try again" not in last["output"]:
            return [assistant_message("done")]
    return [function_call("create_order", {"sku": "A1", "quantity": 1}, call_id=f"c{len(seen)}")]


agent = Agent(name="orders", tools=[create_order], model=ScriptedModel([{"responder": respond}] * 4))
Runner.run_sync(agent, "Order one A1.")
print("tool outputs the model saw:", seen)
print("orders committed:", len(ORDERS))
Expected behavior

A default that doesn't ask for a resend, such as "The tool call failed and may or may not have taken effect. Check before calling it again." Or keep it and document that a tool with side effects needs its own failure_error_function; either change is one string or one doc paragraph, and your users' tools that write stop resending by default.

In agent-evidence-vectors 0.35.0, a public corpus of eight lost-reply scenarios, a @function_tool with the default text and a model that follows it fails four. I can send a test that pins it, kept current by Dependabot, and checks each run with agent-evidence-verify 0.5.0, a checker that gives each run a verdict. Which option would you take?

Ngôn ngữ chính
Python
Star
30.5k
Fork
5k
Merge trung bình
16 giờ 15 phút
Pull request đã merge (30 ngày)
154

Chuẩn bị môi trường

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. 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.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của openai/openai-agents-python

Tất cả issue của openai/openai-agents-python

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.