Hooks
Hooks cung cấp một hệ thống mở rộng theo sự kiện để tự động hóa các hành động khi có lệnh hoặc sự kiện từ agent. Hooks được tự động phát hiện từ các thư mục và có thể quản lý qua lệnh CLI, tương tự như cách Skills hoạt động trong OpenClaw.
Làm quen
Hooks là các script nhỏ chạy khi có sự kiện xảy ra. Có hai loại:
- Hooks (trang này): chạy bên trong Gateway khi có sự kiện từ agent, như
/new,/reset,/stop, hoặc các lifecycle events. - Webhooks: các HTTP webhook bên ngoài cho phép hệ thống khác kích hoạt công việc trong OpenClaw. Xem Webhook Hooks hoặc dùng
openclaw webhooksđể xem các lệnh hỗ trợ Gmail.
Hooks cũng có thể được đóng gói bên trong plugins; xem Plugins.
Các trường hợp sử dụng phổ biến:
- Lưu snapshot bộ nhớ khi các bạn reset một session
- Giữ audit trail của các lệnh để troubleshooting hoặc tuân thủ quy định
- Kích hoạt tự động hóa tiếp theo khi session bắt đầu hoặc kết thúc
- Ghi file vào agent workspace hoặc gọi API bên ngoài khi có sự kiện
Nếu các bạn có thể viết một hàm TypeScript nhỏ, các bạn có thể viết hook. Hooks được phát hiện tự động, và các bạn bật hoặc tắt chúng qua CLI.
Tổng quan
Hệ thống hooks cho phép các bạn:
- Lưu context của session vào bộ nhớ khi gọi
/new - Log tất cả lệnh để audit
- Kích hoạt tự động hóa tùy chỉnh trên các sự kiện lifecycle của agent
- Mở rộng hành vi của OpenClaw mà không cần sửa code lõi
Bắt đầu
Bundled Hooks
OpenClaw đi kèm với bốn bundled hooks được tự động phát hiện:
- 💾 session-memory: Lưu context của session vào agent workspace (mặc định
~/.openclaw/workspace/memory/) khi các bạn gọi/new - 📝 command-logger: Log tất cả sự kiện lệnh vào
~/.openclaw/logs/commands.log - 🚀 boot-md: Chạy
BOOT.mdkhi gateway khởi động (yêu cầu bật internal hooks) - 😈 soul-evil: Hoán đổi nội dung
SOUL.mdđược inject vớiSOUL_EVIL.mdtrong cửa sổ purge hoặc ngẫu nhiên
Liệt kê các hooks có sẵn:
openclaw hooks list
Bật một hook:
openclaw hooks enable session-memory
Kiểm tra trạng thái hook:
openclaw hooks check
Xem thông tin chi tiết:
openclaw hooks info session-memory
Onboarding
Trong quá trình onboarding (openclaw onboard), các bạn sẽ được nhắc bật các hooks được khuyên dùng. Wizard tự động phát hiện các hooks đủ điều kiện và hiển thị để chọn.
Hook Discovery
Hooks được tự động phát hiện từ ba thư mục (theo thứ tự ưu tiên):
- Workspace hooks:
<workspace>/hooks/(theo từng agent, ưu tiên cao nhất) - Managed hooks:
~/.openclaw/hooks/(do người dùng cài đặt, dùng chung giữa các workspaces) - Bundled hooks:
<openclaw>/dist/hooks/bundled/(đi kèm với OpenClaw)
Các thư mục managed hook có thể là single hook hoặc hook pack (thư mục package).
Mỗi hook là một thư mục chứa:
my-hook/
├── HOOK.md # Metadata + tài liệu
└── handler.ts # Triển khai handler
Hook Packs (npm/archives)
Hook packs là các npm package chuẩn export một hoặc nhiều hooks qua openclaw.hooks trong package.json. Cài đặt chúng bằng:
openclaw hooks install <path-or-spec>
Ví dụ package.json:
{
"name": "@acme/my-hooks",
"version": "0.1.0",
"openclaw": {
"hooks": ["./hooks/my-hook", "./hooks/other-hook"]
}
}
Mỗi entry trỏ đến một thư mục hook chứa HOOK.md và handler.ts (hoặc index.ts). Hook packs có thể đi kèm dependencies; chúng sẽ được cài đặt dưới ~/.openclaw/hooks/<id>.
Cấu trúc Hook
Định dạng HOOK.md
File HOOK.md chứa metadata trong YAML frontmatter cộng với tài liệu Markdown:
---
name: my-hook
description: "Mô tả ngắn về hook này làm gì"
homepage: https://docs.openclaw.ai/hooks#my-hook
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Tài liệu chi tiết ở đây...
## Nó làm gì
- Lắng nghe lệnh `/new`
- Thực hiện một hành động nào đó
- Log kết quả
## Yêu cầu
- Phải cài đặt Node.js
## Cấu hình
Không cần cấu hình.
Các trường Metadata
Object metadata.openclaw hỗ trợ:
emoji: Emoji hiển thị cho CLI (ví dụ:"💾")events: Mảng các sự kiện để lắng nghe (ví dụ:["command:new", "command:reset"])export: Named export để sử dụng (mặc định là"default")homepage: URL tài liệurequires: Yêu cầu tùy chọnbins: Các binary bắt buộc trên PATH (ví dụ:["git", "node"])anyBins: Ít nhất một trong các binary này phải cóenv: Các biến môi trường bắt buộcconfig: Các đường dẫn config bắt buộc (ví dụ:["workspace.dir"])os: Các nền tảng bắt buộc (ví dụ:["darwin", "linux"])
always: Bỏ qua kiểm tra điều kiện (boolean)install: Phương thức cài đặt (cho bundled hooks:[{"id":"bundled","kind":"bundled"}])
Triển khai Handler
File handler.ts export một hàm HookHandler:
import type { HookHandler } from "../../src/hooks/hooks.js";
const myHandler: HookHandler = async (event) => {
// Chỉ kích hoạt với lệnh 'new'
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] Lệnh New được kích hoạt`);
console.log(` Session: ${event.sessionKey}`);
console.log(` Timestamp: ${event.timestamp.toISOString()}`);
// Logic tùy chỉnh của các bạn ở đây
// Tùy chọn gửi tin nhắn cho người dùng
event.messages.push("✨ Hook của mình đã chạy!");
};
export default myHandler;
Event Context
Mỗi event bao gồm:
{
type: 'command' | 'session' | 'agent' | 'gateway',
action: string, // ví dụ: 'new', 'reset', 'stop'
sessionKey: string, // Định danh session
timestamp: Date, // Khi sự kiện xảy ra
messages: string[], // Push tin nhắn vào đây để gửi cho người dùng
context: {
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // ví dụ: 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig
}
}
Các loại Event
Command Events
Được kích hoạt khi có lệnh agent:
command: Tất cả sự kiện lệnh (listener chung)command:new: Khi gọi lệnh/newcommand:reset: Khi gọi lệnh/resetcommand:stop: Khi gọi lệnh/stop
Agent Events
agent:bootstrap: Trước khi các file bootstrap của workspace được inject (hooks có thể thay đổicontext.bootstrapFiles)
Gateway Events
Được kích hoạt khi gateway khởi động:
gateway:startup: Sau khi channels khởi động và hooks được load
Tool Result Hooks (Plugin API)
Các hooks này không phải là event-stream listeners; chúng cho phép plugins điều chỉnh tool results một cách đồng bộ trước khi OpenClaw lưu chúng.
tool_result_persist: biến đổi tool results trước khi chúng được ghi vào session transcript. Phải đồng bộ; trả về payload tool result đã cập nhật hoặcundefinedđể giữ nguyên. Xem Agent Loop.
Future Events
Các loại event dự kiến:
session:start: Khi một session mới bắt đầusession:end: Khi một session kết thúcagent:error: Khi agent gặp lỗimessage:sent: Khi một tin nhắn được gửimessage:received: Khi một tin nhắn được nhận
Tạo Custom Hooks
1. Chọn vị trí
- Workspace hooks (
<workspace>/hooks/): Theo từng agent, ưu tiên cao nhất - Managed hooks (
~/.openclaw/hooks/): Dùng chung giữa các workspaces
2. Tạo cấu trúc thư mục
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
3. Tạo HOOK.md
---
name: my-hook
description: "Làm điều gì đó hữu ích"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
Hook này làm điều gì đó hữu ích khi các bạn gọi `/new`.
4. Tạo handler.ts
import type { HookHandler } from "../../src/hooks/hooks.js";
const handler: HookHandler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log("[my-hook] Đang chạy!");
// Logic của các bạn ở đây
};
export default handler;
5. Bật và test
# Xác minh hook được phát hiện
openclaw hooks list
# Bật nó
openclaw hooks enable my-hook
# Restart gateway process (restart menu bar app trên macOS, hoặc restart dev process)
# Kích hoạt sự kiện
# Gửi /new qua messaging channel
Cấu hình
Định dạng Config mới (Khuyên dùng)
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}
Cấu hình theo từng Hook
Hooks có thể có cấu hình tùy chỉnh:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": {
"enabled": true,
"env": {
"MY_CUSTOM_VAR": "value"
}
}
}
}
}
}
Extra Directories
Load hooks từ các thư mục bổ sung:
{
"hooks": {
"internal": {
"enabled": true,
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}
Định dạng Config cũ (Vẫn được hỗ trợ)
Định dạng config cũ vẫn hoạt động để tương thích ngược:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}
Migration: Dùng hệ thống discovery mới cho các hooks mới. Legacy handlers được load sau các directory-based hooks.
Lệnh CLI
Liệt kê Hooks
# Liệt kê tất cả hooks
openclaw hooks list
# Chỉ hiển thị hooks đủ điều kiện
openclaw hooks list --eligible
# Output chi tiết (hiển thị yêu cầu còn thiếu)
openclaw hooks list --verbose
# Output JSON
openclaw hooks list --json
Thông tin Hook
# Hiển thị thông tin chi tiết về một hook
openclaw hooks info session-memory
# Output JSON
openclaw hooks info session-memory --json
Kiểm tra điều kiện
# Hiển thị tóm tắt điều kiện
openclaw hooks check
# Output JSON
openclaw hooks check --json
Bật/Tắt
# Bật một hook
openclaw hooks enable session-memory
# Tắt một hook
openclaw hooks disable command-logger
Bundled Hooks
session-memory
Lưu context của session vào bộ nhớ khi các bạn gọi /new.
Events: command:new
Yêu cầu: workspace.dir phải được cấu hình
Output: <workspace>/memory/YYYY-MM-DD-slug.md (mặc định ~/.openclaw/workspace)
Nó làm gì:
- Dùng session entry trước khi reset để tìm transcript đúng
- Trích xuất 15 dòng cuối của cuộc hội thoại
- Dùng LLM để tạo filename slug mô tả
- Lưu metadata của session vào file memory có ngày tháng
Ví dụ output:
# Session: 2026-01-16 14:30:00 UTC
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram
Ví dụ filename:
2026-01-16-vendor-pitch.md2026-01-16-api-design.md2026-01-16-1430.md(fallback timestamp nếu tạo slug thất bại)
Bật:
openclaw hooks enable session-memory
command-logger
Log tất cả sự kiện lệnh vào file audit tập trung.
Events: command
Yêu cầu: Không có
Output: ~/.openclaw/logs/commands.log
Nó làm gì:
- Capture chi tiết sự kiện (command action, timestamp, session key, sender ID, source)
- Append vào file log ở định dạng JSONL
- Chạy im lặng ở background
Ví dụ log entries:
{"timestamp":"2026-01-16T14:30:00.000Z","action":"new","sessionKey":"agent:main:main","senderId":"+1234567890","source":"telegram"}
{"timestamp":"2026-01-16T15:45:22.000Z","action":"stop","sessionKey":"agent:main:main","senderId":"[email protected]","source":"whatsapp"}
Xem logs:
# Xem các lệnh gần đây
tail -n 20 ~/.openclaw/logs/commands.log
# Pretty-print với jq
cat ~/.openclaw/logs/commands.log | jq .
# Lọc theo action
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
Bật:
openclaw hooks enable command-logger
soul-evil
Hoán đổi nội dung SOUL.md được inject với SOUL_EVIL.md trong cửa sổ purge hoặc ngẫu nhiên.
Events: agent:bootstrap
Docs: SOUL Evil Hook
Output: Không ghi file; hoán đổi chỉ xảy ra trong bộ nhớ.
Bật:
openclaw hooks enable soul-evil
Config:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"soul-evil": {
"enabled": true,
"file": "SOUL_EVIL.md",
"chance": 0.1,
"purge": { "at": "21:00", "duration": "15m" }
}
}
}
}
}
boot-md
Chạy BOOT.md khi gateway khởi động (sau khi channels khởi động). Internal hooks phải được bật để hook này chạy.
Events: gateway:startup
Yêu cầu: workspace.dir phải được cấu hình
Nó làm gì:
- Đọc
BOOT.mdtừ workspace của các bạn - Chạy các hướng dẫn qua agent runner
- Gửi bất kỳ tin nhắn outbound nào được yêu cầu qua message tool
Bật:
openclaw hooks enable boot-md
Best Practices
Giữ Handlers nhanh
Hooks chạy trong quá trình xử lý lệnh. Giữ chúng nhẹ:
// ✓ Tốt - async work, trả về ngay lập tức
const handler: HookHandler = async (event) => {
void processInBackground(event); // Fire and forget
};
// ✗ Không tốt - chặn xử lý lệnh
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};
Xử lý lỗi một cách khéo léo
Luôn wrap các thao tác rủi ro:
const handler: HookHandler = async (event) => {
try {
await riskyOperation(event);
} catch (err) {
console.error("[my-handler] Thất bại:", err instanceof Error ? err.message : String(err));
// Không throw - để các handlers khác chạy
}
};
Lọc Events sớm
Return sớm nếu event không liên quan:
const handler: HookHandler = async (event) => {
// Chỉ xử lý lệnh 'new'
if (event.type !== "command" || event.action !== "new") {
return;
}
// Logic của các bạn ở đây
};
Dùng Event Keys cụ thể
Chỉ định các events chính xác trong metadata khi có thể:
metadata: { "openclaw": { "events": ["command:new"] } } # Cụ thể
Thay vì:
metadata: { "openclaw": { "events": ["command"] } } # Chung - overhead nhiều hơn
Debugging
Bật Hook Logging
Gateway log việc load hook khi khởi động:
Registered hook: session-memory -> command:new
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup
Kiểm tra Discovery
Liệt kê tất cả hooks được phát hiện:
openclaw hooks list --verbose
Kiểm tra Registration
Trong handler của các bạn, log khi nó được gọi:
const handler: HookHandler = async (event) => {
console.log("[my-handler] Được kích hoạt:", event.type, event.action);
// Logic của các bạn
};
Xác minh điều kiện
Kiểm tra tại sao một hook không đủ điều kiện:
openclaw hooks info my-hook
Tìm các yêu cầu còn thiếu trong output.
Testing
Gateway Logs
Theo dõi gateway logs để xem hook execution:
# macOS
./scripts/clawlog.sh -f
# Các nền tảng khác
tail -f ~/.openclaw/gateway.log
Test Hooks trực tiếp
Test các handlers của các bạn một cách độc lập:
import { test } from "vitest";
import { createHookEvent } from "./src/hooks/hooks.js";
import myHandler from "./hooks/my-hook/handler.js";
test("my handler hoạt động", async () => {
const event = createHookEvent("command", "new", "test-session", {
foo: "bar",
});
await myHandler(event);
// Assert side effects
});
Kiến trúc
Các thành phần lõi
src/hooks/types.ts: Định nghĩa typesrc/hooks/workspace.ts: Quét và load thư mụcsrc/hooks/frontmatter.ts: Parse metadata HOOK.mdsrc/hooks/config.ts: Kiểm tra điều kiệnsrc/hooks/hooks-status.ts: Báo cáo trạng tháisrc/hooks/loader.ts: Dynamic module loadersrc/cli/hooks-cli.ts: Lệnh CLIsrc/gateway/server-startup.ts: Load hooks khi gateway khởi độngsrc/auto-reply/reply/commands-core.ts: Kích hoạt command events
Discovery Flow
Gateway startup
↓
Quét thư mục (workspace → managed → bundled)
↓
Parse các file HOOK.md
↓
Kiểm tra điều kiện (bins, env, config, os)
↓
Load handlers từ các hooks đủ điều kiện
↓
Đăng ký handlers cho events
Event Flow
User gửi /new
↓
Validation lệnh
↓
Tạo hook event
↓
Kích hoạt hook (tất cả handlers đã đăng ký)
↓
Xử lý lệnh tiếp tục
↓
Session reset
Troubleshooting
Hook không được phát hiện
-
Kiểm tra cấu trúc thư mục:
ls -la ~/.openclaw/hooks/my-hook/ # Phải hiển thị: HOOK.md, handler.ts -
Xác minh định dạng HOOK.md:
cat ~/.openclaw/hooks/my-hook/HOOK.md # Phải có YAML frontmatter với name và metadata -
Liệt kê tất cả hooks được phát hiện:
openclaw hooks list
Hook không đủ điều kiện
Kiểm tra yêu cầu:
openclaw hooks info my-hook
Tìm những thứ còn thiếu:
- Binaries (kiểm tra PATH)
- Biến môi trường
- Giá trị config
- Tương thích OS
Hook không chạy
-
Xác minh hook đã được bật:
openclaw hooks list # Phải hiển thị ✓ bên cạnh các hooks đã bật -
Restart gateway process để hooks reload.
-
Kiểm tra gateway logs để tìm lỗi:
./scripts/clawlog.sh | grep hook
Lỗi Handler
Kiểm tra lỗi TypeScript/import:
# Test import trực tiếp
node -e "import('./path/to/handler.ts').then(console.log)"
Migration Guide
Từ Legacy Config sang Discovery
Trước:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}
Sau:
-
Tạo thư mục hook:
mkdir -p ~/.openclaw/hooks/my-hook mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts -
Tạo HOOK.md:
--- name: my-hook description: "Hook tùy chỉnh của mình" metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } } --- # My Hook Làm điều gì đó hữu ích. -
Cập nhật config:
{ "hooks": { "internal": { "enabled": true, "entries": { "my-hook": { "enabled": true } } } } } -
Xác minh và restart gateway process:
openclaw hooks list # Phải hiển thị: 🎯 my-hook ✓
Lợi ích của migration:
- Tự động discovery
- Quản lý CLI
- Kiểm tra điều kiện
- Tài liệu tốt hơn
- Cấu trúc nhất quán