title: السياسات المخصصة
description: “اكتب سياساتك الخاصة في JavaScript - فرض الاتفاقيات والوقاية من الانجراف واكتشاف الأعطال والتكامل مع الأنظمة الخارجية”
icon: code
تتيح لك السياسات المخصصة كتابة قواعد لأي سلوك وكيل: فرض اتفاقيات المشروع والوقاية من الانجراف وحجب العمليات المدمرة واكتشاف الوكلاء المحتجزين أو التكامل مع Slack وسير عمل الموافقة والمزيد. تستخدم نفس نظام أحداث الخطاف وقرارات allow و deny و instruct مثل السياسات المدمجة.
مثال سريع
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";
customPolicies.add({
name: "no-production-writes",
description: "Block writes to paths containing 'production'",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (ctx.toolName !== "Write" && ctx.toolName !== "Edit") return allow();
const path = ctx.toolInput?.file_path ?? "";
if (path.includes("production")) {
return deny("Writes to production paths are blocked");
}
return allow();
},
});
ثبّتها:
failproofai policies --install --custom ./my-policies.js
طريقتان لتحميل السياسات المخصصة
الخيار 1: المستند على الاتفاقية (موصى به)
انقل ملفات *policies.{js,mjs,ts} إلى .failproofai/policies/ وسيتم تحميلها تلقائياً — بدون حاجة إلى علامات أو تغييرات في الإعدادات. يعمل هذا مثل git hooks: انقل ملف، ويعمل فقط.
# مستوى المشروع — يتم إرساله إلى git ومشاركته مع الفريق
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs
# المستوى الشخصي — شخصي، ينطبق على جميع المشاريع
~/.failproofai/policies/my-policies.mjs
كيفية العمل:
- يتم مسح كلا دليل المشروع والمستخدم (اتحاد — ليس أول نطاق-يفوز)
- يتم تحميل الملفات أبجدياً في كل دليل. البادئة مع
01- و 02- للتحكم في الترتيب
- يتم تحميل الملفات المطابقة فقط
*policies.{js,mjs,ts}؛ يتم تجاهل الملفات الأخرى
- يتم تحميل كل ملف بشكل مستقل (fail-open لكل ملف)
- يعمل إلى جانب السياسات المخصصة والمدمجة الواضحة
--custom
سياسات الاتفاقية هي أسهل طريقة لبناء معيار جودة لمؤسستك. التزم .failproofai/policies/ في git وكل عضو في الفريق يحصل على نفس القواعد تلقائياً — لا حاجة إلى إعدادات لكل مطور. مع اكتشاف فريقك لأنماط الفشل الجديدة، أضف سياسة وادفع. بمرور الوقت، تصبح هذه معيار جودة حي يتحسن باستمرار مع كل مساهمة.
الخيار 2: مسار الملف الصريح
# التثبيت بملف سياسات مخصص
failproofai policies --install --custom ./my-policies.js
# استبدل مسار ملف السياسات
failproofai policies --install --custom ./new-policies.js
# إزالة مسار السياسات المخصصة من الإعدادات
failproofai policies --uninstall --custom
يتم تخزين المسار المطلق المحل في policies-config.json كـ customPoliciesPath. يتم تحميل الملف بشكل جديد في كل حدث خطاف — لا يوجد تخزين مؤقت بين الأحداث.
استخدام الاثنين معاً
يمكن للسياسات الاتفاقية والملف --custom الصريح أن يتعايشوا. ترتيب التحميل:
- ملف
customPoliciesPath الصريح (إذا تم تكوينه)
- ملفات اتفاقية المشروع (
{cwd}/.failproofai/policies/، أبجدياً)
- ملفات اتفاقية المستخدم (
~/.failproofai/policies/، أبجدياً)
واجهة برمجية التطبيقات
استيراد
import { customPolicies, allow, deny, instruct } from "failproofai";
customPolicies.add(hook)
يسجل سياسة. استدعِ هذا عدة مرات حسب الحاجة لسياسات متعددة في نفس الملف.
customPolicies.add({
name: string; // required - unique identifier
description?: string; // shown in `failproofai policies` output
match?: { events?: HookEventType[] }; // filter by event type; omit to match all
fn: (ctx: PolicyContext) => PolicyResult | Promise<PolicyResult>;
});
مساعدات القرار
| الدالة | التأثير | الاستخدام عند |
|---|
allow() | السماح بالعملية بصمت | الإجراء آمن، لا حاجة إلى رسالة |
deny(message) | حجب العملية | لا يجب على الوكيل اتخاذ هذا الإجراء |
instruct(message) | إضافة السياق دون الحجب | إعطاء الوكيل سياق إضافي للبقاء على المسار |
deny(message) - تظهر الرسالة في Claude مسبوقة بـ "Blocked by failproofai:". يقطع deny واحد كل التقييم الإضافي.
instruct(message) - يتم إضافة الرسالة إلى سياق Claude للاستدعاء الأداة الحالي. يتم تجميع جميع رسائل instruct وتسليمها معاً.
يمكنك إضافة إرشادات إضافية إلى أي رسالة deny أو instruct بإضافة حقل hint في policyParams — لا حاجة إلى تغيير الكود. يعمل هذا مع السياسات المخصصة (custom/) واتفاقية المشروع (.failproofai-project/) واتفاقية المستخدم (.failproofai-user/) أيضاً. انظر Configuration → hint للتفاصيل.
رسائل allow إعلامية
allow(message) يسمح بالعملية و يرسل رسالة معلوماتية مرة أخرى إلى Claude. يتم تسليم الرسالة كـ additionalContext في استجابة stdout لمعالج الخطاف — نفس الآلية المستخدمة من قبل instruct، ولكن مختلفة من الناحية الدلالية: إنها تحديث حالة، وليس تحذير.
| الدالة | التأثير | الاستخدام عند |
|---|
allow(message) | السماح وإرسال السياق إلى Claude | تأكيد نجاح الفحص أو شرح سبب تخطي الفحص |
حالات الاستخدام:
- تأكيدات الحالة:
allow("All CI checks passed.") — يخبر Claude بأن كل شيء أخضر
- شروحات fail-open:
allow("GitHub CLI not installed, skipping CI check.") — يخبر Claude سبب تخطي الفحص حتى يكون لديه السياق الكامل
- رسائل متعددة تتراكم: إذا أرجعت عدة سياسات
allow(message)، يتم دمج جميع الرسائل مع فواصل الأسطر وتسليمها معاً
customPolicies.add({
name: "confirm-branch-status",
match: { events: ["Stop"] },
fn: async (ctx) => {
const cwd = ctx.session?.cwd;
if (!cwd) return allow("No working directory, skipping branch check.");
// ... check branch status ...
if (allPushed) {
return allow("Branch is up to date with remote.");
}
return deny("Unpushed changes detected.");
},
});
حقول PolicyContext
| الحقل | النوع | الوصف |
|---|
eventType | string | "PreToolUse"، "PostToolUse"، "Notification"، "Stop" |
toolName | string | undefined | الأداة التي يتم استدعاؤها (على سبيل المثال "Bash"، "Write"، "Read") |
toolInput | Record<string, unknown> | undefined | معاملات إدخال الأداة |
payload | Record<string, unknown> | حمولة الحدث الخام الكاملة من Claude Code |
session | SessionMetadata | undefined | سياق الجلسة (انظر أدناه) |
| الحقل | النوع | الوصف |
|---|
sessionId | string | معرف جلسة Claude Code |
cwd | string | دليل العمل لجلسة Claude Code |
transcriptPath | string | مسار ملف نسخة JSONL للجلسة |
أنواع الأحداث
| الحدث | متى يتم تشغيله | محتويات toolInput |
|---|
PreToolUse | قبل أن يقوم Claude بتشغيل أداة | إدخال الأداة (على سبيل المثال { command: "..." } لـ Bash) |
PostToolUse | بعد اكتمال أداة | إدخال الأداة + tool_result (الإخراج) |
Notification | عندما يرسل Claude إخطار | { message: "...", notification_type: "idle" | "permission_prompt" | ... } - يجب أن تعيد الخطافات دائماً allow()، ولا يمكنها حجب الإخطارات |
Stop | عند انتهاء جلسة Claude | فارغ |
ترتيب التقييم
يتم تقييم السياسات بهذا الترتيب:
- السياسات المدمجة (بترتيب التعريف)
- السياسات المخصصة الصريحة من
customPoliciesPath (بترتيب .add())
- سياسات الاتفاقية من مشروع
.failproofai/policies/ (ملفات أبجدياً، ترتيب .add() بالداخل)
- سياسات الاتفاقية من مستخدم
~/.failproofai/policies/ (ملفات أبجدياً، ترتيب .add() بالداخل)
يقطع أول deny جميع السياسات اللاحقة. يتم تجميع جميع رسائل instruct وتسليمها معاً.
الاستيرادات المتعددة
يمكن لملفات السياسات المخصصة أن تستورد الوحدات المحلية باستخدام المسارات النسبية:
// my-policies.js
import { isBlockedPath } from "./utils.js";
import { checkApproval } from "./approval-client.js";
customPolicies.add({
name: "approval-gate",
fn: async (ctx) => {
if (ctx.toolName !== "Bash") return allow();
const approved = await checkApproval(ctx.toolInput?.command, ctx.session?.sessionId);
return approved ? allow() : deny("Approval required for this command");
},
});
يتم حل جميع الاستيرادات النسبية القابلة للوصول من ملف الإدخال. يتم تنفيذ هذا بإعادة كتابة استيرادات from "failproofai" إلى مسار التوزيع الفعلي وإنشاء ملفات .mjs مؤقتة لضمان التوافق ESM.
تصفية نوع الحدث
استخدم match.events لتقييد وقت تشغيل السياسة:
customPolicies.add({
name: "require-summary-on-stop",
match: { events: ["Stop"] },
fn: async (ctx) => {
// Only fires when the session ends
// ctx.session.transcriptPath contains the full session log
return allow();
},
});
حذف match بالكامل للتشغيل على كل نوع حدث.
معالجة الأخطاء وأنماط الفشل
السياسات المخصصة fail-open: الأخطاء لا تحجب السياسات المدمجة أو تعطل معالج الخطاف.
| الفشل | السلوك |
|---|
customPoliciesPath لم يتم تعيينه | لا تعمل سياسات مخصصة صريحة؛ تستمر سياسات الاتفاقية والمدمجة بشكل طبيعي |
| الملف غير موجود | تحذير مسجل في ~/.failproofai/hook.log؛ تستمر المدمجة |
| خطأ بناء الجملة/الاستيراد (صريح) | خطأ مسجل في ~/.failproofai/hook.log؛ سياسات مخصصة صريحة مخطية |
| خطأ بناء الجملة/الاستيراد (اتفاقية) | تم تسجيل الخطأ؛ هذا الملف مخطي، ملفات اتفاقية أخرى لا تزال تحمل |
fn يرمي في وقت التشغيل | خطأ مسجل؛ يتم التعامل مع ذلك الخطاف كـ allow؛ خطافات أخرى تستمر |
fn يأخذ أكثر من 10 ثوان | تم تسجيل انتهاء المهلة الزمنية؛ معامل كـ allow |
| دليل الاتفاقية مفقود | لا تعمل سياسات اتفاقية؛ لا خطأ |
لتصحيح أخطاء السياسة المخصصة، راقب ملف السجل:tail -f ~/.failproofai/hook.log
مثال كامل: سياسات متعددة
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";
// Prevent agent from writing to secrets/ directory
customPolicies.add({
name: "block-secrets-dir",
description: "Prevent agent from writing to secrets/ directory",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (!["Write", "Edit"].includes(ctx.toolName ?? "")) return allow();
const path = ctx.toolInput?.file_path ?? "";
if (path.includes("secrets/")) return deny("Writing to secrets/ is not permitted");
return allow();
},
});
// Keep the agent on track: verify tests before committing
customPolicies.add({
name: "remind-test-before-commit",
description: "Keep the agent on track: verify tests pass before committing",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (ctx.toolName !== "Bash") return allow();
const cmd = ctx.toolInput?.command ?? "";
if (/git\s+commit/.test(cmd)) {
return instruct("Verify all tests pass before committing. Run `bun test` if you haven't already.");
}
return allow();
},
});
// Prevent unplanned dependency changes during freeze
customPolicies.add({
name: "dependency-freeze",
description: "Prevent unplanned dependency changes during freeze period",
match: { events: ["PreToolUse"] },
fn: async (ctx) => {
if (ctx.toolName !== "Bash") return allow();
const cmd = ctx.toolInput?.command ?? "";
const isInstall = /^(npm install|yarn add|bun add|pnpm add)\s+\S/.test(cmd);
if (isInstall && process.env.DEPENDENCY_FREEZE === "1") {
return deny("Package installs are frozen. Unset DEPENDENCY_FREEZE to allow.");
}
return allow();
},
});
export { customPolicies };
أمثلة
يحتوي دليل examples/ على ملفات سياسات جاهزة للتشغيل:
| الملف | المحتويات |
|---|
examples/policies-basic.js | خمس سياسات للمبتدئين تغطي أنماط فشل الوكيل الشائعة |
examples/policies-advanced/index.js | أنماط متقدمة: استيرادات متعددة واستدعاءات غير متزامنة وتنظيف الإخراج وخطافات نهاية الجلسة |
examples/convention-policies/security-policies.mjs | سياسات أمان مستند على الاتفاقية (حجب كتابات .env ومنع إعادة كتابة سجل git) |
examples/convention-policies/workflow-policies.mjs | سياسات سير عمل مستند على الاتفاقية (تذكيرات الاختبار والملفات المكتوبة بالتدقيق) |
استخدام أمثلة الملفات الصريحة
failproofai policies --install --custom ./examples/policies-basic.js
استخدام أمثلة مستندة على الاتفاقية
# Copy to project level
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/
# Or copy to user level
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
لا حاجة إلى أمر تثبيت — يتم التقاط الملفات تلقائياً في حدث الخطاف التالي.