Chuyển đến nội dung chính
Chính sách tùy chỉnh cho phép bạn viết các quy tắc cho bất kỳ hành động của agent nào: thực thi các quy ước dự án, ngăn chặn sự trôi dạt, chặn các hoạt động có tính hủy diệt, phát hiện các agent bị kẹt, hoặc tích hợp với Slack, quy trình phê duyệt, v.v. Chúng sử dụng cùng một hệ thống sự kiện hook và các quyết định allow, deny, instruct như các chính sách tích hợp.

Ví dụ nhanh

// 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();
  },
});
Cài đặt nó:
failproofai policies --install --custom ./my-policies.js

Hai cách để tải chính sách tùy chỉnh

Lựa chọn 1: Dựa trên quy ước (được khuyến nghị)

Thả các tệp *policies.{js,mjs,ts} vào .failproofai/policies/ và chúng sẽ được tải tự động — không cần cờ hoặc thay đổi cấu hình. Cách này hoạt động giống như git hooks: thả một tệp, nó sẽ hoạt động.
# Mức dự án — được cam kết với git, chia sẻ với đội
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs

# Mức người dùng — cá nhân, áp dụng cho tất cả các dự án
~/.failproofai/policies/my-policies.mjs
Cách hoạt động:
  • Cả hai thư mục dự án và người dùng được quét (union — không phải first-scope-wins)
  • Các tệp được tải theo thứ tự bảng chữ cái trong mỗi thư mục. Thêm tiền tố 01-, 02- để kiểm soát thứ tự
  • Chỉ các tệp khớp với *policies.{js,mjs,ts} được tải; các tệp khác bị bỏ qua
  • Mỗi tệp được tải độc lập (fail-open cho mỗi tệp)
  • Hoạt động cùng với các chính sách --custom rõ ràng và tích hợp
Chính sách quy ước là cách dễ nhất để chia sẻ chính sách trên toàn đội. Cam kết .failproofai/policies/ với git và mỗi thành viên đội sẽ tự động nhận được chúng.

Lựa chọn 2: Đường dẫn tệp rõ ràng

# Cài đặt với tệp chính sách tùy chỉnh
failproofai policies --install --custom ./my-policies.js

# Thay thế đường dẫn tệp chính sách
failproofai policies --install --custom ./new-policies.js

# Xóa đường dẫn chính sách tùy chỉnh khỏi cấu hình
failproofai policies --uninstall --custom
Đường dẫn tuyệt đối được phân giải được lưu trữ trong policies-config.json dưới dạng customPoliciesPath. Tệp được tải lại trên mỗi sự kiện hook - không có bộ nhớ cache giữa các sự kiện.

Sử dụng cả hai cùng nhau

Chính sách quy ước và tệp --custom rõ ràng có thể cùng tồn tại. Thứ tự tải:
  1. Tệp customPoliciesPath rõ ràng (nếu được cấu hình)
  2. Tệp quy ước dự án ({cwd}/.failproofai/policies/, theo thứ tự bảng chữ cái)
  3. Tệp quy ước người dùng (~/.failproofai/policies/, theo thứ tự bảng chữ cái)

API

Nhập

import { customPolicies, allow, deny, instruct } from "failproofai";

customPolicies.add(hook)

Đăng ký một chính sách. Gọi hàm này bao nhiêu lần cần thiết cho nhiều chính sách trong cùng một tệp.
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>;
});

Trợ giúp quyết định

HàmTác độngSử dụng khi
allow()Cho phép hoạt động im lặngHành động an toàn, không cần tin nhắn
deny(message)Chặn hoạt độngAgent không nên thực hiện hành động này
instruct(message)Thêm bối cảnh mà không chặnCung cấp cho agent bối cảnh bổ sung để tiếp tục theo đúng hướng
deny(message) - thông báo sẽ xuất hiện cho Claude với tiền tố "Blocked by failproofai:". Một deny duy nhất sẽ ngắt khoá tất cả các đánh giá tiếp theo. instruct(message) - thông báo được nối thêm vào bối cảnh của Claude cho lệnh gọi công cụ hiện tại. Tất cả các thông báo instruct được tích lũy và gửi cùng nhau.
Bạn có thể nối thêm hướng dẫn bổ sung vào bất kỳ thông báo deny hoặc instruct nào bằng cách thêm trường hint trong policyParams — không cần thay đổi mã. Điều này hoạt động cho các chính sách tùy chỉnh (custom/), quy ước dự án (.failproofai-project/), và quy ước người dùng (.failproofai-user/) cũng vậy. Xem Cấu hình → hint để biết chi tiết.

Thông báo allow thông tin

allow(message) cho phép hoạt động gửi một thông báo thông tin quay lại cho Claude. Thông báo được gửi dưới dạng additionalContext trong phản hồi stdout của trình xử lý hook — cơ chế tương tự được sử dụng bởi instruct, nhưng về mặt ngữ nghĩa khác: đó là một cập nhật trạng thái, không phải cảnh báo.
HàmTác độngSử dụng khi
allow(message)Cho phép và gửi bối cảnh cho ClaudeXác nhận kiểm tra đã vượt qua, hoặc giải thích tại sao một kiểm tra bị bỏ qua
Các trường hợp sử dụng:
  • Xác nhận trạng thái: allow("All CI checks passed.") — cho Claude biết mọi thứ đang ổn
  • Giải thích fail-open: allow("GitHub CLI not installed, skipping CI check.") — cho Claude biết tại sao một kiểm tra bị bỏ qua để nó có đầy đủ bối cảnh
  • Nhiều thông báo tích lũy: nếu nhiều chính sách mỗi cái trả về allow(message), tất cả các thông báo được nối lại bằng dòng mới và gửi cùng nhau
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.");
  },
});

