feat(hooks): add lifecycle events for sessions and agent turns#6885
feat(hooks): add lifecycle events for sessions and agent turns#6885mverrilli wants to merge 2 commits intoopenclaw:mainfrom
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5cecd487d7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
17b3219 to
1a44949
Compare
There was a problem hiding this comment.
💡 Codex Review
https://github.com/openclaw/openclaw/blob/1a44949f241e347280f5e90dab11e721ea0b570e/src/auto-reply/reply/agent-runner.ts#L352-L354
Emit lifecycle hooks even on final run outcomes
The early return for runOutcome.kind === "final" skips the new session:start and agent:reply hook emissions that happen later in this function. This matters in the reset/error paths where runAgentTurnWithFallback returns kind: "final" after resetting the session (e.g., compaction failure, role ordering conflict), so hooks never observe the session start or the warning reply that is actually sent. If hooks are meant to track all session starts and replies, consider emitting them before returning in this branch or handling the final outcome alongside the normal response flow.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Re: Emit lifecycle hooks even on final run outcomes Fixed this and similar edge cases. Also ran across a small bug that returned max tokens instead of actual tokens which is now fixed. @codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b24b09ae80
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6d58c0f210
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 503c092c7c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Codex Review: Didn't find any major issues. Nice work! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Additional Comments (1)
Consider skipping hook emission when there’s no session key, or ensuring a stable fallback key is always available. Prompt To Fix With AIThis is a comment left during a code review.
Path: src/auto-reply/reply/commands-session.ts
Line: 328:333
Comment:
This can emit a `command:stop` hook with an empty `sessionKey` via `abortTarget.key ?? params.sessionKey ?? ""`. If both are unset for a given command source, hook handlers that route/index by `sessionKey` won’t be able to associate the event.
Consider skipping hook emission when there’s no session key, or ensuring a stable fallback key is always available.
How can I resolve this? If you propose a fix, please make it concise. |
007d341 to
e9de691
Compare
dea9539 to
baa83d4
Compare
|
@greptileai review |
Additional Comments (1)
Prompt To Fix With AIThis is a comment left during a code review.
Path: src/auto-reply/reply/agent-runner.ts
Line: 311:315
Comment:
**Wrong session file resolver**
`resetSession()` builds `nextSessionFile` using `resolveSessionTranscriptPath(nextSessionId, agentId, sessionCtx.MessageThreadId)` (`agent-runner.ts:311-315`), but elsewhere the code treats `sessionFile` as the session JSONL path resolved via `resolveSessionFilePath(...)` (and uses `resolveSessionTranscriptPath(...)` for transcript/derived paths). Storing a transcript path into `SessionEntry.sessionFile` can break later reads/writes that expect the JSONL session file (e.g., compaction/memory tooling that opens the session file). This should use the same resolver used in `initSessionState` when setting `sessionEntry.sessionFile`.
How can I resolve this? If you propose a fix, please make it concise. |
|
@greptileai The current implementation is correct and matches initSessionState. Evidence from session.ts:331-335: Both use the same pattern:
The distinction:
The current code correctly uses resolveSessionTranscriptPath when creating a new session file path, consistent with how sessions are initialized throughout the codebase. |
|
You're correct. After reviewing The naming is a bit confusing ( |
baa83d4 to
9ff7083
Compare
|
@greptileai review |
|
@mverrilli do you need a hand with this? I need this PR for a few things im working through atm. |
a9b16ff to
167ee17
Compare
Hey @vincentkoc I did some refactoring and have just been plugging away at edge cases and minor inconsistencies throughout the day although I let the code reviewer take me astray for a bit. You can test what I have checked in right now. I just fixed the ordering and alignment of events. Event hooks are on a "best effort" basis as implemented here. Let me know if you have any trouble. |
|
@mverrilli i decided to take a more comprehensive approach as there are more deep routed issues with just adding the events to ensure full coverage, i decided to add changes in my own PR #9761 |
|
@vincentkoc alright, yeah.. I was avoiding some of the bigger issues I noticed as I was trying to keep the PR focused on what I needed for my hooks. I did add compactions events today and typed them. was thinking to add the end phase as well. |
Do you have a PR link open/closed for the compaction? |
|
@vincentkoc 009d561 That's the commit, I hadn't made a PR specifically for it, I just added it to this one. |
009d561 to
10c161d
Compare
10c161d to
cdbbee3
Compare
Add internal hook events for session and agent lifecycle transitions: - session:start — fires when a new session begins (user-initiated or auto-recovery) - session:end — fires when a session ends (reset, idle timeout, daily rollover) - session:reset — fires on session transitions with old/new session context - session:compaction — fires after auto-compaction or memory flush compaction - agent:reply — fires after each agent turn with input/output/turnId - agent:flush — fires before memory flush runs - command:stop — fires when /stop is issued with persistence status Shared helpers extracted to hook-helpers.ts to deduplicate emission logic across agent-runner, followup-runner, get-reply, and command handlers. Session reset reason tracking added to session.ts for hook context. Co-Authored-By: Claude Opus 4.6 <[email protected]>
Add documentation for all new internal hook events including event names, trigger conditions, context payloads, and delivery semantics. Co-Authored-By: Claude Opus 4.6 <[email protected]>
cdbbee3 to
a83cebe
Compare
|
Abandoning as there are many hook PRs now along with some just merged that overlaps with this. |
Summary
Adds comprehensive session lifecycle and agent execution hooks, enabling event-driven automation for session transitions, agent turns, memory management, and session maintenance operations.
Hooks Added
Session Lifecycle Events
session:start- Fires when a new persisted session begins (user-initiated/new//reset, or auto-recovery)session:end- Fires when a persisted session terminates (all transition types: user commands, idle timeout, daily reset, auto-recovery)session:reset- Fires aftersession:endduring resets, providing transition context (old/new session IDs and entries)Session Maintenance Events
session:compaction- Fires after session history compaction completes (inline or during memory flush)Agent Execution Events
agent:reply- Fires after each agent turn completes with user input and/or assistant outputagent:flush- Fires when memory flush starts (context approaching token limit)agent:bootstrap- Fires before workspace bootstrap files are injected (hooks can mutate bootstrap files)Key Features
Complete Session Coverage
/new,/reset), idle timeout, daily reset, and auto-recovery (compaction failure, role-ordering conflicts)sessionKeyto prevent empty-key emissionsRich Event Context
session:endandsession:resetprovide:user_command,idle_timeout,daily_reset,compaction_failure,role_ordering_conflictagent:replyprovides:agent:flushprovides:session:compactionprovides:auto_compactionormemory_flush)Hook Message System
event.messagesarray; messages are prepended to agent responsescommand:*events emit regardless of persistence, but message delivery depends on routing contextLifecycle Patterns
User-initiated reset (
/newor/reset):command:neworcommand:resetfires immediatelysession:end→session:reset(if replacing existing session)session:startfires during agent turnAuto-recovery reset (compaction failure/role conflicts):
session:end→session:resetfire during resetsession:startfires when agent turn runsIdle timeout / Daily reset:
session:end→session:resetfire on expirationsession:startfires during next agent turnBug Fixes
Documentation
Comprehensive documentation in
docs/hooks.mdcovering:Testing
Verified event sequences for all session transitions:
/new,/reset)Use Cases
Changes: 883 additions, 77 deletions across 10 files
Main files:
agent-runner.ts(383+),commands-session.ts(78+),session.ts(81+),get-reply.ts(78+),hooks.md(81+)