HOOK.md
do người vận hành cài đặt, phản ứng với các sự kiện lệnh và Gateway như /new,
/reset, /stop, agent:bootstrap hoặc gateway:startup.
Bắt đầu nhanh
Đăng ký các hook có kiểu bằngapi.on(...) từ điểm vào của plugin:
priority giảm dần; các trình xử lý có cùng mức ưu tiên giữ nguyên thứ tự đăng ký.
Các trình xử lý chỉ quan sát chạy song song, còn những lần điều phối quan sát
không chờ kết quả có thể chồng lấn với các sự kiện tiếp theo. Không dùng mức ưu tiên để sắp xếp
các tác dụng phụ của hoạt động quan sát.
api.on(name, handler, opts?) chấp nhận:
Người vận hành có thể đặt ngân sách hook mà không cần sửa mã plugin:
hooks.timeouts.<hookName> ghi đè hooks.timeoutMs, còn giá trị này ghi đè giá trị
api.on(..., { timeoutMs }) do tác giả plugin đặt. Mỗi giá trị phải là một
số nguyên dương không quá 600000 ms. Ưu tiên ghi đè theo từng hook đối với các
hook được biết là chậm để một plugin không nhận ngân sách dài hơn ở mọi nơi.
Promise của trình xử lý đã hết thời gian vẫn tiếp tục chạy vì callback hook không
nhận tín hiệu hủy. Quá trình điều phối hook có thể giải phóng quyền tiếp nhận của Gateway
trong khi công việc của plugin đó vẫn đang diễn ra. Các plugin sở hữu
công việc chạy dài phải tự cung cấp vòng đời hủy và tắt.
Các hook sửa đổi đầu ra message_sending và reply_payload_sending dùng thời gian mặc định
15 giây cho mỗi trình xử lý. Nếu một trình xử lý hết thời gian, OpenClaw ghi nhật ký lỗi plugin
và tiếp tục với payload mới nhất để làn phân phối tuần tự có thể
hoàn tất. Hãy đặt ngân sách theo hook lớn hơn cho những plugin chủ ý thực hiện công việc
chậm hơn trước khi phân phối.
Các plugin kênh dùng createReplyDispatcher cũng có thể khai báo ngân sách dương
lớn hơn cho mỗi giai đoạn bằng beforeDeliverOptions: { timeoutMs }, hoặc khi
nối thêm công việc bằng dispatcher.appendBeforeDeliver(handler, { timeoutMs }).
Nếu chủ sở hữu không khai báo ngân sách, các callback đó dùng cùng giá trị mặc định
15 giây để một callback bị treo không thể giữ làn phân phối tuần tự.
Mỗi hook nhận event.context.pluginConfig, tức cấu hình đã phân giải cho
plugin đã đăng ký trình xử lý đó. OpenClaw chèn cấu hình này theo từng trình xử lý mà không
làm thay đổi đối tượng sự kiện dùng chung mà các plugin khác nhìn thấy.
Danh mục hook
Các hook được nhóm theo bề mặt mà chúng mở rộng. Tên in đậm chấp nhận kết quả quyết định (chặn, hủy, ghi đè hoặc yêu cầu phê duyệt); các hook còn lại chỉ dùng để quan sát. Lượt tác tử
Quan sát cuộc hội thoại
Công cụ
Tin nhắn và phân phối
Phiên và Compaction
Đối với các lệnh gọi
sessions.create có parentSessionKey và emitCommandHooks: true, một tiến trình con riêng biệt luôn nhận session_start. Bên gọi khai báo liệu tiến trình cha cũng nhận session_end kết thúc bằng succeedsParent hay không: true nghĩa là tiến trình kế nhiệm, false nghĩa là tiến trình con song song. Việc bỏ qua duy trì hành vi chuyển tiếp tiến trình cha kiểu cũ. Các hook command:new và before_reset vẫn mô tả hành động /new được yêu cầu trong cả hai trường hợp.
Tác tử con
subagent_spawned/subagent_ended- theo dõi việc khởi chạy và hoàn tất subagent.subagent_delivery_target- hook tương thích để chuyển thông báo hoàn tất khi không có liên kết phiên lõi nào có thể ánh xạ một tuyến.subagent_spawning- hook tương thích đã ngừng dùng. Lõi hiện chuẩn bị các liên kết subagentthread: truethông qua bộ điều hợp liên kết phiên của kênh trước khisubagent_spawnedkích hoạt.subagent_spawnedbao gồmresolvedModelvàresolvedProviderkhi OpenClaw đã phân giải mô hình gốc của phiên con trước khi khởi chạy.subagent_endedmang theotargetSessionKey(danh tính - khớp vớisubagent_spawned.childSessionKey),targetKind("subagent"hoặc"acp"),reason,outcometùy chọn ("ok","error","timeout","killed","reset"hoặc"deleted"),errortùy chọn,runId,endedAt,accountIdvàsendFarewell. Nó không bao gồmagentIdhoặcchildSessionKey; hãy dùngtargetSessionKeyđể đối chiếu với sự kiệnsubagent_spawnedtương ứng.
Yêu cầu ghép cặp kênh
Dùngchannel_pairing_requested khi một plugin cần thông báo cho người vận hành hoặc
ghi bản ghi kiểm toán sau khi người gửi DM chưa được ghép cặp tạo một yêu cầu ghép cặp
đang chờ xử lý. Hook được điều phối khi yêu cầu được tạo; việc kênh chuyển
phản hồi ghép cặp không bị trì hoãn bởi các trình xử lý hook chậm hoặc gặp lỗi.
accountId tùy chọn,
senderId theo phạm vi kênh, code ghép cặp và siêu dữ liệu kênh. Hãy coi
mã ghép cặp là thông tin xác thực phê duyệt dùng một lần đang còn hiệu lực và chỉ chuyển mã đó đến một
đích nhận của người vận hành đáng tin cậy. Hãy coi metadata là văn bản danh tính
không đáng tin cậy do người gửi cung cấp. Hook không bao gồm nội dung hoặc phương tiện của tin nhắn đến.
Hook gỡ lỗi runtime
Dùngbefore_model_resolve để chuyển nhà cung cấp hoặc mô hình cho một lượt của agent - hook này
chạy trước khi phân giải mô hình. llm_output chỉ chạy sau khi một lần thử mô hình
tạo ra đầu ra của trợ lý.
Để xác minh mô hình phiên thực tế, hãy kiểm tra các đăng ký runtime, sau đó
dùng openclaw sessions hoặc các bề mặt phiên/trạng thái của Gateway. Để gỡ lỗi
payload của nhà cung cấp, hãy khởi động Gateway với --raw-stream và
--raw-stream-path <path> để ghi các sự kiện luồng mô hình thô vào một tệp jsonl.
Chính sách gọi công cụ
before_tool_call nhận:
event.toolNameevent.paramsevent.toolKindvàevent.toolInputKindtùy chọn, các bộ phân biệt có thẩm quyền từ máy chủ dành cho những công cụ cố ý dùng chung tên; ví dụ, các lệnh gọiexeccủa chế độ mã bên ngoài dùngtoolKind: "code_mode_exec"và bao gồmtoolInputKind: "javascript" | "typescript"khi ngôn ngữ đầu vào đã được xác địnhevent.derivedPathstùy chọn, các gợi ý đường dẫn đích được máy chủ suy ra theo nguyên tắc nỗ lực tối đa cho các phong bì công cụ phổ biến nhưapply_patch; các đường dẫn này có thể không đầy đủ hoặc ước lượng rộng hơn những gì công cụ thực sự sẽ tác động (ví dụ, với đầu vào không hợp lệ hoặc chỉ có một phần)event.runIdtùy chọnevent.toolCallIdtùy chọn- các trường ngữ cảnh như
ctx.agentId,ctx.sessionKey,ctx.sessionId,ctx.runId,ctx.toolKind,ctx.toolInputKindvàctx.tracechẩn đoán ctx.requestertùy chọn, bên yêu cầu do máy chủ suy ra đã khởi tạo lần chạy tin nhắn hiện tại. Nó có thể bao gồmchannel,accountId,senderId,senderIsOwnervàroleIdsgốc của nhà cung cấp. Các trường bị thiếu là chưa được chứng minh, không phải sự bảo đảm rằng giá trị là sai; hãy từ chối theo mặc định khi chính sách yêu cầu các trường đó.
block: truelà trạng thái kết thúc và bỏ qua các trình xử lý có mức ưu tiên thấp hơn.block: falseđược coi là không có quyết định.paramsviết lại các tham số công cụ để thực thi.requireApprovaltạm dừng lần chạy agent và hỏi người dùng thông qua cơ chế phê duyệt của plugin./approvecó thể phê duyệt cả phê duyệt exec và plugin. Trong các relayPreToolUsegốc ở chế độ báo cáo của app-server Codex, thao tác này chuyển quyền xử lý cho yêu cầu phê duyệt app-server tương ứng; xem runtime bộ kiểm thử Codex.- Một
block: truecó mức ưu tiên thấp hơn vẫn có thể chặn sau khi hook có mức ưu tiên cao hơn yêu cầu phê duyệt. onResolutionnhận quyết định đã được phân giải:allow-once,allow-always,deny,timeouthoặccancelled.
Chính sách nhận biết người gửi trong một tệp
Một tệp plugin độc lập có thể giữ chính sách dành riêng cho việc triển khai trong mã thay vì thêm một schema cấu hình khác. Ví dụ này cấp cho chủ sở hữu mọi công cụ, cho phép các bảo trì viên đã cấu hình dùng một tập công cụ và hành động tin nhắn thận trọng, đồng thời cung cấp/fix cho những người gửi đã được cấu hình kênh cấp quyền:
AGENT_ID phải đặt tên cho agent được liên kết với cuộc hội thoại bảo trì.
Liên kết chọn agent đó cho các tin nhắn thông thường và /fix; tệp độc lập
vẫn là chủ sở hữu duy nhất của chính sách công cụ phân biệt chủ sở hữu với bảo trì viên.
requireAuth: true tái sử dụng cơ chế tiếp nhận người gửi hiện có của từng kênh. Đối với
Discord, danh sách cho phép users/roles của máy chủ hoặc kênh có thể cấp quyền cho
đối tượng bảo trì. Các kênh khác có thể dùng id người gửi ổn định. Sau đó, hook
áp dụng quyết định chi tiết hơn theo từng công cụ cho mọi lệnh gọi công cụ trong lần chạy, bao gồm
các lệnh gọi PreToolUse gốc của Codex. Nó có thể phủ quyết một công cụ mà mô hình nhìn thấy, nhưng không thể
thêm công cụ bị máy chủ lược bỏ. Các chính sách hiện có về sandbox, phê duyệt exec, công cụ lõi
chỉ dành cho chủ sở hữu và kênh vẫn được áp dụng; hook không thể vượt qua các chính sách đó để cấp quyền.
Hãy giới hạn id người gửi và vai trò trong một cặp kênh/tài khoản chính xác như minh họa; cả hai đều là
không gian tên cục bộ của nhà cung cấp. Duy trì danh sách cho phép một cách thận trọng. Chỉ thêm các công cụ
ghi hoặc thực thi khi chính sách sandbox và phê duyệt của việc triển khai bảo đảm an toàn.
Đối với các lần chạy tự động hoặc hệ thống, hãy quyết định rõ liệu việc thiếu
ctx.requester có được phép tiếp tục hay không; ví dụ này từ chối trường hợp đó đối với agent có phạm vi áp dụng.
Xem Yêu cầu quyền của plugin để biết
cách định tuyến phê duyệt, hành vi quyết định và khi nào nên dùng requireApproval thay
cho công cụ tùy chọn hoặc phê duyệt exec.
Các plugin cần chính sách cấp máy chủ có thể đăng ký chính sách công cụ đáng tin cậy bằng
api.registerTrustedToolPolicy(...). Các chính sách này chạy trước các hook
before_tool_call thông thường và trước các quyết định hook thông thường. Các chính sách đáng tin cậy
được đóng gói chạy trước; các chính sách đáng tin cậy của plugin đã cài đặt chạy tiếp theo thứ tự tải
plugin; các hook before_tool_call thông thường chạy sau chúng. Các plugin được đóng gói giữ
đường dẫn chính sách đáng tin cậy hiện có. Các plugin đã cài đặt phải được bật rõ ràng
và khai báo mọi id chính sách trong contracts.trustedToolPolicies; các id chưa khai báo
bị từ chối trước khi đăng ký. Id chính sách được giới hạn trong phạm vi plugin đăng ký,
vì vậy các plugin khác nhau có thể tái sử dụng cùng một id cục bộ. Chỉ dùng tầng này
cho các cổng kiểm soát được máy chủ tin cậy như chính sách workspace, thực thi ngân sách hoặc
an toàn của quy trình công việc dành riêng.
Hook môi trường exec
resolve_exec_env cho phép các plugin bổ sung biến môi trường vào các lần gọi công cụ exec
trước khi lệnh chạy. Hook này nhận:
event.sessionKeyevent.toolName, hiện luôn là"exec"event.host, một trong"gateway","sandbox"hoặc"node"- các trường ngữ cảnh như
ctx.agentId,ctx.sessionKey,ctx.messageProvidervàctx.channelId
Record<string, string> để hợp nhất vào môi trường exec. Các trình xử lý
chạy theo thứ tự ưu tiên; với cùng một khóa, kết quả sau sẽ ghi đè kết quả
trước.
Đầu ra của hook được lọc qua chính sách khóa môi trường exec của máy chủ trước khi
hợp nhất. PATH luôn bị loại bỏ (việc phân giải lệnh và kiểm tra tệp nhị phân an toàn
phụ thuộc vào biến này). Các khóa không hợp lệ và khóa ghi đè máy chủ nguy hiểm như LD_*,
DYLD_*, NODE_OPTIONS, các biến proxy (HTTP_PROXY, HTTPS_PROXY,
ALL_PROXY, NO_PROXY) và các biến ghi đè TLS (NODE_TLS_REJECT_UNAUTHORIZED,
SSL_CERT_FILE và tương tự) đều bị loại bỏ. Môi trường plugin đã lọc được đưa vào
siêu dữ liệu phê duyệt/kiểm toán của Gateway và chuyển tiếp đến các yêu cầu thực thi
trên máy chủ Node.
Lưu trữ lâu dài kết quả công cụ
Kết quả công cụ có thể bao gồmdetails có cấu trúc để kết xuất giao diện người dùng, chẩn đoán,
định tuyến phương tiện hoặc siêu dữ liệu do plugin sở hữu. Xem details là siêu dữ liệu thời gian chạy,
không phải nội dung prompt:
- OpenClaw loại bỏ
toolResult.detailstrước khi phát lại cho nhà cung cấp và đưa vào dữ liệu Compaction để siêu dữ liệu không trở thành ngữ cảnh mô hình. - Các mục phiên được lưu trữ chỉ giữ lại
detailscó giới hạn. Chi tiết quá lớn được thay thế bằng bản tóm tắt ngắn gọn vàpersistedDetailsTruncated: true. tool_result_persistvàbefore_message_writechạy trước giới hạn lưu trữ cuối cùng. Giữdetailsđược trả về ở kích thước nhỏ và tránh đặt văn bản liên quan đến prompt chỉ trongdetails; hãy đặt đầu ra công cụ mà mô hình có thể thấy trongcontent.
Hook prompt và mô hình
Sử dụng các hook theo từng giai đoạn cho plugin mới:before_model_resolve: chỉ nhận prompt hiện tại và siêu dữ liệu tệp đính kèm. Trả vềproviderOverridehoặcmodelOverride.agent_turn_prepare: nhận prompt hiện tại, các thông điệp phiên đã chuẩn bị và mọi nội dung chèn chỉ-một-lần trong hàng đợi đã được lấy ra cho phiên này. Trả vềprependContexthoặcappendContext.before_prompt_build: nhận prompt hiện tại và các thông điệp phiên. Trả vềprependContext,appendContext,systemPrompt,prependSystemContexthoặcappendSystemContext.heartbeat_prompt_contribution: chỉ chạy cho các lượt Heartbeat và trả vềprependContexthoặcappendContext. Dành cho các trình giám sát nền cần tóm tắt trạng thái hiện tại mà không thay đổi các lượt do người dùng khởi tạo.
before_agent_run chạy sau khi xây dựng prompt và trước mọi đầu vào mô hình,
bao gồm việc tải hình ảnh cục bộ của prompt và quan sát llm_input. Hook này nhận
đầu vào người dùng hiện tại dưới dạng prompt, cùng lịch sử phiên đã tải trong messages
và prompt hệ thống đang hoạt động. Trả về { outcome: "block", reason, message? }
để dừng lượt chạy trước khi mô hình đọc prompt. reason là nội bộ;
message là nội dung thay thế dành cho người dùng. Chỉ hỗ trợ kết quả pass và block;
các dạng quyết định không được hỗ trợ sẽ đóng theo hướng an toàn.
Khi một lượt chạy bị chặn, OpenClaw chỉ lưu văn bản thay thế trong
message.content cùng siêu dữ liệu chặn không nhạy cảm như mã định danh
plugin chặn và dấu thời gian. Văn bản gốc của người dùng không được giữ lại trong bản chép lời
hoặc ngữ cảnh tương lai. Các lý do chặn nội bộ được xem là nhạy cảm và
bị loại khỏi tải trọng bản chép lời, lịch sử, phát rộng, nhật ký và chẩn đoán.
Khả năng quan sát nên sử dụng các trường đã làm sạch như mã định danh trình chặn, kết quả,
dấu thời gian hoặc một danh mục an toàn.
Các hook lượt tác nhân, bao gồm agent_end, có event.runId khi OpenClaw có thể
xác định lượt chạy đang hoạt động; cùng giá trị này cũng có trên ctx.runId. Các lượt chạy do Cron điều khiển
cũng cung cấp ctx.jobId (mã định danh tác vụ cron khởi nguồn) trong ngữ cảnh lượt tác nhân
để hook có thể giới hạn phạm vi số liệu, hiệu ứng phụ hoặc trạng thái vào một
tác vụ đã lên lịch cụ thể. ctx.jobId không thuộc ngữ cảnh công cụ before_tool_call.
Đối với các lượt bắt nguồn từ kênh, ctx.channel và ctx.messageProvider xác định
bề mặt nhà cung cấp như discord hoặc telegram, còn ctx.channelId là
mã định danh đích hội thoại khi OpenClaw có thể suy ra từ khóa phiên
hoặc siêu dữ liệu phân phối.
Khi có danh tính người gửi, ngữ cảnh hook tác nhân cũng bao gồm:
ctx.senderId- mã định danh người gửi trong phạm vi kênh (ví dụ:open_idcủa Feishu, mã định danh người dùng Discord). Được điền khi lượt chạy bắt nguồn từ thông điệp của người dùng có siêu dữ liệu người gửi đã biết.ctx.chatId- mã định danh hội thoại nguyên bản của tầng vận chuyển (ví dụ:chat_idcủa Feishu,chat_idcủa Telegram). Được điền khi kênh khởi nguồn cung cấp mã định danh hội thoại nguyên bản.ctx.channelContext.sender.id- cùng mã định danh người gửi vớictx.senderId, nằm trong một đối tượng do kênh sở hữu mà plugin có thể mở rộng bằng các trường dành riêng cho kênh.ctx.channelContext.chat.id- cùng mã định danh hội thoại vớictx.chatId, nằm trong một đối tượng do kênh sở hữu mà plugin có thể mở rộng bằng các trường dành riêng cho kênh.
id lồng nhau. Plugin kênh chuyển tiếp siêu dữ liệu
người gửi hoặc cuộc trò chuyện phong phú hơn qua trình trợ giúp đầu vào có thể bổ sung
PluginHookChannelSenderContext hoặc PluginHookChannelChatContext từ
openclaw/plugin-sdk/channel-inbound:
ctx.senderExternalId vẫn được giữ dưới dạng trường tương thích mã nguồn đã lỗi thời cho
các plugin cũ. Core không điền trường này; danh tính người gửi mới dành riêng cho kênh
nên nằm trong ctx.channelContext.sender thông qua phần
bổ sung mô-đun.
agent_end là một hook quan sát. Các đường dẫn Gateway và harness lưu trữ lâu dài chạy
hook này theo kiểu kích hoạt rồi bỏ qua sau lượt, còn các đường dẫn CLI dùng một lần, tồn tại ngắn sẽ chờ
promise của hook trước khi dọn dẹp tiến trình để các plugin đáng tin cậy có thể đẩy hết
dữ liệu quan sát đầu cuối hoặc chụp trạng thái. Trình chạy hook áp dụng thời gian chờ 30 giây
để một plugin bị treo hoặc điểm cuối nhúng không thể khiến promise của hook
chờ mãi mãi. Sự kiện hết thời gian chờ được ghi nhật ký và OpenClaw tiếp tục; hệ thống không
hủy công việc mạng do plugin sở hữu trừ khi plugin cũng sử dụng tín hiệu hủy
riêng.
Sử dụng model_call_started và model_call_ended cho dữ liệu đo từ xa của lệnh gọi nhà cung cấp
không được nhận prompt thô, lịch sử, phản hồi, tiêu đề, nội dung
yêu cầu hoặc mã định danh yêu cầu của nhà cung cấp. Các hook này bao gồm siêu dữ liệu ổn định như
runId, callId, provider, model, api/transport tùy chọn, trạng thái cuối
durationMs/outcome và upstreamRequestIdHash khi OpenClaw có thể suy ra một
hàm băm mã định danh yêu cầu của nhà cung cấp có giới hạn. Khi thời gian chạy đã phân giải
siêu dữ liệu cửa sổ ngữ cảnh, sự kiện và ngữ cảnh hook cũng bao gồm
contextTokenBudget, ngân sách token hiệu dụng sau các giới hạn của mô hình/cấu hình/tác nhân,
cùng contextWindowSource và contextWindowReferenceTokens khi một
giới hạn thấp hơn được áp dụng.
before_agent_finalize chỉ chạy khi một harness sắp chấp nhận câu trả lời tự nhiên
cuối cùng của trợ lý. Đây không phải đường dẫn hủy /stop và không
chạy khi người dùng hủy một lượt. Trả về { action: "revise", reason } để yêu cầu
harness thực hiện thêm một lượt mô hình trước khi hoàn tất, { action: "finalize", reason? } để buộc hoàn tất hoặc bỏ qua kết quả để tiếp tục.
Các trình xử lý có ngân sách mặc định là 15 giây; khi hết thời gian chờ, OpenClaw ghi nhật ký lỗi và
tiếp tục với câu trả lời cuối cùng ban đầu.
Các hook Stop nguyên bản của Codex được chuyển tiếp vào hook này dưới dạng các quyết định
before_agent_finalize của OpenClaw.
Khi trả về action: "revise", plugin có thể bao gồm siêu dữ liệu retry để
đảm bảo lượt mô hình bổ sung có giới hạn và an toàn khi phát lại:
instruction được nối vào lý do sửa đổi gửi đến harness.
idempotencyKey cho phép máy chủ đếm số lần thử lại cho cùng một yêu cầu plugin
trên các quyết định hoàn tất tương đương, còn maxAttempts giới hạn số lượt bổ sung
mà máy chủ cho phép trước khi tiếp tục với câu trả lời cuối cùng tự nhiên.
Các plugin không đi kèm cần hook hội thoại thô (before_model_resolve,
before_agent_reply, llm_input, llm_output, before_agent_finalize,
agent_end hoặc before_agent_run) phải đặt:
plugins.entries.<id>.hooks.allowPromptInjection=false.
Phần mở rộng phiên và nội dung chèn cho lượt tiếp theo
Plugin quy trình làm việc có thể lưu trữ trạng thái phiên nhỏ, tương thích JSON bằngapi.session.state.registerSessionExtension(...) và cập nhật trạng thái đó thông qua
phương thức Gateway sessions.pluginPatch. Các hàng phiên chiếu trạng thái phần mở rộng
đã đăng ký qua pluginExtensions, cho phép Control UI và các
máy khách khác kết xuất trạng thái do plugin sở hữu mà không cần biết chi tiết nội bộ của plugin.
api.registerSessionExtension(...) vẫn hoạt động nhưng đã lỗi thời; nên dùng
không gian tên api.session.state.
Sử dụng api.session.workflow.enqueueNextTurnInjection(...) khi plugin cần
ngữ cảnh bền vững đến đúng một lần trong lượt mô hình tiếp theo (api.enqueueNextTurnInjection(...)
cấp cao nhất là bí danh đã lỗi thời nhưng có cùng hành vi). OpenClaw lấy các nội dung chèn
trong hàng đợi ra trước hook prompt, loại bỏ nội dung chèn hết hạn và loại bỏ trùng lặp theo
idempotencyKey cho từng plugin. Đây là điểm nối phù hợp cho việc tiếp tục sau phê duyệt,
tóm tắt chính sách, phần thay đổi của trình giám sát nền và phần tiếp nối lệnh cần hiển thị
cho mô hình ở lượt tiếp theo nhưng không được trở thành văn bản prompt hệ thống vĩnh viễn.
Ngữ nghĩa dọn dẹp là một phần của hợp đồng. Các lệnh gọi lại dọn dẹp phần mở rộng phiên và
vòng đời thời gian chạy nhận reset, delete, disable hoặc
restart. Máy chủ xóa trạng thái phần mở rộng phiên lưu trữ lâu dài
và các nội dung chèn đang chờ cho lượt tiếp theo của plugin sở hữu khi đặt lại/xóa/vô hiệu hóa; khi khởi động lại,
trạng thái phiên bền vững được giữ nguyên, còn các lệnh gọi lại dọn dẹp cho phép plugin giải phóng
tác vụ của bộ lập lịch, ngữ cảnh chạy và các tài nguyên ngoài luồng khác của thế hệ
thời gian chạy cũ.
Hook thông điệp
Sử dụng hook thông điệp cho chính sách định tuyến và phân phối cấp kênh:message_received: quan sát nội dung đầu vào, người gửi,threadId,messageId,senderId, tương quan lượt chạy/phiên tùy chọn và siêu dữ liệu.message_sending: viết lạicontenthoặc trả về{ cancel: true }.reply_payload_sending: viết lại các đối tượngReplyPayloadđã chuẩn hóa (bao gồmpresentation,delivery, tham chiếu phương tiện và văn bản) hoặc trả về{ cancel: true }.message_sent: quan sát trạng thái thành công hoặc thất bại cuối cùng.
content có thể chứa bản chép lời nói
ẩn ngay cả khi tải trọng kênh không có văn bản/chú thích hiển thị.
Việc viết lại content đó chỉ cập nhật bản chép lời mà hook có thể thấy; nội dung này không được
kết xuất dưới dạng chú thích phương tiện.
Các sự kiện reply_payload_sending có thể bao gồm usageState, một ảnh chụp nhanh trực tiếp,
theo từng lượt và theo nỗ lực tốt nhất về mô hình/mức sử dụng/ngữ cảnh. Hoạt động phân phối bền vững, phát lại đã khôi phục và
các phản hồi không có tương quan lượt chạy chính xác sẽ không bao gồm trường này.
Ngữ cảnh hook thông báo cung cấp các trường tương quan ổn định khi có sẵn:
ctx.sessionKey, ctx.runId, ctx.messageId, ctx.senderId, ctx.trace,
ctx.traceId, ctx.spanId, ctx.parentSpanId và ctx.callDepth. Ngữ cảnh gửi đến
và before_dispatch cũng cung cấp siêu dữ liệu phản hồi khi kênh
có dữ liệu thông báo được trích dẫn đã lọc theo phạm vi hiển thị: replyToId, replyToIdFull,
replyToBody, replyToSender và replyToIsQuote. Ưu tiên các trường
hạng nhất này trước khi đọc siêu dữ liệu cũ.
Ưu tiên các trường threadId và replyToId có kiểu trước khi sử dụng siêu dữ liệu
dành riêng cho kênh.
Quy tắc quyết định:
message_sendingvớicancel: truelà trạng thái kết thúc.message_sendingvớicancel: falseđược coi là không có quyết định.contentđã được viết lại tiếp tục đến các hook có mức ưu tiên thấp hơn, trừ khi một hook sau đó hủy việc phân phối.reply_payload_sendingchạy sau khi chuẩn hóa tải trọng và trước khi phân phối qua kênh, bao gồm cả các phản hồi được định tuyến trở lại kênh ban đầu. Các trình xử lý chạy tuần tự và mỗi trình xử lý thấy tải trọng mới nhất do các trình xử lý có mức ưu tiên cao hơn tạo ra.- Tải trọng
reply_payload_sendingkhông cung cấp các dấu hiệu tin cậy khi chạy nhưtrustedLocalMedia; plugin có thể chỉnh sửa cấu trúc tải trọng nhưng không thể cấp quyền tin cậy cho phương tiện cục bộ. message_sendingcó thể trả vềcancelReasonvàmetadatacó giới hạn cùng với thao tác hủy. Các API vòng đời thông báo mới cung cấp điều này dưới dạng kết quả phân phối bị chặn với lý docancelled_by_message_sending_hook; cơ chế phân phối trực tiếp cũ vẫn trả về một mảng kết quả rỗng để đảm bảo khả năng tương thích.message_sentchỉ dùng để quan sát. Lỗi trình xử lý được ghi nhật ký và không thay đổi kết quả phân phối.
Cài đặt hook
Sử dụngsecurity.installPolicy cho các quyết định cho phép/chặn do người vận hành sở hữu. Chính sách đó
chạy từ cấu hình OpenClaw, áp dụng cho các đường dẫn cài đặt và cập nhật CLI, đồng thời
từ chối theo mặc định khi được bật nhưng không khả dụng.
before_install là một hook vòng đời của môi trường chạy plugin. Hook này chạy sau
security.installPolicy chỉ trong tiến trình OpenClaw nơi các hook plugin
đã được tải, chẳng hạn như các luồng cài đặt dựa trên Gateway. Hook này hữu ích cho
các hoạt động quan sát, cảnh báo và kiểm tra khả năng tương thích do plugin sở hữu, nhưng không phải là
ranh giới bảo mật chính của doanh nghiệp hoặc máy chủ đối với việc cài đặt. Trường
builtinScan vẫn nằm trong tải trọng sự kiện để đảm bảo khả năng tương thích, nhưng
OpenClaw không còn chạy cơ chế chặn mã nguy hiểm tích hợp sẵn tại thời điểm cài đặt, vì vậy đây
là một kết quả ok rỗng. Trả về các phát hiện bổ sung hoặc
{ block: true, blockReason } để dừng quá trình cài đặt trong tiến trình đó.
block: true là trạng thái kết thúc. block: false được coi là không có quyết định. Lỗi trình xử lý
chặn quá trình cài đặt theo cơ chế từ chối mặc định.
Vòng đời Gateway
Sử dụnggateway_start để khởi động các dịch vụ plugin chung và gateway_stop để
dọn dẹp các tài nguyên chạy lâu dài. Bộ lập lịch cron có thể vẫn đang tải khi
gateway_start chạy, vì vậy không sử dụng hook này làm tín hiệu cơ sở cho phép chiếu
cron bên ngoài.
Không dựa vào hook nội bộ gateway:startup cho các dịch vụ khi chạy
do plugin sở hữu.
cron_reconciled được kích hoạt sau khi bộ lập lịch cron của Gateway và các trình theo dõi
khi thoát đã đối soát trạng thái bền vững của chúng. Hook này được kích hoạt cho cả lần
khởi động ban đầu và khi thay thế bộ lập lịch trong quá trình tải lại cấu hình. Sự kiện báo cáo
reason (startup hoặc reload) và trạng thái enabled có hiệu lực. Cron bị tắt
vẫn phát sự kiện với enabled: false, cho phép một phép chiếu bên ngoài
xóa các lần đánh thức cũ. Sử dụng ctx.getCron?.() cho đúng phiên bản bộ lập lịch đã
hoàn tất đối soát; lần tải lại sau đó không chuyển đích gọi lại đó.
ctx.abortSignal sở hữu cùng ảnh chụp nhanh bộ lập lịch đó. Gateway hủy tín hiệu này ngay
khi một bộ lập lịch mới hơn được kích hoạt hoặc quá trình tắt bắt đầu. Truyền tín hiệu này qua mọi
tác dụng phụ bền vững và không chấp nhận ảnh chụp nhanh sau khi tín hiệu bị hủy.
Đây là tín hiệu vòng đời bộ lập lịch, không phải tín hiệu kích hoạt plugin:
việc tải lại nóng chỉ dành cho plugin không phát lại tín hiệu này. Một trình tiêu thụ mới được bật nhận
đường cơ sở đầu tiên khi bộ lập lịch được thay thế lần tiếp theo hoặc khi Gateway khởi động.
Giống như các hook quan sát khác, các lệnh gọi lại gateway_start và cron_reconciled
có thể chồng lấn. Nếu cả hai trình xử lý dùng chung quá trình khởi tạo plugin, hãy phối hợp chúng
bằng một promise sẵn sàng cục bộ của plugin thay vì phụ thuộc vào thứ tự gọi lại.
cron_changed được kích hoạt cho các sự kiện vòng đời cron do Gateway sở hữu với tải trọng
sự kiện có kiểu bao gồm các lý do added, updated, removed, started, finished
và scheduled. Sự kiện mang theo một ảnh chụp nhanh PluginHookGatewayCronJob
(bao gồm state.nextRunAtMs, state.lastRunStatus và
state.lastError khi có) cùng với một PluginHookGatewayCronDeliveryStatus
thuộc not-requested | delivered | not-delivered | unknown. Các sự kiện đã xóa
diễn ra sau khi cam kết: chúng chỉ được kích hoạt sau khi xóa bền vững thành công và vẫn mang theo
ảnh chụp nhanh tác vụ đã xóa để các bộ lập lịch bên ngoài có thể đối soát trạng thái.
Sự kiện scheduled diễn ra sau khi cam kết: sự kiện này chỉ được kích hoạt sau khi một thao tác ghi bền vững
thành công thay đổi nextRunAtMs có hiệu lực của một tác vụ hiện có, không bao gồm sự kiện vòng đời
added, updated hoặc removed tường minh của tác vụ đó. event.nextRunAtMs
cấp cao nhất là lần đánh thức tiếp theo đã được cam kết; khi không có trường này, tác vụ
không có lần đánh thức tiếp theo. Hãy xem các sự kiện này là gợi ý đối soát, không phải nhật ký
chênh lệch có thứ tự. Sử dụng chúng làm các gợi ý có thể hợp nhất để đọc lại bộ lập lịch được
cron_reconciled ghi nhận gần nhất; không tiếp nhận bộ lập lịch từ ngữ cảnh cron_changed.
Giữ OpenClaw làm nguồn dữ liệu chính xác cho việc kiểm tra đến hạn và thực thi.
Phép chiếu cron bên ngoài an toàn
Chiếu một ảnh chụp nhanh đánh thức hoàn chỉnh thay vì chuyển tiếp các chênh lệch sự kiện cron. Thao tácreplaceAll của bộ điều hợp bên ngoài phải có tính nguyên tử và lũy đẳng, đồng thời
chỉ được hoàn tất sau khi máy chủ đã chấp nhận ảnh chụp nhanh một cách bền vững. Thao tác này
cũng phải tuân thủ tín hiệu hủy được cung cấp: nếu tín hiệu bị hủy trước khi
chấp nhận bền vững, bộ điều hợp không được chấp nhận ảnh chụp nhanh đó.
Mẫu này chỉ duy trì một worker trạng thái mới nhất đang hoạt động. Chỉ cron_reconciled
tiếp nhận một phiên bản bộ lập lịch; cron_changed chỉ yêu cầu worker đó đọc lại
phiên bản có thẩm quyền, do đó một gợi ý đến muộn không thể khôi phục bộ lập lịch cũ hơn.
Một phiên bản sửa đổi mới hơn hủy lần thử máy chủ đang hoạt động trước khi nó có thể chấp nhận một
ảnh chụp nhanh cũ.
cron_reconciled báo cáo enabled: false, cùng đường dẫn đó gọi
replaceAll([]) và xóa các lần đánh thức bên ngoài cũ. Cơ chế thử lại/chờ lũy tiến trong ví dụ này
là cục bộ theo tiến trình và coi lỗi bộ điều hợp khi chạy là tạm thời; hãy xác thực
cấu hình không thể thử lại trước khi đăng ký. OpenClaw không cung cấp
hộp thư đi cho các tác dụng của hook plugin. Nếu tiến trình thoát trước khi được chấp nhận bền vững,
lần khởi động Gateway tiếp theo sẽ phát một ảnh chụp nhanh cron_reconciled mới có thẩm quyền.
gateway_stop hủy công việc máy chủ đang thực hiện, chờ worker ổn định, sau đó
đóng bộ điều hợp.
Các tính năng sắp ngừng hỗ trợ
Một vài bề mặt liền kề hook đã không còn được khuyến nghị nhưng vẫn được hỗ trợ. Hãy di chuyển trước bản phát hành chính tiếp theo:- Phong bì kênh dạng văn bản thuần trong các trình xử lý
inbound_claimvàmessage_received. Hãy đọcBodyForAgentvà các khối ngữ cảnh người dùng có cấu trúc thay vì phân tích văn bản phong bì phẳng. Xem Phong bì kênh dạng văn bản thuần → BodyForAgent. subagent_spawningvẫn được giữ để tương thích với các plugin cũ, nhưng plugin mới không nên trả về thông tin định tuyến luồng từ đó. Core chuẩn bị các liên kết subagentthread: truethông qua bộ điều hợp liên kết phiên kênh trước khisubagent_spawnedđược kích hoạt.deactivatevẫn được giữ làm bí danh tương thích dọn dẹp đã lỗi thời cho đến sau ngày 2026-08-16. Plugin mới nên sử dụnggateway_stop.onResolutiontrongbefore_tool_callhiện sử dụng hợpPluginApprovalResolutioncó định kiểu (allow-once/allow-always/deny/timeout/cancelled) thay chostringdạng tự do.api.registerSessionExtension/api.enqueueNextTurnInjectionvẫn được giữ làm bí danh tương thích cấp cao nhất. Plugin mới nên sử dụngapi.session.state.registerSessionExtension(...)vàapi.session.workflow.enqueueNextTurnInjection(...).
command-auth → command-status — hãy xem
Di chuyển Plugin SDK → Các tính năng đã lỗi thời đang hoạt động.
Liên quan
- Di chuyển Plugin SDK - các tính năng đã lỗi thời đang hoạt động và lịch trình loại bỏ
- Xây dựng plugin
- Tổng quan về Plugin SDK
- Điểm vào của plugin
- Hook nội bộ
- Chi tiết nội bộ về kiến trúc plugin