Các trường PolicyContext

TrườngLoạiMô tả
eventTypestring"PreToolUse", "PostToolUse", "Notification", "Stop"
toolNamestring | undefinedCông cụ được gọi (ví dụ: "Bash", "Write", "Read")
toolInputRecord<string, unknown> | undefinedCác tham số đầu vào của công cụ
payloadRecord<string, unknown>Toàn bộ tải trọng sự kiện thô từ Claude Code
sessionSessionMetadata | undefinedBối cảnh phiên (xem bên dưới)

Các trường SessionMetadata

TrườngLoạiMô tả
sessionIdstringMã định danh phiên Claude Code
cwdstringThư mục làm việc của phiên Claude Code
transcriptPathstringĐường dẫn đến tệp transcript JSONL của phiên

Các loại sự kiện

Sự kiệnKhi nó kích hoạtNội dung toolInput
PreToolUseTrước khi Claude chạy một công cụĐầu vào của công cụ (ví dụ: { command: "..." } cho Bash)
PostToolUseSau khi một công cụ hoàn thànhĐầu vào của công cụ + tool_result (đầu ra)
NotificationKhi Claude gửi thông báo{ message: "...", notification_type: "idle" | "permission_prompt" | ... } - hooks phải luôn trả về allow(), chúng không thể chặn thông báo
StopKhi phiên Claude kết thúcTrống

Thứ tự đánh giá

Chính sách được đánh giá theo thứ tự này:
  1. Chính sách tích hợp (theo thứ tự định nghĩa)
  2. Chính sách tùy chỉnh rõ ràng từ customPoliciesPath (theo thứ tự .add())
  3. Chính sách quy ước từ dự án .failproofai/policies/ (tệp theo thứ tự bảng chữ cái, .add() theo thứ tự trong)
  4. Chính sách quy ước từ người dùng ~/.failproofai/policies/ (tệp theo thứ tự bảng chữ cái, .add() theo thứ tự trong)
deny đầu tiên sẽ ngắt khoá tất cả các chính sách tiếp theo. Tất cả các thông báo instruct được tích lũy và gửi cùng nhau.

Nhập transitive

Các tệp chính sách tùy chỉnh có thể nhập các mô-đun cục bộ bằng cách sử dụng đường dẫn tương đối:
// 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");
  },
});
Tất cả các nhập tương đối có thể tiếp cận từ tệp nhập được phân giải. Điều này được triển khai bằng cách viết lại các nhập from "failproofai" thành đường dẫn dist thực tế và tạo các tệp .mjs tạm thời để đảm bảo tương thích ESM.

Lọc loại sự kiện

Sử dụng match.events để giới hạn khi một chính sách kích hoạt:
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();
  },
});
Bỏ qua match hoàn toàn để kích hoạt trên mọi loại sự kiện.

Xử lý lỗi và chế độ lỗi

Chính sách tùy chỉnh là fail-open: các lỗi không bao giờ chặn chính sách tích hợp hoặc làm hỏng trình xử lý hook.
LỗiHành vi
customPoliciesPath không được đặtKhông có chính sách tùy chỉnh rõ ràng chạy; chính sách quy ước và tích hợp tiếp tục bình thường
Tệp không tìm thấyCảnh báo được ghi vào ~/.failproofai/hook.log; tích hợp tiếp tục
Lỗi cú pháp/nhập (rõ ràng)Lỗi được ghi vào ~/.failproofai/hook.log; chính sách tùy chỉnh rõ ràng bị bỏ qua
Lỗi cú pháp/nhập (quy ước)Lỗi được ghi; tệp đó bị bỏ qua, các tệp quy ước khác vẫn tải
fn ném tại thời gian chạyLỗi được ghi; hook đó được coi là allow; các hook khác tiếp tục
fn mất lâu hơn 10 giâyTimeout được ghi; được coi là allow
Thư mục quy ước bị thiếuKhông có chính sách quy ước chạy; không có lỗi
Để gỡ lỗi các lỗi chính sách tùy chỉnh, hãy theo dõi tệp nhật ký:
tail -f ~/.failproofai/hook.log

Ví dụ đầy đủ: nhiều chính sách

// 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 };

Ví dụ

Thư mục examples/ chứa các tệp chính sách sẵn sàng để chạy:
TệpNội dung
examples/policies-basic.jsNăm chính sách khởi động bao gồm các chế độ lỗi agent phổ biến
examples/policies-advanced/index.jsMô hình nâng cao: nhập transitive, gọi không đồng bộ, làm sạch đầu ra, và hook kết thúc phiên
examples/convention-policies/security-policies.mjsChính sách bảo mật dựa trên quy ước (chặn ghi .env, ngăn chặn viết lại lịch sử git)
examples/convention-policies/workflow-policies.mjsChính sách quy trình làm việc dựa trên quy ước (nhắc nhở kiểm tra, tệp ghi kiểm toán)

Sử dụng các ví dụ tệp rõ ràng

failproofai policies --install --custom ./examples/policies-basic.js

Sử dụng các ví dụ dựa trên quy ước

# 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/
Không cần lệnh cài đặt — các tệp sẽ được chọn tự động khi sự kiện hook tiếp theo.