---
title: 'OpenAI Agents SDK 0.23: تم اختبار حجب أخطاء الأدوات'
description: لقد قمت بتشغيل openai-agents 0.22.3 و 0.23.1 باستخدام نموذج مبرمج. رسالة خطأ الأداة الافتراضية لم تعد ترسل نص الاستثناء إلى النموذج أو إلى trace spans.
url: https://nerdleveltech.com/ar/openai-agents-python-tool-error-redaction-tested
language: ar
date: '2026-10-09'
category: ai-ml
tags:
  - openai agents sdk
  - tool error handling
  - failure_error_function
  - ai agent security
  - python
  - ai agents
markdown_url: https://nerdleveltech.com/ar/openai-agents-python-tool-error-redaction-tested.md
attribution: 'Source: NerdLevelTech — https://nerdleveltech.com/ar/openai-agents-python-tool-error-redaction-tested'
terms: https://nerdleveltech.com/llms.txt
---

# OpenAI Agents SDK 0.23: تم اختبار حجب أخطاء الأدوات

**ملخص:** في `openai-agents` 0.22.3، كانت الأداة التي تثير استثناءً (exception) ترسل نص الاستثناء الكامل مرة أخرى إلى النموذج وتكتبه في التتبع (trace). أما في 0.23.1، فإن المعالج الافتراضي يعيد رسالة ثابتة بدلاً من ذلك. لقد قمت بتشغيل كلا الإصدارين باستخدام نموذج مبرمج وكلمة مرور قاعدة بيانات وهمية للتحقق.[^1][^3][^7]

إن `failure_error_function` الخاصة بك لم تتغير ولا تزال ترى كل شيء، وكذلك الأمر بالنسبة لـ trace span التي تنتجها. وينطبق الشيء نفسه على `failure_error_function=None`. أحد الآثار الجانبية: بالنسبة للمدخلات الخاطئة، لم يعد النموذج يتلقى حتى الملاحظة القصيرة "Invalid JSON input".[^7]

## معالجة أخطاء أدوات OpenAI Agents SDK: الإجابة المختصرة

أداة الدالة (function tool) هي دالة Python يمكن للنموذج استدعاؤها. عندما تثير الدالة خطأً، يجب على SDK تحديد ما يراه النموذج بعد ذلك. يذكر دليل الأدوات أن `failure_error_function` "توفر استجابة خطأ لـ LLM في حالة تعطل استدعاء الأداة".[^5]

في الإصدار 0.22.3، تضمنت الاستجابة الافتراضية رسالة الاستثناء. أما في 0.23.1، فهي النص الثابت "An error occurred while running the tool. Please try again." ويسجل trace span أن "Tool execution failed. Error details are redacted."[^7]

## ما ستتعلمه

- محتويات رسالة خطأ الأداة الافتراضية في 0.22.3 وفي 0.23.1
- كيفية إعادة إنتاج الفرق باستخدام نموذج مبرمج وبدون مفتاح API
- المسارات التي لا تزال تكشف عن الاستثناء الخام: المعالج المخصص و `failure_error_function=None`
- لماذا لا تحمل أخطاء الوسائط الخاطئة (bad-argument) أي تلميح الآن، وما هي تكلفة ذلك
- كيف تغيرت أدوات `**kwargs`، ومعالج مختبر يمكنك نسخه

## ما الذي تغير بين 0.22.3 و 0.23.1

