openclaw - 💡(How to fix) Fix Support async handlers for tool_result_persist hook [1 comments, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#58558Fetched 2026-04-08 02:01:06
View on GitHub
Comments
1
Participants
1
Timeline
0
Reactions
0

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.

Root Cause

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.

Fix Action

Fix / Workaround

Current Workaround

Code Example

tool_result_persist: (event: PluginHookToolResultPersistEvent, ctx: PluginHookToolResultPersistContext) 
  => PluginHookToolResultPersistResult | void;

---

tool_result_persist: (event: PluginHookToolResultPersistEvent, ctx: PluginHookToolResultPersistContext) 
  => Promise<PluginHookToolResultPersistResult | void> | PluginHookToolResultPersistResult | void;
RAW_BUFFERClick to expand / collapse

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.

extent analysis

TL;DR

Update the tool_result_persist hook to support asynchronous operations by changing its return type to Promise<PluginHookToolResultPersistResult | void> | PluginHookToolResultPersistResult | void.

Guidance

  • Identify the specific use case where asynchronous operations are necessary, such as scanning tool results for PII or secrets, and determine if the updated tool_result_persist hook can address this need.
  • Verify that the proposed change to the tool_result_persist hook does not introduce any backwards compatibility issues with existing plugins.
  • Consider updating other hooks, such as before_message_write, to also support asynchronous operations if they have similar limitations.
  • Evaluate the current workaround using before_tool_call and message_sending hooks to determine if it can be replaced or supplemented with the updated tool_result_persist hook.

Example

tool_result_persist: async (event: PluginHookToolResultPersistEvent, ctx: PluginHookToolResultPersistContext) 
  => {
    const policyCheck = await scanToolResultForPII(event.toolResult);
    if (policyCheck.violatesPolicy) {
      // Redact or block the tool result
    }
    return policyCheck.result;
  };

Notes

The proposed change to the tool_result_persist hook assumes that the underlying implementation can handle asynchronous operations without introducing significant performance or complexity issues.

Recommendation

Apply the proposed workaround by updating the tool_result_persist hook to support asynchronous operations, as this will provide the necessary functionality for governance plugins to scan tool results before persistence.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING