> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Các Chính Sách Tùy Chỉnh

> Viết các quy tắc riêng của bạn bằng JavaScript - thực thi quy ước, ngăn chặn sai lệch, phát hiện sự cố, tích hợp với các hệ thống bên ngoài

Các 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 vi nào của agent: thực thi quy ước dự án, ngăn chặn sai lệch, gated các hoạt động hủy diệt, phát hiện agent bị kẹt, hoặc tích hợp với Slack, quy trình phê duyệt, và nhiều hơn nữa. Chúng sử dụng cùng 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 sẵn.

***

## Ví dụ nhanh

```js theme={null}
// 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ó:

```bash theme={null}
failproofai policies --install --custom ./my-policies.js
```

***

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

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

Đặt 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. Điều này hoạt động giống như git hooks: đặt một tệp, nó chỉ hoạt động.

```
# Project level — committed to git, shared with the team
.failproofai/policies/security-policies.mjs
.failproofai/policies/workflow-policies.mjs

# User level — personal, applies to all projects
~/.failproofai/policies/my-policies.mjs
```

**Cách nó 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` và tích hợp sẵn rõ ràng

<Tip>
  Các chính sách theo quy ước là cách dễ nhất để xây dựng một tiêu chuẩn chất lượng cho tổ chức của bạn. Commit `.failproofai/policies/` vào git và mỗi thành viên trong nhóm sẽ tự động nhận các quy tắc giống nhau — không cần thiết lập cho từng nhà phát triển. Khi nhóm của bạn phát hiện ra các chế độ lỗi mới, hãy thêm một chính sách và đẩy lên. Theo thời gian, chúng trở thành một tiêu chuẩn chất lượng sống động tiếp tục cải thiện với mỗi đóng góp.
</Tip>

### Tùy chọn 2: Đường dẫn tệp rõ ràng

```bash theme={null}
# Install with a custom policies file
failproofai policies --install --custom ./my-policies.js

# Replace the policies file path
failproofai policies --install --custom ./new-policies.js

# Remove the custom policies path from config
failproofai policies --uninstall --custom
```

Đường dẫn tuyệt đối được phân giải được lưu trữ trong `policies-config.json` như `customPoliciesPath`. Tệp được tải mớ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

Các chính sách theo quy ước và tệp `--custom` rõ ràng có thể coexist. Thứ tự tải:

1. Tệp `customPoliciesPath` rõ ràng (nếu được cấu hình)
2. Các tệp quy ước dự án (`{cwd}/.failproofai/policies/`, theo thứ tự bảng chữ cái)
3. Các tệp quy ước người dùng (`~/.failproofai/policies/`, theo thứ tự bảng chữ cái)

***

## API

### Import

```js theme={null}
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 tùy ý cho nhiều chính sách trong cùng một tệp.

```ts theme={null}
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àm                 | Hiệu ứng                    | Sử dụng khi                                              |
| ------------------- | --------------------------- | -------------------------------------------------------- |
| `allow()`           | Cho phép hoạt động im lặng  | Hành động an toàn, không cần thông báo                   |
| `deny(message)`     | Chặn hoạt động              | Agent không nên thực hiện hành động này                  |
| `instruct(message)` | Thêm ngữ cảnh mà không chặn | Cung cấp ngữ cảnh bổ sung cho agent để tiếp tục theo dõi |

`deny(message)` - thông báo xuất hiện cho Claude với tiền tố `"Blocked by failproofai:"`. Một `deny` duy nhất sẽ short-circuit tất cả các đánh giá tiếp theo.

`instruct(message)` - thông báo được nối vào ngữ 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à cung cấp cùng nhau.