يتم نشر [OpenAI Agents SDK](https://openai.github.io/openai-agents-python/) للغة Python على [PyPI باسم `openai-agents`](https://pypi.org/project/openai-agents/). تم رفع الإصدار 0.22.3 في 17 سبتمبر 2026 (UTC). الإصدار التالي على PyPI هو 0.23.1، والذي تم رفعه في 2 أكتوبر 2026 (UTC). لا يوجد إصدار 0.23.0 على PyPI.[^1]

تم نشر الإصدار 0.23.0 على GitHub في 2 أكتوبر 2026 (UTC)، وعنوان سجل التغييرات الخاص به مؤرخ في 1 أكتوبر. تقول ملاحظات الإصدار 0.23.1 ما يعنيه ذلك للمحدثين: "المستخدمون الذين يقومون بالتحديث من 0.22.3 يتلقون تغييرات سلوك 0.23.0 بالإضافة إلى هذا الإصلاح".[^2][^8]

هناك تغييران في سجل تغييرات 0.23.0 مهمان هنا. تم دمج طلب السحب (Pull request) رقم 5112 في 20 سبتمبر 2026، بعد ثلاثة أيام من 0.22.3. يقول وصفه:[^3]

> الإخفاقات الافتراضية الآن تعيد رسالة ثابتة وتحجب تفاصيل الاستثناء من نطاقات الخطأ (error spans)، بما في ذلك الإلغاء المحلي للأداة والوسائط المشوهة.

طلب السحب (Pull request) رقم 5174، الذي تم دمجه في 25 سبتمبر 2026، يرفض المفاتيح الإضافية المسطحة (flat extra keys) في أدوات `**kwargs` غير الصارمة بدلاً من تجاهلها دون تنبيه.[^4]

## إعادة إنتاج المشكلة باستخدام نموذج مبرمج (scripted model)

ستحتاج إلى Python 3.10 أو إصدار أحدث وبيئتين افتراضيتين، واحدة لكل إصدار. `ScriptedModel` و `function_call` و `assistant_message` تأتي من `agents.testing`، وهي موجودة في كلا الإصدارين. لا يوجد مفتاح API مشارك في العملية.[^7]

```bash
python3 -m venv v0.22.3 && ./v0.22.3/bin/pip install openai-agents==0.22.3
python3 -m venv v0.23.1 && ./v0.23.1/bin/pip install openai-agents==0.23.1
./v0.22.3/bin/python matrix.py
./v0.23.1/bin/python matrix.py
```

احفظ هذا الملف باسم `matrix.py`. كل حالة تقوم ببناء أداة، وبرمجة النموذج لاستدعائها مرة واحدة، ثم قراءة ما تم عرضه على النموذج في الجولة الثانية، أو تسجيل أن التشغيل تسبب في خطأ بدلاً من ذلك. يقوم معالج التتبع (trace processor) بجمع كل نطاق (span) مُصدّر حتى يتمكن السكريبت من البحث فيها عن كلمة المرور الوهمية.[^7]

```python
import asyncio, json
import importlib.metadata as md
from agents import Agent, Runner, function_tool, set_trace_processors
from agents.tracing import TracingProcessor
from agents.testing import ScriptedModel, assistant_message, function_call

SECRET = "hunter2"


class Collect(TracingProcessor):
    def __init__(self): self.spans = []
    def on_trace_start(self, trace): pass
    def on_trace_end(self, trace): pass
    def on_span_start(self, span): pass
    def on_span_end(self, span): self.spans.append(span.export())
    def shutdown(self): pass
    def force_flush(self): pass


def shown_to_model(model):
    items = model.last_call.input
    return [i["output"] for i in items if isinstance(i, dict) and i.get("type") == "function_call_output"]


def lookup(account_id: str) -> str:
    raise ValueError(f"connect failed: postgres://admin:{SECRET}@db.internal/prod")


def add(a: int, b: int) -> int:
    return a + b


def kw(a: int, **kwargs) -> str:
    return f"a={a} kwargs={kwargs}"


async def run(fn, args, **tool_opts):
    col = Collect()
    set_trace_processors([col])
    tool = function_tool(fn, **tool_opts)
    model = ScriptedModel([
        [function_call(tool.name, args, call_id="c1")],
        [assistant_message("done")],
    ])
    try:
        await Runner.run(Agent(name="a", model=model, tools=[tool]), "go")
        seen = shown_to_model(model)[0]
    except Exception as e:
        seen = f"RAISED {type(e).__name__}"
    in_trace = SECRET in json.dumps(col.spans, default=str)
    return f"model saw: {seen!r} | secret in trace: {in_trace}"


async def main():
    print("openai-agents", md.version("openai-agents"))
    custom = lambda ctx, e: f"custom saw: {e}"
    print("1 tool raises         ", await run(lookup, {"account_id": "x"}))
    print("2 custom handler      ", await run(lookup, {"account_id": "x"}, failure_error_function=custom))
    print("3 handler = None      ", await run(lookup, {"account_id": "x"}, failure_error_function=None))
    print("4 bad JSON arguments  ", await run(add, '{"a": 1, "b": '))
    print("5 wrong argument type ", await run(add, {"a": "one", "b": 2}))
    print("6 extra field, add()  ", await run(add, {"a": 1, "b": 2, "c": 3}))
    print("7 **kwargs flat extra ", await run(kw, {"a": 1, "extra": "x"}, strict_mode=False))
    print("8 **kwargs nested     ", await run(kw, {"a": 1, "kwargs": {"extra": "x"}}, strict_mode=False))


asyncio.run(main())
```

## النتائج: 0.22.3 مقابل 0.23.1

![جدول يقارن ما رآه النموذج والتتبع في ثماني حالات استدعاء للأدوات على openai-agents 0.22.3 و 0.23.1](https://nerdleveltech.com/images/openai-agents-python-0-23-tool-error-redaction.png)

المخرجات في إصدار 0.22.3:

```text
openai-agents 0.22.3
1 tool raises          model saw: 'An error occurred while running the tool. Please try again. Error: connect failed: postgres://admin:hunter2@db.internal/prod' | secret in trace: True
2 custom handler       model saw: 'custom saw: connect failed: postgres://admin:hunter2@db.internal/prod' | secret in trace: True
3 handler = None       model saw: 'RAISED UserError' | secret in trace: True
4 bad JSON arguments   model saw: 'An error occurred while running the tool. Please try again. Error: Invalid JSON input for tool add' | secret in trace: False
5 wrong argument type  model saw: 'An error occurred while running the tool. Please try again. Error: Invalid JSON input for tool add' | secret in trace: False
6 extra field, add()   model saw: '3' | secret in trace: False
7 **kwargs flat extra  model saw: 'a=1 kwargs={}' | secret in trace: False
8 **kwargs nested      model saw: "a=1 kwargs={'extra': 'x'}" | secret in trace: False
```

المخرجات في إصدار 0.23.1:

```text
openai-agents 0.23.1
1 tool raises          model saw: 'An error occurred while running the tool. Please try again.' | secret in trace: False
2 custom handler       model saw: 'custom saw: connect failed: postgres://admin:hunter2@db.internal/prod' | secret in trace: True
3 handler = None       model saw: 'RAISED UserError' | secret in trace: True
4 bad JSON arguments   model saw: 'An error occurred while running the tool. Please try again.' | secret in trace: False
5 wrong argument type  model saw: 'An error occurred while running the tool. Please try again.' | secret in trace: False
6 extra field, add()   model saw: '3' | secret in trace: False
7 **kwargs flat extra  model saw: 'An error occurred while running the tool. Please try again.' | secret in trace: False
8 **kwargs nested      model saw: "a=1 kwargs={'extra': 'x'}" | secret in trace: False
```

لقد قمت بتشغيل السكريبت ثلاث مرات لكل إصدار وكانت المخرجات متطابقة في كل مرة.[^7]

## الرسالة الافتراضية لم تعد تحمل الاستثناء (exception)

الحالة 1 هي الحالة المهمة فيما يتعلق بالأسرار. تثير الأداة خطأ من نوع `ValueError` تحتوي رسالته على رابط قاعدة بيانات مع كلمة مرور. في إصدار 0.22.3، رأى النموذج رسالة الاستثناء الكاملة وكان نطاق التتبع يحتوي عليها أيضاً. أما في إصدار 0.23.1، فقد رأى النموذج الرسالة الثابتة فقط، وقرأ النطاق: "Tool execution failed. Error details are redacted."[^7]

يمكن أن تتضمن رسائل الاستثناء من برامج تشغيل قواعد البيانات، وعملاء HTTP، وواجهات برمجة تطبيقات الملفات (file APIs) سلاسل الاتصال، أو مسارات الملفات، أو تفاصيل الطلبات. وأي شيء يراه النموذج يمكن تكراره للمستخدم، أو نسخه في استدعاء لاحق للأداة، أو تخزينه في سجل المحادثة.

استمر سلوك إصدار 0.23.1 مع إعدادات التتبع الافتراضية. يذكر دليل التتبع أنه بشكل افتراضي تكون قيمة `trace_include_sensitive_data` هي `True`، ومع ذلك ظل النطاق محجوباً (redacted) في تجربتي.[^6][^7]

## المعالج المخصص لا يزال يرى كل شيء

الحالتان 2 و 3 لم تتغيرا. الدالة التي تمررها كـ `failure_error_function` تستقبل الاستثناء الأصلي، وأي شيء تعيده يذهب مباشرة إلى النموذج. في الحالة 2، نقل نص المعالج الرسالة الكاملة إلى النموذج، واحتوى التتبع على كلمة المرور أيضاً.[^7]

تمرير `failure_error_function=None` يؤدي إلى إعادة إثارة الخطأ (re-raises)، كما يصف دليل الأدوات.[^5] تسبب التشغيل في إثارة خطأ `UserError`، لذا في الحالة 3 لم يرَ النموذج أي شيء على الإطلاق، واحتوى التتبع على كلمة المرور في كلا الإصدارين.[^7]

إذا كنت قد كتبت بالفعل معالجاً يعيد `str(error)`، فإن الترقية لن تحل المشكلة نيابة عنك. الحجب الجديد يغطي الحالة الافتراضية فقط.

الـ span هو مسار منفصل عن نص النموذج. يوضح قسم الـ handler أدناه أن الـ handler المخصص الذي يعيد سلسلة نصية آمنة للنموذج لا يزال يترك الخطأ الخام في الـ span، إلا إذا قمت بإيقاف `trace_include_sensitive_data`.

هناك مفتاح تحويل آخر. ضبط `OPENAI_AGENTS_DONT_LOG_TOOL_DATA=0` في الإصدار 0.23.1 جعل الـ SDK يكتب وسائط الأداة والرسالة والـ traceback في السجل المحلي. ظل النص الذي رآه النموذج والـ trace spans محجوبة في تلك العملية.[^7] يوثق دليل التكوين هذا المتغير ويذكر أن ضبطه على `0` "يمكن أن يكشف عن بيانات النموذج أو الأداة الخام في السجلات، ورسائل الاستثناء، وسلاسل الاستثناء، وسياقات التشخيص الأخرى." ويوصي بتفعيله "فقط في بيئة تطوير خاضعة للرقابة."[^9] ابقهِ مغلقاً في بيئة الإنتاج.

## الوسائط الخاطئة تحصل الآن على رسالة عامة أيضاً

توضح الحالتان 4 و 5 التكلفة. في الإصدار 0.22.3، وصل كل من الـ JSON غير السليم ونوع الوسائط الخاطئ إلى النموذج على هيئة "حدث خطأ أثناء تشغيل الأداة. يرجى المحاولة مرة أخرى. الخطأ: مدخل JSON غير صالح للأداة add". هذا يشير إلى وجود خطأ في الوسائط، ولكن ليس ما هو الخطأ أو أي حقل تحديداً. استخدم الـ SDK نفس الصيغة لكلتا الحالتين. في الإصدار 0.23.1، يعود كلاهما بنفس النص العام دون ذكر السبب.[^7]

الرسالة التي تقول فقط "يرجى المحاولة مرة أخرى" لا تعطي النموذج أي شيء ليقوم بتصحيحه. لقد استخدمت نموذجاً مبرمجاً (scripted model)، لذا لا يمكنني تحديد عدد المرات التي يتعافى فيها نموذج حقيقي، ولم أقم بقياس ذلك.

تنبيه آخر. يحتوي مصدر الإصدار 0.22.3 على فرع افتراضي ثانٍ للـ JSON غير السليم يضيف "يرجى المحاولة مرة أخرى باستخدام JSON صالح" ورسالة الـ decoder. لم يتم تفعيل ذلك في تجاربي. يوضح دليل التكوين السبب: "مع تفعيل حجب بيانات الأداة (tool-data redaction)، فإن الوسائط غير الصالحة لـ `FunctionTool` تثير `ModelBehaviorError` عاماً دون ربطه بخطأ التحقق الأساسي."[^9] تتبعت سلسلة أسباب الاستثناء باستخدام سكريبت قصير على كلا الإصدارين ووجدت فقط `ModelBehaviorError` نفسه.[^7] قد تتصرف مسارات الاستدعاء الأخرى بشكل مختلف.

إذا كنت تريد أن يحصل النموذج على تلميح، فاكتب handler يحدد ما يجب قوله بناءً على نوع الخطأ. يوجد واحد في قسم الـ handler أدناه.

## أداة `**kwargs` ترفض المفاتيح الإضافية المسطحة

الأداة غير الصارمة (non-strict tool) التي تستخدم `**kwargs` تعلن عن كائن متداخل واحد يسمى `kwargs`. في الإصدار 0.22.3، النموذج الذي أرسل `{"a": 1, "extra": "x"}` حصل على تشغيل ناجح مع `kwargs={}`: تم إسقاط المفتاح الإضافي بصمت. في الإصدار 0.23.1، يفشل الاستدعاء بالخطأ العام (الحالة 7)، ويذكر الـ pull request أن المفاتيح تُرفض قبل الاستدعاء.[^4][^7]

يصف طلب السحب (Pull request) رقم 5174 نفس الخطأ: "قام Pydantic بتجاهل المفاتيح غير المتوقعة في المستوى الأعلى وعملت الدالة بوسطاء مفقودة."[^4] النموذج المتداخل `{"a": 1, "kwargs": {"extra": "x"}}` عمل في كلا الإصدارين (الحالة 8). أما الأداة البسيطة مثل `add()` فلا تزال تتجاهل أي مفتاح غير معروف في المستوى الأعلى في كلا الإصدارين (الحالة 6). طلب السحب يتعلق فقط بأدوات `**kwargs`.[^4][^7]

الأداة الصارمة (strict tool) التي تستخدم `**kwargs` تفشل عند تعريفها في كلا الإصدارين. في الإصدار 0.22.3 كان خطأ `UserError` يتعلق بـ `additionalProperties`. أما في الإصدار 0.23.1 فيطلب تعيين `strict_mode=False` أو استخدام بارامترات صريحة.[^7]

```python
from agents import function_tool


def kw(a: int, **kwargs) -> str:
    return ""


try:
    function_tool(kw)
except Exception as e:
    print(type(e).__name__, e)
```

المخرجات في الإصدار 0.22.3، ثم في 0.23.1 (سطر واحد لكل منهما):

```text
UserError additionalProperties should not be set for object types. This could be because you're using an older version of Pydantic, or because you configured additional properties to be allowed. If you really need this, update the function or output tool to not use a strict schema.
UserError Variadic keyword parameter `**kwargs` in function kw cannot use a strict schema. Set strict_mode=False on the function tool (or strict_json_schema=False on function_schema) and pass keyword arguments in the nested `kwargs` object, or use explicit parameters for a strict tool.
```

## معالج فشل لما يراه النموذج

يسمح هذا المعالج لفئة استثناء واحدة بالتحدث إلى النموذج، ويعطي تلميحاً ثابتاً للوسطاء المشوهة، ويخفي كل شيء آخر عن النموذج. كما يقوم بتسجيل الخطأ الخام من جانبك، حيث يمكنك تنقيته. يقوم السكريبت بتشغيل كل حالة مرتين، مرة باستخدام `trace_include_sensitive_data` الافتراضي ومرة أخرى مع تعيينه على `False`.[^7]

```python
import asyncio, json, logging, sys
from agents import Agent, RunConfig, Runner, function_tool, set_trace_processors
from agents.exceptions import ModelBehaviorError
from agents.tracing import TracingProcessor
from agents.testing import ScriptedModel, assistant_message, function_call

log = logging.getLogger("tool-errors")
logging.basicConfig(level=logging.ERROR, format="server log: %(message)s", stream=sys.stdout)


class Collect(TracingProcessor):
    def __init__(self): self.spans = []
    def on_trace_start(self, trace): pass
    def on_trace_end(self, trace): pass
    def on_span_start(self, span): pass
    def on_span_end(self, span): self.spans.append(span.export())
    def shutdown(self): pass
    def force_flush(self): pass


class SafeToolError(Exception):
    """Messages on this class are written for the model and safe to show."""


def failure_handler(ctx, error):
    log.error("%s: %s", type(error).__name__, error)
    if isinstance(error, SafeToolError):
        return f"Tool failed: {error}"
    if isinstance(error, ModelBehaviorError):
        return "Your arguments did not match the tool schema. Send valid JSON with the listed fields."
    return "Tool failed for an internal reason. Do not retry with the same input."


def lookup(account_id: str) -> str:
    if account_id == "x":
        raise SafeToolError("account x is archived, use an active id")
    raise ValueError("connect failed: postgres://admin:hunter2@db.internal/prod")


async def call(args, sensitive):
    col = Collect()
    set_trace_processors([col])
    tool = function_tool(lookup, failure_error_function=failure_handler)
    model = ScriptedModel([[function_call("lookup", args, call_id="c1")], [assistant_message("done")]])
    cfg = RunConfig(trace_include_sensitive_data=sensitive)
    await Runner.run(Agent(name="a", model=model, tools=[tool]), "go", run_config=cfg)
    seen = [i["output"] for i in model.last_call.input if isinstance(i, dict) and i.get("type") == "function_call_output"][0]
    return f"model saw: {seen} | secret in trace: {'hunter2' in json.dumps(col.spans, default=str)}"


async def main():
    for sensitive in (True, False):
        print(f"trace_include_sensitive_data={sensitive}")
        print(await call({"account_id": "x"}, sensitive))
        print(await call({"account_id": "y"}, sensitive))
        print(await call('{"account_id": ', sensitive))


asyncio.run(main())
```

المخرجات، متطابقة في الإصدارين 0.22.3 و 0.23.1:

```text
trace_include_sensitive_data=True
server log: SafeToolError: account x is archived, use an active id
model saw: Tool failed: account x is archived, use an active id | secret in trace: False
server log: ValueError: connect failed: postgres://admin:hunter2@db.internal/prod
model saw: Tool failed for an internal reason. Do not retry with the same input. | secret in trace: True
server log: ModelBehaviorError: Invalid JSON input for tool lookup
model saw: Your arguments did not match the tool schema. Send valid JSON with the listed fields. | secret in trace: False
trace_include_sensitive_data=False
server log: SafeToolError: account x is archived, use an active id
model saw: Tool failed: account x is archived, use an active id | secret in trace: False
server log: ValueError: connect failed: postgres://admin:hunter2@db.internal/prod
model saw: Tool failed for an internal reason. Do not retry with the same input. | secret in trace: False
server log: ModelBehaviorError: Invalid JSON input for tool lookup
model saw: Your arguments did not match the tool schema. Send valid JSON with the listed fields. | secret in trace: False
```

يقوم المعالج بعمله بالنسبة للنموذج: فقط نص `SafeToolError` هو الذي مر. هناك شيئان لا يفعلهما؛ فأسطر سجل الخادم لا تزال تحتوي على كلمة المرور. وفي التشغيل الافتراضي، احتوى نطاق التتبع (trace span) على كلمة المرور في حالة `ValueError` في كلا الإصدارين. يسجل الإصدار 0.22.3 الاستثناء الخام في النطاق لكل معالج، بينما يقوم الإصدار 0.23.1 بحذفه فقط للمعالج الافتراضي.[^7] تعيين `trace_include_sensitive_data=False` أدى إلى إزالتها في تجربتي. يذكر دليل التتبع أن نطاقات التوليد ونطاقات الدوال تخزن المدخلات والمخرجات، وأنه يمكنك تعطيل التقاط هذه البيانات بنفس الإعداد.[^6] قم بتنقية أو تقييد السجل، وحدد إعداد التتبع الذي تريده.

## ما لم أقم باختباره

لقد استخدمت نموذجاً مبرمجاً (scripted model)، لذا لا يوجد شيء هنا يوضح كيف يتفاعل نموذج حقيقي مع الرسالة العامة. قمت بتشغيل Python 3.13.16 على Linux مع `openai` 3.26.1 ولم أجرب إصدارات Python أخرى.[^7]

لم أختبر عمليات التشغيل المتدفقة (streaming runs)، أو أدوات MCP، أو الأدوات المستضافة، أو عمليات التسليم (handoffs) أو تدفقات الموافقة. تسرد قائمة تغييرات 0.23.0 العديد من التغييرات الأخرى، من بينها تحديد نطاق الموافقة لكل وكيل، وخيارات البيئة المعزولة (sandbox)، وميزانية فحص السجل المشفر. لم أختبر أيًا منها.[^2] إذا كنت تستخدم الموافقات، فإن [اختبار needsApproval الخاص بي على JavaScript SDK](https://nerdleveltech.com/openai-agents-js-needsapproval-null-optional-tested) يغطي استدعاء الموافقة لهذا الـ SDK، ويغطي [درس human-in-the-loop التعليمي](https://nerdleveltech.com/human-in-the-loop-claude-agent-sdk-typescript-tutorial) تدفقات الموافقة في Claude Agent SDK.

## قائمة مراجعة الترقية

1. ابحث في أدواتك عن `failure_error_function` وعن أي معالج يعيد `str(error)`.
2. حدد أنواع الاستثناءات التي يمكن أن تصل إلى النموذج، وأعد سلسلة نصية ثابتة للبقية.
3. أضف تلميحاً لـ `ModelBehaviorError` حتى يتعلم النموذج على الأقل أن وسائطه كانت خاطئة.

- راجع أي أداة `**kwargs` غير صارمة للموديلات التي ترسل مفاتيح إضافية في المستوى الأعلى.
- راجع نظام تتبع الآثار (trace backend) الخاص بك للبحث عن الـ spans التي تم تصديرها قبل الترقية، حيث أن الإصدار 0.22.3 وضع نصوص الأخطاء بداخلها.
- إذا كنت تستخدم معالجًا مخصصًا (custom handler)، فحدد ما إذا كان من الممكن أن تظل الأخطاء الخام في الـ trace spans الخاصة بك، وقم بضبط `trace_include_sensitive_data` ليتناسب مع ذلك.
- قم بتثبيت إصدار محدد من `openai-agents` قمت باختباره، وأعد تشغيل `matrix.py` بعد كل عملية ترقية.

للاطلاع على أنماط حواجز الحماية (guardrail) الأوسع، راجع [موثوقية وكلاء الذكاء الاصطناعي، وحلقات التحقق وحواجز الحماية](https://nerdleveltech.com/ai-agent-reliability-verification-loops-guardrails).

## الأسئلة الشائعة

### ماذا تقول رسالة خطأ الأداة الافتراضية في openai-agents 0.23.1؟

تعيد الرسالة "An error occurred while running the tool. Please try again." بدون أي نص للاستثناء. لقد رأيت هذا النص في مدخلات الموديل عند حدوث `ValueError`، أو عند وجود JSON غير صحيح، أو نوع وسيط (argument) خاطئ.[^7]

### هل لا تزال دالة failure\_error\_function المخصصة تستقبل الاستثناء الخام؟

نعم. في مثال المعالج أعلاه، يظهر السجل (log) الخاص بها الـ `ValueError` الأصلي، وفي حالة الـ JSON غير الصحيح، يظهر `ModelBehaviorError`، وذلك في كلا الإصدارين. وأي شيء تعيده الدالة يذهب إلى الموديل، لذا فهي تحتاج إلى نظام تصفية خاص بها.[^7]

### كيف أعطي الموديل خطأً مفيدًا دون تسريب أسرار؟

قم بكتابة معالج يعيد نصًا فقط لفئات الاستثناءات التي تتحكم بها، ويعطي تلميحًا ثابتًا للوسائط غير الصحيحة، ويسجل الخطأ الخام من جانبك. المثال أعلاه يفعل ذلك بالنسبة للنص الموجه للموديل. ولكنه لا يمسح الـ trace span، وهو ما يتطلب ضبط `trace_include_sensitive_data=False`.[^6][^7]

### هل يوجد إصدار openai-agents 0.23.0 على PyPI؟

لا. يسرد PyPI الإصدار 0.22.3 ثم 0.23.1، الذي تم رفعه في 2 أكتوبر 2026. تغييرات الإصدار 0.23.0 مدمجة داخل 0.23.1.[^1][^8]

### هل أحتاج إلى مفتاح OpenAI API لإعادة إنتاج هذه المشكلة؟

لا. يقوم `ScriptedModel` في `agents.testing` باستبدال الموديل، وقد تم تشغيل كل حالة دون اتصال بالإنترنت (offline). كما تقوم السكربتات باستبدال معالجات التتبع (trace processors) الخاصة بـ SDK بمعالج محلي، لذا لا يتم تصدير أي شيء.[^7]

## الخلاصة

في الإصدار 0.22.3، كان من الممكن للأداة التي تفشل أن تضع نص الاستثناء الخاص بها أمام الموديل وفي الـ spans التي يصدرها الـ SDK. في الإصدار 0.23.1، يتوقف المعالج الافتراضي عن القيام بذلك.

تظل المعالجات المخصصة، و`failure_error_function=None`، وإعدادات التتبع، وتكلفة رسالة الخطأ الخالية من التلميحات، قرارات تعود إليك. اختبرها باستخدام موديل مبرمج (scripted model) قبل الترقية.

[^1]: PyPI, [openai-agents](https://pypi.org/project/openai-agents/), release metadata read through the PyPI JSON API on October 9, 2026: 0.22.3 uploaded 2026-09-17 and 0.23.1 uploaded 2026-10-02, with no 0.23.0 in the release list. `pip download openai-agents==0.23.0` also found no matching distribution.

[^3]: openai/openai-agents-python, [pull request #5112, "fix(tools): redact default tool failure details"](https://github.com/openai/openai-agents-python/pull/5112), merged 2026-09-20. The quoted sentence is from the description.

[^7]: Author's measurement, October 9, 2026: Python 3.13.16 on Linux, `openai` 3.26.1, `openai-agents` 0.22.3 and 0.23.1 in separate virtual environments, `ScriptedModel` from `agents.testing`, no API key. Every script in this post was extracted from the finished article and rerun, and the output blocks match. The matrix output was identical across three runs per version. The cause-chain check mentioned above is a separate short script that is not shown, and so is the run that printed the exported span's error field to read its exact text. Statements about branches inside the default handler and the span logic come from reading the installed source file `agents/tool.py` in each version.

[^5]: OpenAI Agents SDK, [Tools guide](https://openai.github.io/openai-agents-python/tools/), section "Handling errors in function tools". Quote and the `None` behavior taken on October 9, 2026 from the guide's source file, `docs/tools.md` on the main branch.

[^2]: openai/openai-agents-python GitHub releases, [v0.23.0](https://github.com/openai/openai-agents-python/releases/tag/v0.23.0), published 2026-10-02 UTC with a changelog heading of 2026-10-01. The list includes #5112 and #5174 (bug fixes), #5144 (approval scoping), and the features #5116 (sandbox), #5118 (encrypted history scan budget) and #5135 (sandbox).

[^8]: openai/openai-agents-python GitHub releases, [v0.23.1](https://github.com/openai/openai-agents-python/releases/tag/v0.23.1), published 2026-10-02. The quoted sentence is from the release readiness review in the release notes, which also says PyPI had neither 0.23.0 nor 0.23.1 when the review was written.

[^4]: openai/openai-agents-python, [pull request #5174, "fix(core): reject silently discarded kwargs tool arguments"](https://github.com/openai/openai-agents-python/pull/5174), merged 2026-09-25. The quoted words are from the summary.

[^6]: OpenAI Agents SDK, [Tracing guide](https://openai.github.io/openai-agents-python/tracing/), section "Sensitive data": "By default, `trace_include_sensitive_data` is `True`." The same section says: "The `generation_span()` stores the inputs/outputs of the LLM generation, and `function_span()` stores the inputs/outputs of function calls. These may contain sensitive data, so you can disable capturing that data via" the `RunConfig.trace_include_sensitive_data` setting. Taken from `docs/tracing.md` on the main branch on October 9, 2026.

[^9]: OpenAI Agents SDK, [Configuration guide](https://openai.github.io/openai-agents-python/config/), section "Sensitive data in logs and diagnostics". Quotes checked on October 9, 2026 against the guide's source file, `docs/config.md`, in a clone of the main branch at commit 125efa0 (2026-10-08).
