מדיניות מותאמות אישית מאפשרת לך לכתוב כללים לכל התנהגות של סוכן: אכוף קונוונציות פרויקט, מנע סחיפה, עצור פעולות הרסניות, גלה סוכנים תקועים, או השתלב עם Slack, זרימות אישור, ועוד. הם משתמשים באותו מערכת אירועי hook וגם בהחלטות 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
איך זה עובד:
- שני המדירים (פרויקט ומשתמש) נסרקים (איחוד — לא first-scope-wins)
- הקבצים נטענים באופן אלפביתי בתוך כל ספרייה. הקדם עם
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. הקובץ נטען בצורה טרייה בכל אירוע hook - אין אחסון זיכרון מטמון בין אירועים.
שימוש בשניהם יחד
מדיניות קונוונציה וקובץ --custom מפורש יכולים להתקיים. סדר טעינה:
- קובץ
customPoliciesPath מפורש (אם מוגדר)
- קובצי קונוונציה פרויקט (
{cwd}/.failproofai/policies/, אלפביתי)
- קובצי קונוונציה משתמש (
~/.failproofai/policies/, אלפביתי)
API
ייבוא
import { customPolicies, allow, deny, instruct } from "failproofai";
customPolicies.add(hook)
רושם מדיניות. קרא לזה כמה פעמים שצריך עבור מדיניויות מרובות באותו קובץ.
customPolicies.add({
name: string; // נדרש - מזהה ייחודי
description?: string; // מוצג בפלט `failproofai policies`
match?: { events?: HookEventType[] }; // סנן לפי סוג אירוע; השמט כדי להתאים הכל
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 של מטפל ה-hook — אותו מנגנון המשמש ל-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" | ... } - hooks חייבים תמיד להחזיר 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" ייבואים לנתיב dist בפועל ויצירת קובצי .mjs זמניים כדי להבטיח תאימות ESM.
סינון סוג אירוע
השתמש ב-match.events כדי להגביל מתי מדיניות נעיר:
customPolicies.add({
name: "require-summary-on-stop",
match: { events: ["Stop"] },
fn: async (ctx) => {
// רק נעיר כאשר הסשן מסתיים
// ctx.session.transcriptPath מכיל את יומן הסשן המלא
return allow();
},
});
השמט match לחלוטין כדי להנעיר בכל סוג אירוע.
טיפול בשגיאות ואופני כשל
מדיניות מותאמת אישית היא fail-open: שגיאות לעולם לא חוסמות מדיניות מובנית או מקריסות מטפל ה-hook.
| כשל | התנהגות |
|---|
customPoliciesPath לא מוגדר | אין מדיניות מותאמת אישית מפורשת שתרוצה; מדיניויות קונוונציה וביטויים מובנים ממשיכים בדרך כלל |
| קובץ לא נמצא | אזהרה מוקדשת ל-~/.failproofai/hook.log; ביטויים מובנים ממשיכים |
| שגיאת תחביר/ייבוא (מפורשת) | שגיאה מוקדשת ל-~/.failproofai/hook.log; מדיניות מותאמת אישית מפורשת דלגה |
| שגיאת תחביר/ייבוא (קונוונציה) | שגיאה מוקדשת; קובץ זה דלג, קובצי קונוונציה אחרים עדיין טוענים |
fn זורק בזמן ריצה | שגיאה מוקדשת; hook זה מטופל כ-allow; hooks אחרים ממשיכים |
fn לוקח יותר מ-10 שניות | timeout מוקדש; מטופל כ-allow |
| ספריית קונוונציה חסרה | אין מדיניויות קונוונציה שרוצות; אין שגיאה |
כדי לנפות שגיאות במדיניות מותאמת אישית, צפו בקובץ היומן:tail -f ~/.failproofai/hook.log
דוגמה מלאה: מדיניויות מרובות
// my-policies.js
import { customPolicies, allow, deny, instruct } from "failproofai";
// מנע סוכן מכתיבה לספריית secrets/
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();
},
});
// שמור את הסוכן על המסלול: אמת בדיקות לפני התחייבות
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();
},
});
// מנע שינויי תלות בלתי מתוכננים במהלך הקפאה
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 | דפוסים מתקדמים: ייבואים טרנזיטיביים, קריאות אסינכרוניות, גישול פלט, וqueries hook של סיום סשן |
examples/convention-policies/security-policies.mjs | מדיניויות אבטחה מבוססות קונוונציה (חסום כתיבה של .env, מנע כתיבת מחדש של היסטוריה של git) |
examples/convention-policies/workflow-policies.mjs | מדיניויות זרימת עבודה מבוססות קונוונציה (תזכורות בדיקה, קובצי כתיבה בודקים) |
שימוש בדוגמאות קובץ מפורש
failproofai policies --install --custom ./examples/policies-basic.js
שימוש בדוגמאות מבוססות קונוונציה
# עתק לרמת פרויקט
mkdir -p .failproofai/policies
cp examples/convention-policies/*.mjs .failproofai/policies/
# או עתק לרמת משתמש
mkdir -p ~/.failproofai/policies
cp examples/convention-policies/*.mjs ~/.failproofai/policies/
אין צורך בפקודת התקנה — הקבצים נבחרים באופן אוטומטי בכל אירוע hook הבא.