<Tip>
  Bạn có thể nối thêm hướng dẫn 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 [Configuration → hint](/vi/configuration#hint-cross-cutting) để biết chi tiết.
</Tip>

### Thông báo allow thông tin

`allow(message)` cho phép hoạt động **và** gửi thông báo thông tin lại cho Claude. Thông báo được cung cấp như `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 khác nhau về mặt ngữ nghĩa: đó là một cập nhật trạng thái, không phải một cảnh báo.

| Hàm              | Hiệu ứng                            | Sử dụng khi                                                               |
| ---------------- | ----------------------------------- | ------------------------------------------------------------------------- |
| `allow(message)` | Cho phép và gửi ngữ cảnh cho Claude | Xác nhận kiểm tra đã vượt qua, hoặc giải thích tại sao kiểm tra bị bỏ qua |

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ứ đều bình thường
* **Giải thích fail-open:** `allow("GitHub CLI not installed, skipping CI check.")` — cho Claude biết tại sao kiểm tra bị bỏ qua để nó có bối cảnh đầy đủ
* **Nhiều thông báo tích lũy:** nếu một số chính sách mỗi cái trả về `allow(message)`, tất cả thông báo được nối với các dòng mới và cung cấp cùng nhau

```js theme={null}
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ường      | Loại                                   | Mô tả                                                        |
| ----------- | -------------------------------------- | ------------------------------------------------------------ |
| `eventType` | `string`                               | `"PreToolUse"`, `"PostToolUse"`, `"Notification"`, `"Stop"`  |
| `toolName`  | `string \| undefined`                  | Công cụ đang được gọi (ví dụ: `"Bash"`, `"Write"`, `"Read"`) |
| `toolInput` | `Record<string, unknown> \| undefined` | Các tham số đầu vào của công cụ                              |
| `payload`   | `Record<string, unknown>`              | Payload sự kiện thô đầy đủ từ Claude Code                    |
| `session`   | `SessionMetadata \| undefined`         | Ngữ cảnh phiên (xem bên dưới)                                |

### Các trường `SessionMetadata`

| Trường           | Loại     | Mô tả                                     |
| ---------------- | -------- | ----------------------------------------- |
| `sessionId`      | `string` | Định danh phiên Claude Code               |
| `cwd`            | `string` | Thư mục làm việc của phiên Claude Code    |
| `transcriptPath` | `string` | Đường dẫn đến tệp bản ghi JSONL của phiên |

### Các loại sự kiện

| Sự kiện        | Khi nó kích hoạt                  | Nội dung `toolInput`                                                                                                                             |
| -------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `PreToolUse`   | Trước khi Claude chạy một công cụ | Đầu vào của công cụ (ví dụ: `{ command: "..." }` cho Bash)                                                                                       |
| `PostToolUse`  | Sau khi một công cụ hoàn tất      | Đầu vào của công cụ + `tool_result` (đầu ra)                                                                                                     |
| `Notification` | Khi Claude gửi một 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 |
| `Stop`         | Khi phiên Claude kết thúc         | Trống                                                                                                                                            |

***

## Thứ tự đánh giá

Các chính sách được đánh giá theo thứ tự này:

1. Các chính sách tích hợp sẵn (theo thứ tự định nghĩa)
2. Các chính sách tùy chỉnh rõ ràng từ `customPoliciesPath` (theo thứ tự `.add()`)
3. Các chính sách quy ước từ `.failproofai/policies/` dự án (tệp theo thứ tự bảng chữ cái, thứ tự `.add()` bên trong)
4. Các chính sách quy ước từ `~/.failproofai/policies/` người dùng (tệp theo thứ tự bảng chữ cái, thứ tự `.add()` bên trong)

<Note>
  `deny` đầu tiên short-circuits tất cả các chính sách sau. Tất cả các thông báo `instruct` được tích lũy và cung cấp cùng nhau.
</Note>

***

## Các import chuyển tiếp

Các tệp chính sách tùy chỉnh có thể import các mô-đun cục bộ bằng cách sử dụng các đường dẫn tương đối:

```js theme={null}
// 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 import tương đối có thể truy cập từ tệp entry được giải quyết. Điều này được thực hiện bằng cách viết lại các import `from "failproofai"` sang đường dẫn dist thực tế và tạo các tệp `.mjs` tạm thời để đảm bảo khả năng 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:

```js theme={null}
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à các chế độ lỗi

Các chính sách tùy chỉnh là **fail-open**: các lỗi không bao giờ chặn các chính sách tích hợp sẵn hoặc làm crash trình xử lý hook.

| Lỗi                                 | Hành vi                                                                                                 |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `customPoliciesPath` không được đặt | Không có chính sách tùy chỉnh rõ ràng chạy; các chính sách quy ước và tích hợp sẵn tiếp tục bình thường |
| Tệp không tìm thấy                  | Cảnh báo được ghi vào `~/.failproofai/hook.log`; tích hợp sẵn tiếp tục                                  |
| Lỗi cú pháp/import (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/import (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 lỗi khi chạy               | Lỗi được ghi; hook đó được coi là `allow`; các hook khác tiếp tục                                       |
| `fn` mất hơn 10 giây                | Timeout được ghi; được coi là `allow`                                                                   |
| Thư mục quy ước bị thiếu            | Không có chính sách quy ước chạy; không có lỗi                                                          |

<Tip>
  Để 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ý:

  ```bash theme={null}
  tail -f ~/.failproofai/hook.log
  ```
</Tip>

***

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

```js theme={null}
// 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ệp                                                  | Nội dung                                                                                             |
| ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `examples/policies-basic.js`                         | Năm chính sách khởi động bao gồm các chế độ lỗi agent phổ biến                                       |
| `examples/policies-advanced/index.js`                | Các mẫu nâng cao: import chuyển tiếp, lệnh gọi không đồng bộ, loại bỏ đầu ra, và hook kết thúc phiên |
| `examples/convention-policies/security-policies.mjs` | Các chí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.mjs` | Các chính sách quy trình làm việc dựa trên quy ước (nhắc nhở kiểm tra, tệp kiểm tra lưu trữ)         |

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

```bash theme={null}
failproofai policies --install --custom ./examples/policies-basic.js
```

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

```bash theme={null}
# 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 được chọn tự động trên sự kiện hook tiếp theo.
