إنها الساعة الثالثة فجراً، ووكيلك يعالج تذاكر الدعم بينما أنت نائم. يكتشف تذكرة تبدو كتصعيد، فينشئ ملخصاً ويرسله إلى مديرك عبر البريد الإلكتروني. الملخص صحيح لغوياً ودقيق تقنياً، لكن لم يطلب أحد إرساله، ولم يراجعه أحد، ولم توجد آلية توقفه بعد أن قرر الإرسال. نفّذ الوكيل تماماً ما سمحت به تعليماته، وهذه هي المشكلة.
أخطر إخفاقات الوكلاء ليست الهلوسة أو تعطل سير العمل؛ تلك أخطاء صاخبة يسهل اكتشافها. الإخفاقات الخطيرة هادئة: يرسل الوكيل بريداً، أو يحذف سجلاً، أو ينشئ طلباً، وكل ذلك وفق التعليمات، لكن دون طبقة تفصل قرار النموذج عن التأثير الفعلي.
الحاجز الواقي هو هذه الطبقة. يفحص الإجراء قبل تنفيذه ثم يقرر أحد ثلاثة مسارات:
- السماح بالإجراء تلقائياً
- منعه
- طلب موافقة بشرية
في هذا الدليل ستبني أربعة حواجز عملية:
- قائمة إجراءات مسموح بها
- بوابة موافقة بشرية
- وضع تشغيل تجريبي
- حدود لنطاق الضرر
ثم ستختبر أن هذه الحواجز تعمل فعلاً. للمزيد من السياق، يشرح مقال لماذا تتعطل وكلاء الذكاء الاصطناعي في الإنتاج أنماط إخفاق الوكلاء، ومنها غياب الحواجز الواقية.
صنّف الإجراءات حسب مدى الضرر
ليس كل إجراء يحتاج إلى موافقة. يمكن للوكيل تنفيذ العمليات الآمنة بسرعة، مثل:
- قراءة التقويم
- جلب التوقعات
- البحث في بيانات للقراءة فقط
- إنشاء مسودة قابلة للحذف أو التعديل
إذا وضعت كل هذه العمليات خلف موافقة بشرية، فسيتحول فريقك إلى الضغط على "موافقة" بلا مراجعة. عندها تصبح الموافقة عديمة الفائدة عندما تحتاجها فعلاً.
ابدأ بتقسيم أدوات الوكيل إلى قائمتين:
| القائمة | أمثلة | السلوك |
|---|---|---|
| قائمة السماح |
GET، البحث، القراءة، إنشاء مسودة قابلة للعكس |
تنفيذ تلقائي |
| إجراءات محمية | الإرسال، الحذف، الدفع، الكتابة في CRM أو نظام سجلات | موافقة أو منع |
استخدم هذا الاختبار العملي لكل إجراء:
إذا نفّذ الوكيل هذا الإجراء 100 مرة بالخطأ، فما حجم الضرر؟
إذا لم تكن الإجابة "لا مشكلة تقريباً"، فلا تضفه إلى قائمة السماح.
لا تصنف الإجراء وفق فعل HTTP فقط. مثلاً:
- طلب
POSTلإنشاء مسودة: قد يكون قابلاً للعكس. - طلب
POSTينشئ مسودة ثم يرسلها للعميل: إجراء خارجي وغير قابل للعكس بسهولة.
صنّف وفق النتيجة، لا وفق شكل الطلب.
يمكنك تمثيل القرار في طبقة الأدوات بهذا الشكل:
type ActionRisk = "safe" | "approval_required";
const actionPolicy: Record<string, ActionRisk> = {
"calendar.read": "safe",
"tickets.search": "safe",
"email.create_draft": "safe",
"email.send": "approval_required",
"customer.delete": "approval_required",
"payment.create": "approval_required",
};
function requiresApproval(action: string) {
return actionPolicy[action] === "approval_required";
}
المهم هنا أن تكون السياسة خارج مطالبة النموذج قدر الإمكان. لا تترك للنموذج قرار ما إذا كان الإجراء آمناً؛ طبقة التطبيق هي التي تفرض ذلك.
أضف موافقة بشرية قبل الإجراءات المدمرة
بعد تحديد الإجراءات الخطرة، أضف بوابة موافقة. يتوقف الوكيل قبل التنفيذ، ويعرض الإجراء المقترح، ثم ينتظر قرار شخص مسؤول.
هذا هو نمط الإنسان في الحلقة. قيمته الأساسية أنه يحول خطأ غير قابل للتراجع إلى طلب يمكن رفضه.
لا تعرض ملخصاً عاماً مثل:
يريد الوكيل إرسال بريد إلكتروني.
اعرض الطلب الفعلي الذي سيصل إلى النظام الخارجي:
{
"action": "email.send",
"recipient": "manager@example.com",
"subject": "تصعيد محتمل في تذكرة الدعم #481",
"body": "ملخص التذكرة...",
"reason": "صنّف الوكيل التذكرة كتصعيد محتمل"
}
وبالمثل، لا تقل:
يريد الوكيل حذف سجل.
بل اعرض:
- معرّف السجل
- نوع البيانات
- سبب الحذف
- هل توجد إمكانية استرجاع؟
- الطلب الفعلي أو الحمولة التي سترسل
مثال مبسط لتدفق موافقة:
async function executeAction(action: ToolCall) {
if (!requiresApproval(action.name)) {
return callTool(action);
}
const approval = await createApprovalRequest({
action: action.name,
arguments: action.arguments,
rawRequest: buildRawRequest(action),
});
if (approval.status !== "approved") {
await auditLog({
event: "action_rejected",
action: action.name,
approvalId: approval.id,
});
return {
blocked: true,
reason: "لم تتم الموافقة على الإجراء",
};
}
return callTool(action);
}
اجعل الرفض سريعاً وواضحاً. إذا كانت واجهة الموافقة بطيئة أو مبهمة، سيوافق المراجعون تلقائياً دون تدقيق.
كما يجب تسجيل كل قرار:
await auditLog({
event: "approval_decision",
approvalId,
reviewerId,
decision: "approved",
action: "payment.create",
timestamp: new Date().toISOString(),
});
توضح مناقشة Anthropic SDK حول إضافة خطوة موافقة بشرية قبل أن يتصرف الوكيل نقطة مهمة: لا يستطيع المراجع اتخاذ قرار حقيقي إن لم يرَ الحمولة الدقيقة التي سيجري تنفيذها.
امنح الوكيل وضع تشغيل تجريبي
بوابة الموافقة تحمي الإنتاج، لكن وضع التشغيل التجريبي يحميك قبل الوصول إليه.
في وضع التشغيل التجريبي، ينفذ الوكيل كل خطوات التخطيط المعتادة:
- يختار الأداة
- يبني الطلب
- يحدد الوسائط
- يسجل ما كان سيفعله
- لا يرسل أي طلب ذي تأثير جانبي
بدلاً من استدعاء خدمة الدفع أو الإرسال، أعد نتيجة محاكاة واضحة:
async function callTool(action: ToolCall, dryRun = false) {
const request = buildRawRequest(action);
if (dryRun && isSideEffectAction(action.name)) {
return {
dryRun: true,
executed: false,
plannedAction: action.name,
request,
};
}
return executeHttpRequest(request);
}
استخدم وضع التشغيل التجريبي في التطوير والتدريج لاكتشاف سلوك الوكيل باستخدام مدخلات واقعية دون آثار جانبية حية.
مثال على سجل مفيد:
{
"step": 4,
"tool": "customer.delete",
"dryRun": true,
"request": {
"method": "DELETE",
"url": "/customers/cus_123"
},
"result": "تم منع التنفيذ بسبب وضع التشغيل التجريبي"
}
هذا السجل يحول عبارة "الوكيل فعل شيئاً غريباً" إلى تشخيص محدد:
حاول الوكيل استدعاء نقطة حذف العملاء في الخطوة الرابعة.
يمكنك استخدام مصحح أخطاء وكيل الذكاء الاصطناعي لمراجعة المكالمات المقصودة وتسلسلها والوسائط المستخدمة فيها.
لا تخلط بين وضع التشغيل التجريبي وبوابة الموافقة:
- التشغيل التجريبي: للتطوير والتدريج؛ لا شيء حقيقي يحدث.
- بوابة الموافقة: للإنتاج؛ الإجراء حقيقي لكنه يتطلب قراراً بشرياً.
تحتاج إلى الاثنين.
حدّد نطاق الانفجار
قائمة السماح وبوابة الموافقة تتعاملان مع قرار واحد. أما حدود نطاق الانفجار فتحدد أقصى ضرر يمكن أن يسببه الوكيل عبر سلسلة من القرارات، حتى لو كانت بعض تلك القرارات صحيحة أو تمت الموافقة عليها.
ركّز على ثلاثة أنواع من الحدود.
1. نطاق الصلاحيات
لا تمنح الوكيل مفتاح مسؤول شامل إن كان يحتاج إلى مشروع واحد فقط.
بدلاً من:
ADMIN_API_KEY=global-org-admin
استخدم بيانات اعتماد محدودة:
PROJECT_ID=support-project
TOKEN_SCOPE=tickets:read,tickets:write
يجب أن يمتلك وكيل إدارة تذاكر مشروع واحد صلاحية هذا المشروع فقط، لا صلاحية المؤسسة كاملة.
2. الحصص ومعدلات التنفيذ
امنع الحلقات العالقة من تنفيذ آلاف الإجراءات.
const limits = {
"email.send": { max: 10, window: "1h" },
"payment.create": { max: 3, window: "1h" },
"customer.delete": { max: 5, window: "1d" },
};
عند تجاوز الحد، افشل بشكل مغلق:
if (await exceedsRateLimit(action.name, tenantId)) {
throw new Error(`تم تجاوز الحد المسموح للإجراء: ${action.name}`);
}
3. حدود الإنفاق
ضع سقفاً للاستهلاك لكل مهمة ولكل يوم:
- حد للرموز المميزة
- حد لتكلفة النموذج
- حد للمبالغ المالية
- حد لعدد العمليات المدفوعة
if (taskCostUsd > 2 || dailyCostUsd > 50) {
throw new Error("تم تجاوز حد الإنفاق المسموح");
}
هذه الحدود هي شبكة الأمان عند فشل حاجز أدق. حتى إن تجاوز الوكيل بوابة ما، يجب ألا يستطيع تجاوز صلاحياته أو حصته أو سقف إنفاقه.
راقب المقاييس التالية:
- عدد استدعاءات كل أداة
- عمليات الإرسال لكل مهمة
- نسبة الرفض في بوابة الموافقة
- الإنفاق لكل وكيل ولكل عميل
- معدلات الخطأ قرب الحدود
- عدد المحاولات المحظورة بسبب النطاق أو الحصة
تعامل معها كما تتعامل مع مراقبة API في أي خدمة إنتاج.
تشير OWASP إلى الخطر نفسه ضمن OWASP Top 10 لتطبيقات نماذج اللغة الكبيرة: الوكالة المفرطة. كل حد من هذه الحدود يقلل ما يمكن للوكيل فعله عند الخطأ.
كيف تختبر الحاجز الواقي
الحقيقة غير المريحة: كل حاجز واقٍ هو فرع في الشيفرة لا يُنفذ إلا عندما يكون هناك إجراء خطير. غالباً ما تكون هذه أقل المسارات استخداماً، ولذلك قد تتعطل بصمت.
البوابة التي لا تُفعّل أبداً قد تبدو تماماً كبوابة تُفعّل ثم يتم تجاوزها.
لا تختبر ذلك عبر API الحقيقي. اختبار بوابة منع إرسال البريد عبر خدمة البريد الحية قد ينتهي بإرسال بريد حقيقي. بدلاً من ذلك، حاكي نقطة النهاية ذات التأثير الجانبي واختبر المسار الذي يسلكه الوكيل.
اتبع هذه الحلقة:
- حاكي نقطة النهاية المدمرة.
- شغّل الوكيل في سيناريو يجب أن يفعّل الحاجز.
- تحقق من المسار، لا من النتيجة فقط.
- اختبر إجراءً آمناً للتأكد من أنه لا يطلب موافقة بلا داعٍ.
1. حاكي نقطة النهاية
أنشئ محاكاة لخدمة الإرسال أو الحذف أو الدفع. يجب أن تسجل ما يصلها دون لمس الخدمة الحقيقية.
const receivedRequests: Request[] = [];
app.post("/mock/send-email", (req, res) => {
receivedRequests.push(req.body);
res.status(200).json({
id: "mock_email_123",
status: "queued",
});
});
2. شغّل سيناريو خطراً
استخدم مدخلاً يفترض أن يقود إلى إجراء محمي:
const scenario = {
ticket: {
id: "481",
subject: "تصعيد عاجل",
customerImpact: "مرتفع",
},
};
3. تحقق من مسار الموافقة
شرط النجاح ليس أن الوكيل أرسل الطلب، بل أن الوكيل طلب الموافقة ولم ينفذ التأثير الجانبي.
expect(receivedRequests).toHaveLength(0);
expect(approvalRequests).toContainEqual(
expect.objectContaining({
action: "email.send",
status: "pending",
}),
);
تحقق أيضاً من الحمولة:
expect(approvalRequests[0].rawRequest).toMatchObject({
method: "POST",
url: "/emails/send",
body: expect.objectContaining({
recipient: "manager@example.com",
}),
});
4. اختبر الاتجاه العكسي
نفّذ إجراءً آمناً، مثل استعلام للقراءة فقط، وتأكد من أنه يمر مباشرة:
const result = await agent.run({
task: "اعرض التذاكر المفتوحة فقط",
});
expect(approvalRequests).toHaveLength(0);
expect(result.status).toBe("success");
البوابة التي تمنع كل شيء معطلة بقدر البوابة التي لا تمنع شيئاً.
يشرح دليل كيفية اختبار وكلاء الذكاء الاصطناعي الذين يستدعون واجهات برمجة التطبيقات الخاصة بك إعداد المحاكاة بشكل كامل، بينما يغطي اختبار وكلاء الذكاء الاصطناعي وواجهة برمجة التطبيقات أنماط التأكيد المناسبة للسلوك غير الحتمي.
النقطة الأساسية: أثبت أن التأثير الجانبي لم يحدث وأن طلب الموافقة حدث. الاختبار الذي يتحقق من المسار السعيد فقط قد ينجح في اليوم الذي تتعطل فيه بوابتك.
أين يتناسب Apidog وأين لا يتناسب
كن دقيقاً بشأن دور الأداة. Apidog ليس إطار عمل لوكلاء الذكاء الاصطناعي، ولا يستضيف النموذج، ولا يقرر ما إذا كان الإجراء آمناً، ولا يبني بوابات الموافقة بدلاً منك.
شيفرتك وطبقة التنسيق لديك هي المسؤولة عن:
- قائمة السماح
- سياسة المخاطر
- بوابة الموافقة
- وضع التشغيل التجريبي
- الصلاحيات والحصص وحدود الإنفاق
يتناسب Apidog مع طبقة API التي يستدعيها الوكيل ومع اختبارات هذه الحواجز. يمكنك استخدامه لمحاكاة نقاط النهاية ذات التأثير الجانبي، مثل الإرسال والحذف والدفع، ثم برمجة الاستجابات التي يتوقعها وكيلك، بما في ذلك الاستجابات الفاشلة.
الهدف من الاختبار هو التحقق من أن:
- نقطة النهاية الحية لم تستقبل طلباً
- تم إنشاء طلب موافقة
- الحمولة المعروضة للمراجع تطابق الطلب الفعلي
- لا يتم تنفيذ الإجراء إلا بعد الموافقة
بعبارة مختصرة: يحاكي Apidog واجهات API المدمرة التي يستدعيها وكيلك، لتتمكن من إثبات أن الوكيل يسلك مسار الموافقة بدلاً من المسار المباشر.
أسئلة مكررة
ما الفرق بين قائمة السماح وبوابة الموافقة؟
قائمة السماح تحدد الإجراءات التي يمكن تنفيذها تلقائياً دون إنسان. بوابة الموافقة تتعامل مع كل ما هو خارج تلك القائمة وتوقف التنفيذ حتى يوافق شخص مسؤول.
قائمة السماح تفرز؛ البوابة توقف.
هل تبطئ الحواجز الواقية الوكيل كثيراً؟
فقط إذا وضعت بوابات للإجراءات الخطأ. اترك القراءات والعمليات القابلة للعكس في قائمة السماح، واستخدم الموافقة للإجراءات المكلفة أو الخارجية أو صعبة التراجع.
قائمة سماح جيدة تعني أن معظم خطوات الوكيل لا تتوقف.
هل يمكن اختبار الحواجز الواقية دون استدعاء واجهات API الحقيقية؟
نعم، ويجب أن تفعل ذلك. حاكي نقطة النهاية ذات التأثير الجانبي، شغّل السيناريو الخطر، ثم تحقق من عدم وصول أي طلب للمحاكاة ومن إنشاء طلب الموافقة بالحمولة الصحيحة.
ماذا أضع خلف بوابة أولاً؟
ابدأ بما يصعب التراجع عنه:
- المدفوعات
- الحذف
- الإرسال إلى العملاء
- الكتابة في أنظمة السجلات
- أي إجراء قد يراه عميل أو زميل
إذا كان تكرار الإجراء بالخطأ مرة واحدة فقط قد يسبب ضرراً حقيقياً، فهو يحتاج إلى بوابة.
ابدأ بالإجراء الأكثر تدميراً لديك
لا تحتاج إلى تطبيق الحواجز الأربعة كلها في اليوم الأول.
اختر الإجراء الذي تخشى أن يظهر في مراجعة حادثة، ثم نفّذ هذه الخطوات هذا الأسبوع:
- انقله خارج قائمة السماح.
- أضف له بوابة موافقة.
- فعّل وضع التشغيل التجريبي له.
- حاكي نقطة النهاية الخاصة به.
- اكتب اختباراً يثبت أن الوكيل يطلب الموافقة بدلاً من التنفيذ.
عندما يكسر تغيير في الشيفرة هذا الاختبار للمرة الأولى، سترى القيمة الفعلية للحاجز الواقي: ليس لأنه موجود في التصميم، بل لأنه ثبت أنه يمنع المسار الخطر.
نزّل Apidog لمحاكاة نقاط النهاية المدمرة، وبرمجة الاستجابات، واختبار أن وكيلك يسلك مسار الموافقة بدلاً من المسار المباشر.
Top comments (0)