deny أو sanitize
على استدعاءات الأدوات التي يصدرها نموذجك — ويستدعي وكيلك البوابة بـ
"stream": true. السؤال الذي يهم فعلاً: هل يمكن لاستجابة مبثوثة أن تسرّب
استدعاء أداة محجوباً قبل أن يقرّر جدار الحماية؟ لا يمكنها، وتشرح هذه الصفحة
الآلية الوحيدة التي تجعل ذلك صحيحاً فيمكنك التفكير في زمن الاستجابة والأجزاء
التي يتلقّاها عميلك.
هذه نظرة مركّزة على سلوك SSE. للأحكام نفسها انظر
الأحكام؛ ولقواعد القاعدة انظر
مرجع القواعد.
1. مشكلة sse للبث في جدار الحماية
استجابة غير مبثوثة هي جسم JSON واحد — يرى جدار الحماية الكل، يقيّمtool_calls، ويعيد النتيجة المنظَّفة. البث مختلف: يصدر نموذج استدعاء أداة
كعشرات فروقات tool_call عبر إطارات SSE كثيرة، وبمجرد تمرير إطار، يملكه
وكيلك بالفعل — لا تراجع عن رمز أرسلته. قيّم مبكراً جداً ولا تملك الاستدعاء
الكامل (الاسم + الوسائط الكاملة) لتحكم؛ ومرّر أثناء التقدّم ويكون deny قد فات
أوانه.
تحل البوابة هذا بعقد بسيط قابل للملاحظة:
المحتوى يُبَث حياً
فروقات النص والاستدلال العادية تمرّ دون تغيير، في الزمن الحقيقي — صفر
زمن استجابة مضاف على الرموز التي يقرأها مستخدمك.
إطارات استدعاء الأداة تُحتجَز
أي إطار يحمل فرق
tool_call (أو function_call القديم) يُحجَب من
البث الحي حتى يكتمل الاستدعاء ويُقيَّم.جدار الحماية بوابة أمنية، فهو يحلّل كل إطار. لا يخمّن أن إطاراً محتوى فقط
من البايتات الخام — عضو
tool_calls مهرَّب بـ JSON لا سلسلة فرعية حرفية له
ليطابق عليها، فاختصار سلسلة فرعية سيمرّر استدعاء أداة غير مُقيَّم. إطارات SSE
صغيرة؛ البوابة تحلّل كل واحد.2. تسلسل الاحتجاز-التجميع-التقييم
لاستجابة chat-completions مبثوثة بسياسة سطح استجابة نشطة، كل إطار يصدره الأعلى يأخذ أحد مسارين:إطار محتوى / دور / استدلال / استخدام ← يُمرَّر الآن
إطار محتوى / دور / استدلال / استخدام ← يُمرَّر الآن
يُبَث إلى عميلك فوراً، بايت ببايت. هذه لا تحمل أبداً استدعاء أداة، فلا شيء
لجدار الحماية ليقرّره.
إطار tool_call (أو function_call القديم) ← يُحتجَز
إطار tool_call (أو function_call القديم) ← يُحتجَز
يُخزَّن خارج البث الحي. إطار
finish_reason الختامي لدور أداة يُحتجَز
معه، لأن إصداره مبكراً سيخبر عميلك أن الدور انتهى قبل أن يحكم جدار الحماية.arguments المبثوثة لكل استدعاء)، تقيّم كل واحد مقابل سياستك
على سطح response — نفس دلالات الحكم والقاعدة كمسار غير البث — وتصدر
الناجين فقط:
| حكم الاستدعاء المُحتجَز | ماذا يتلقّى عميلك |
|---|---|
allow / audit | الإطارات المُحتجَزة الأصلية، دون تغيير — تمرير مؤجَّل، وليس جزءاً مُعاد تجميعه. |
sanitize | الاستدعاء بوسائطه مُعاد كتابتها (الأسرار/PII المطابقة مُستبدلة برمز مكتوب)، مُعاد إصداره. |
deny | يُسقَط الاستدعاء. إذا كان استدعاء الدور الوحيد، يُغلَق الدور بـ finish_reason: "stop" — يبدو البث كأن النموذج لم يقم بأي استدعاء أداة. |
3. مثال ملموس واحد
سياسة استجابة بقاعدةdeny على *.delete (ألّفها في محرر القواعد بوحدة
التحكم) وطلب مبثوث يقرّر نموذجه استدعاء كلٍّ من db.query وdb.delete:
db.query فقط —
db.delete جُمِّع، قُيِّم، رُفِض، ولم يُصدَر أبداً. الاستدعاء الناجي مُعاد
فهرسته من 0، وحدث جدار الحماية للاستدعاء المرفوض يهبط في
سجل الأحداث مع القاعدة التي أُطلقت.
4. حجوبات inbound تختصر قبل بدء البث
رقصة الإطار المُحتجَز للسطح response فقط — الاستدعاءات التي يصدرها النموذج. deny علىinbound (أداة يعلن عنها
وكيل) يُطلق قبل استدعاء النموذج الأعلى، فطلب مبثوث يتعثّر بقاعدة inbound لا
يفتح بث SSE أبداً: يعيد HTTP 400 عادياً برمز خطأ firewall_blocked،
معلّماً بـ skip-retry.
لا إطارات، لا نافذة احتجاز — يهبط الحجب كأي خطأ غير مبثوث.
5. حواجز الحماية على نفس البث
استجابة مبثوثة يمكن أن تحمل سياسة مخرجات حاجز حماية و سياسة استجابة جدار حماية دفعةً واحدة. تتصرفان على أشياء مختلفة — حواجز الحماية تفحص النص الذي يبثّه النموذج؛ وجدار الحماية يحكم استدعاءات الأدوات — وتتركّبان:- حجب حاجز مخرجات (بث): فاحص المخرجات يقطع البث لحظة تعثّر قاعدة، يمرّر
جزء استبدال عاماً واحداً —
[Response blocked by content policy.]بـfinish_reason: "content_filter"— ويتوقف. الرسالة عامة عمداً (لا فئة قاعدة) فلا يمكن لمستكشف تعداد سياستك. احتجاز جدار حماية أثناء الطيران عند حدوث هذا يُلغى، فاستدعاء أداة محجوب لا يمكنه التسلل بعد الحجب. - إخفاء حاجز مخرجات (بث): إخفاء الطلب قبل أن يصبح النموذج حياً؛ الإخفاء المضمّن الحي لـ المخرجات المبثوثة على خارطة الطريق. على بث، قاعدة إخفاء تسجّل المطابقة لكنها حالياً تمرّر الجزء الأصلي — ألّفها عالماً أن التنقيح لم يُعَد كتابته على السلك بعد. حجب المخرجات مفروض بالكامل على البث.
تصف هذه الصفحة شكل SSE لـ chat-completions في OpenAI. نفس عقد
الاحتجاز-التقييم-الإصدار مربوط لكل صيغة — Anthropic Messages الأصلي، وGemini،
وxAI، وبث OpenAI Responses كل منها يحمله في شكل حدثه الخاص — فالسلوك الملاحظ
من قبل العميل متطابق بغض النظر عن أي مزود خدم الطلب.
6. ماذا يعني هذا لعميلك
بضع عواقب عملية لنموذج الإطار المُحتجَز:finish_reason يمكن أن يتغيّر
finish_reason يمكن أن يتغيّر
دور كان استدعاء أداته الوحيد مرفوضاً يُغلَق بـ
finish_reason: "stop"
بدلاً من "tool_calls" — لوكيلك يُقرأ كـ “اختار النموذج عدم استدعاء
أداة.” دور نجا فيه بعض الاستدعاءات يُغلَق بـ "tool_calls"، حاملاً
الناجين فقط.usage لا يزال يصل
usage لا يزال يصل
عندما يحزم أعلى رموز
usage على نفس الجزء النهائي الذي احتجزه جدار
الحماية، تعيد البوابة إرفاقه بالإطار النهائي المُعاد بناؤه — عميل طلب
استخدام البث لا يزال يحصل عليه.النص الذي شارك جزء استدعاء أداة محفوظ
النص الذي شارك جزء استدعاء أداة محفوظ
إذا أصدر النموذج محتوى و استدعاء أداة في نفس الإطار، يُستعاد المحتوى
ويُعاد إصداره حتى عندما يُجرَّد استدعاء الأداة — حجب استدعاء واحد لا يُسقط
أبداً نص مساعدك.
لا تغيير في كود الوكيل
لا تغيير في كود الوكيل
لا تختار إدخال بث في أي من هذا. اربط سياسة بالمفتاح (أو اضبط افتراضي مساحة
عمل) وابقَ تبث تماماً كما من قبل — الفرض في البوابة.
أين تذهب بعد ذلك
المراحل والأسطح
inbound، response، mcp، egress — أين يُقيَّم كل قاعدة.
الأحكام
allow، audit، deny، sanitize، pending_approval، cap_cost.
تطهير الوسائط
نقّح الأسرار من وسائط استدعاء أداة — مستوى الوسيطة فقط.
وضع الظل
خفّض الأحكام الفارضة إلى audit بينما تقيس الأثر.
