Summary
The tool_result_persist hook currently has a synchronous-only signature:
tool_result_persist: (event: PluginHookToolResultPersistEvent, ctx: PluginHookToolResultPersistContext)
=> PluginHookToolResultPersistResult | void;
This prevents plugins from making async operations (HTTP calls, database queries) during tool result persistence. Other hooks like before_tool_call, message_sending, after_tool_call, session_start, and session_end all support Promise returns.
Use Case
Governance plugins need to scan tool results for PII, secrets, and policy violations before they are persisted to the session transcript. This requires an async HTTP call to a policy server. With the current sync-only signature, the plugin cannot:
- Send tool results to an external policy engine for PII/secrets detection
- Redact sensitive data before it enters the LLM context window
- Block results that violate data governance policies
The message_sending hook (which IS async) catches PII before it reaches the end user, but the gap is tool results entering the LLM context window unscanned.
Proposed Change
Add Promise support to the tool_result_persist return type, matching the pattern used by other hooks:
tool_result_persist: (event: PluginHookToolResultPersistEvent, ctx: PluginHookToolResultPersistContext)
=> Promise<PluginHookToolResultPersistResult | void> | PluginHookToolResultPersistResult | void;
Similarly, before_message_write has the same sync-only limitation and would benefit from async support.
Current Workaround
Plugins can use before_tool_call for input governance and message_sending for outbound message scanning, but there is no async-capable hook for scanning tool results before transcript persistence.
Context
We encountered this while building @axonflow/openclaw-plugin, a governance plugin that enforces policies across tool inputs and outbound messages. The tool_result_persist hook was the intended point for output scanning, but the sync-only constraint makes it impossible to call an external policy server.
Summary
The
tool_result_persisthook currently has a synchronous-only signature:This prevents plugins from making async operations (HTTP calls, database queries) during tool result persistence. Other hooks like
before_tool_call,message_sending,after_tool_call,session_start, andsession_endall supportPromisereturns.Use Case
Governance plugins need to scan tool results for PII, secrets, and policy violations before they are persisted to the session transcript. This requires an async HTTP call to a policy server. With the current sync-only signature, the plugin cannot:
The
message_sendinghook (which IS async) catches PII before it reaches the end user, but the gap is tool results entering the LLM context window unscanned.Proposed Change
Add
Promisesupport to thetool_result_persistreturn type, matching the pattern used by other hooks:Similarly,
before_message_writehas the same sync-only limitation and would benefit from async support.Current Workaround
Plugins can use
before_tool_callfor input governance andmessage_sendingfor outbound message scanning, but there is no async-capable hook for scanning tool results before transcript persistence.Context
We encountered this while building @axonflow/openclaw-plugin, a governance plugin that enforces policies across tool inputs and outbound messages. The
tool_result_persisthook was the intended point for output scanning, but the sync-only constraint makes it impossible to call an external policy server.