title: Kiến trúc description: “Cách hook handler, config loading, và policy evaluation hoạt động bên trong” icon: sitemap
Tài liệu này giải thích cách failproofai hoạt động bên trong: cách hệ thống hook chặn các lệnh gọi tool của agent, cách cấu hình được tải và hợp nhất, cách các chính sách được đánh giá, và cách dashboard giám sát hoạt động của agent.Tổng quan
failproofai có hai subsystem độc lập:- Hook handler - Một CLI subprocess nhanh mà Claude Code gọi trên mỗi lệnh gọi tool của agent. Đánh giá các chính sách và trả về một quyết định.
- Agent Monitor (Dashboard) - Một ứng dụng web Next.js để giám sát các session agent và quản lý các chính sách.
~/.failproofai/ và thư mục .failproofai/ của dự án, nhưng chúng chạy dưới dạng các process riêng biệt và chỉ giao tiếp thông qua hệ thống tệp.
Hook handler
Tích hợp với Claude Code
Khi bạn chạyfailproofai policies --install, nó sẽ ghi các mục như thế này vào ~/.claude/settings.json:
failproofai --hook PreToolUse dưới dạng một subprocess trước mỗi lệnh gọi tool, truyền một payload JSON trên stdin.
Định dạng payload
PostToolUse, payload cũng chứa tool_result với kết quả đầu ra của tool.
Handler thực thi giới hạn 1 MB cho stdin. Các payload vượt quá giới hạn này bị loại bỏ và tất cả các chính sách được phép một cách ngầm.
Định dạng phản hồi
Deny (PreToolUse):- Mã thoát:
2 - Lý do được ghi vào stderr (không phải stdout)
- Mã thoát:
0 - Stdout trống
allow(message) cho phép một chính sách gửi context thông tin trở lại Claude ngay cả khi thao tác được cho phép. Hook handler ghi JSON sau đây vào stdout (không phải một tệp cấu hình — đây là phản hồi của handler process đối với Claude Code, giống như các phản hồi deny và instruct ở trên):
- Mã thoát:
0(thao tác được cho phép) - Khi nhiều chính sách trả về
allowvới một thông báo, các thông báo của chúng được nối với ký tự xuống dòng thành một chuỗiadditionalContextduy nhất - Nếu không có chính sách nào cung cấp một thông báo, stdout trống (giống như trước đây)
Processing pipeline
src/hooks/handler.ts triển khai toàn bộ pipeline:
Configuration loading
src/hooks/hooks-config.ts triển khai config loading ba phạm vi.
enabledPolicies- union không trùng lặp trên cả ba tệppolicyParams- mỗi chính sách là một key, tệp đầu tiên xác định nó sẽ giành toàn bộcustomPoliciesPath- tệp đầu tiên xác định nó sẽ giànhllm- tệp đầu tiên xác định nó sẽ giành
readHooksConfig() (chỉ global) để đọc và ghi, vì nó không được gọi với một project cwd.
Policy evaluation
src/hooks/policy-evaluator.ts chạy các chính sách theo thứ tự.
Đối với mỗi chính sách:
- Tìm kiếm schema
paramscủa chính sách (nếu có). - Đọc
policyParams[policy.name]từ config đã hợp nhất. - Hợp nhất các giá trị do người dùng cung cấp trên các giá trị mặc định của schema để tạo ra
ctx.params. - Gọi
policy.fn(ctx)với context đã được giải quyết. - Nếu kết quả là
deny, dừng ngay lập tức và trả về quyết định đó. - Nếu kết quả là
instruct, tích lũy thông báo và tiếp tục. - Nếu kết quả là
allow, tiếp tục đến chính sách tiếp theo.
- Nếu bất kỳ
denynào được trả về, phát ra phản hồi deny. - Nếu bất kỳ kết quả
instructnào được thu thập, phát ra một phản hồi instruct duy nhất với tất cả các thông báo được nối. - Nếu không, phát ra một phản hồi allow (stdout trống, exit 0).
Builtin policies
src/hooks/builtin-policies.ts định nghĩa tất cả 26 chính sách tích hợp dưới dạng các đối tượng BuiltinPolicyDefinition:
params khai báo một PolicyParamsSchema với các kiểu và giá trị mặc định cho mỗi tham số. Policy evaluator tiêm các giá trị đã được giải quyết vào ctx.params trước khi gọi fn. Các hàm chính sách đọc ctx.params mà không cần null-guard vì các giá trị mặc định luôn được áp dụng trước.
Khớp mẫu bên trong các chính sách sử dụng các command token được phân tích cú pháp (argv), không phải khớp chuỗi thô. Điều này ngăn chặn bypass thông qua shell operator injection (ví dụ: một mẫu cho sudo systemctl status * không thể bị bypass bằng cách thêm ; rm -rf / vào command).
Custom policies
src/hooks/custom-hooks-registry.ts triển khai một registry hỗ trợ bởi globalThis:
src/hooks/custom-hooks-loader.ts tải tệp chính sách của người dùng:
- Đọc
customPoliciesPathtừ cấu hình; bỏ qua nếu không có. - Giải quyết đến đường dẫn tuyệt đối; kiểm tra xem tệp có tồn tại.
- Viết lại tất cả các import
from "failproofai"đến đường dẫn dist thực tế đểcustomPoliciesgiải quyết đến cùng một registryglobalThis. - Viết lại đệ quy các import cục bộ chuyển tiếp để đảm bảo khả năng tương thích ESM.
- Ghi các tệp
.mjstạm thời vàimport()tệp entry. - Gọi
getCustomHooks()để truy xuất các hook đã đăng ký. - Dọn sạch tất cả các tệp tạm thời trong một khối
finally.
~/.failproofai/hook.log và loader trả về một mảng trống. Các chính sách tích hợp không bị ảnh hưởng.
Các chính sách tùy chỉnh được đánh giá sau tất cả các chính sách tích hợp. Một chính sách tùy chỉnh deny vẫn short-circuit các chính sách tùy chỉnh tiếp theo (nhưng tất cả các tích hợp đã chạy ở thời điểm này).
Activity logging
Sau mỗi sự kiện hook, handler nối một dòng JSONL vào~/.failproofai/hook-activity.jsonl:
Dashboard architecture
Dashboard là một ứng dụng Next.js 16 sử dụng App Router với React Server Components và Server Actions.- Các trang component gọi
lib/projects.tsvàlib/log-entries.tsđể đọc dữ liệu dự án/session trực tiếp từ hệ thống tệp (không có lớp API cho việc đọc). - Trang Policies sử dụng Server Actions cho tất cả các mutations (toggle, params update, install/remove).
- Session viewer phân tích định dạng transcript JSONL của Claude và hiển thị một timeline của các thông báo và lệnh gọi tool.
- Không có database - tất cả trạng thái persistent nằm trong các tệp thuần túy (
~/.failproofai/,~/.claude/projects/). - Server Actions cho mutations - không cần REST API cho các thao tác CRUD.
- React Server Components cho các trang đọc - tải lần đầu nhanh hơn, không có client bundle cho việc tìm nạp dữ liệu.
- Client components chỉ khi cần tương tác (policy toggles, activity search, log viewer).

