feat(hooks): fixed and adding various agent, messaging, system and compaction hooks#9761
feat(hooks): fixed and adding various agent, messaging, system and compaction hooks#9761vincentkoc wants to merge 70 commits intoopenclaw:mainfrom
Conversation
Additional Comments (2)
Set Prompt To Fix With AIThis is a comment left during a code review.
Path: src/infra/outbound/deliver.ts
Line: 232:235
Comment:
**message_sent not fired**
`deliverOutboundPayloads()` emits `message_sent` after `sendTextChunks()`/`sendSignalTextChunks()` and inside the media loop, but the early-return path for `handler.sendPayload && payload.channelData` only calls `message_sent` on success. If `handler.sendPayload(payload)` throws, the `catch` will run `runMessageSentHook(attemptedSendContent, false, ...)`, but `attemptedSendContent` is initialized from the *pre-hook* `payloadSummary.text` and doesn’t track per-channelData payload content after `message_sending` mutation. This makes `message_sent` report stale content for failures on `sendPayload` channels.
Set `attemptedSendContent` after applying `message_sending` (and/or right before each send attempt) so failure hooks report the same content that was actually attempted.
How can I resolve this? If you propose a fix, please make it concise.
This is especially relevant because pruning runs in the Prompt To Fix With AIThis is a comment left during a code review.
Path: src/agents/pi-extensions/context-pruning/pruner.ts
Line: 266:268
Comment:
**Prune hook await changes**
`pruneContextMessages()` is now `async` solely to `await triggerInternalHook` via `emitPruneHook()`. This makes every pruning pass wait on hook handlers, which can slow the agent loop and (if hooks hang) block prompt execution. Since the hook is best-effort telemetry, consider firing it without awaiting (e.g., `void triggerInternalHook(...)` with `.catch(...)`) or using a timeout so pruning remains deterministic.
This is especially relevant because pruning runs in the `context` extension on every turn when enabled.
How can I resolve this? If you propose a fix, please make it concise. |
Additional Comments (2)
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/agents/pi-tools.before-tool-call.ts
Line: 1704:1718
Comment:
**Tool hook sessionKey misuse**
`resolveHookSessionKey()` fabricates a `sessionKey` like `tool:<agentId>:<toolCallId>` when `ctx.sessionKey` is missing (`src/agents/pi-tools.before-tool-call.ts:1704-1718`). This makes internal `agent:tool:*` hooks look like they’re attached to a real session key and can collide across runs if toolCallIds repeat, breaking routing/attribution for any consumer that treats `sessionKey` as a persisted identifier. Consider using a clearly non-session key (e.g. `run:<runId>` like `attempt.ts` does) or leaving `sessionKey` empty and putting the fallback into `context` only.
How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/agents/pi-extensions/context-pruning/extension.ts
Line: 1413:1416
Comment:
**Async handler may be ignored**
`contextPruningExtension` changed the `api.on("context", ...)` handler to `async` (`src/agents/pi-extensions/context-pruning/extension.ts:1413-1416`). If the underlying extension host expects a synchronous return value (common for hook-style APIs), returning a Promise can cause the pruned `messages` to be ignored (or applied too late), meaning pruning silently stops working in production. This needs confirmation against the `ExtensionAPI.on` contract; if it’s sync-only, keep the handler synchronous and avoid awaiting inside it. Does the pi-coding-agent ExtensionAPI.on("context") contract support async handlers (i.e., does it await Promises)? If not, we need to keep pruning synchronous and remove async/await here.
How can I resolve this? If you propose a fix, please make it concise. |
|
This is too big. Make small PRs. Stop spamming me. |
@cpojer As requested, PR has been split and child PRs are ready
|
|
Moved to #16788 |
This PR adds and wires missing lifecycle hooks across OpenClaw (internal hooks and plugin hooks) to unlock observability, guardrails, and monitoring. Also patched CI/CD to ensure formatter passes.
New/expanded internal hooks (
HOOK.md)session:compact:before/session:compact:after(compaction lifecycle)session:prune(context pruning of tool outputs)gateway:shutdown/gateway:pre-restart(gateway lifecycle)agent:thinking:start/agent:thinking:end(model call boundary)agent:response:start/agent:response:end(response generation boundary)agent:tool:start/agent:tool:end(tool execution boundary)Plugin hooks wired
before_compaction/after_compactionnow called in the compaction pipelinemessage_received/message_sending/message_sentwired into outbound deliverybefore_tool_call/after_tool_callnow receivetoolCallIdwhen availableFixes and other context improvements
pnpm formatsessionKey/sessionIdtoolCallIdsession-write-lockfailures + unhandledprocess.exitcaused byec0728b35(fix: release session locks on process termination [AI-assisted] #1962)dispatch-from-configonToolResultexpectation failures caused by05b28c147ee1ec3fab(fix: wire onToolResult callback for verbose tool summaries #2022)onToolResultbehavior change from05b28c147+ee1ec3fabIssues addressed
message:received/senthooks wired:message_receivedto internal hooks:toolCallId:sessionKeyusage in hooks:FYI
Greptile Overview
Greptile Summary
This PR expands OpenClaw’s lifecycle hook surface area and wires plugin hooks into core workflows. Key changes include:
session:compact:before/after), context pruning (session:prune), gateway shutdown/restart (gateway:shutdown,gateway:pre-restart), and agent lifecycle boundaries (agent:thinking:*,agent:response:*,agent:tool:*).message_sending,message_sent) and extends tool hook context to includetoolCallId.normalizeSessionKeyhelper and propagatessessionKey/sessionIdthrough outbound delivery paths.Overall, the PR is centered on improving observability/guardrails by ensuring lifecycle hooks fire consistently across internal and plugin APIs, while also tightening session key handling for routing/storage consistency.
Confidence Score: 3/5