feat: agent event hooks + streaming for channel plugins#48355
feat: agent event hooks + streaming for channel plugins#48355carlos-sarmiento wants to merge 1 commit into
Conversation
Greptile SummaryThis PR adds agent cognitive lifecycle hooks (
Confidence Score: 2/5
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a1e0854637
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@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: b3901c8119
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@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: a286ab506a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@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: 5821718b68
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
10f7436 to
de52bf0
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: de52bf0e7c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
de52bf0 to
7a3e2ca
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7a3e2cabd5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
7a3e2ca to
15b5017
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 15b5017bd5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
15b5017 to
e1559d8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e1559d8239
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
e1559d8 to
c53d301
Compare
c53d301 to
4ca6245
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4ca6245452
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const ctx = getAgentRunContext(evt.runId); | ||
| if (ctx?.sessionKey === sk) { |
There was a problem hiding this comment.
Resolve session filter before dispatching listeners
api.onAgentEvent falls back to getAgentRunContext(evt.runId) when evt.sessionKey is missing, but that lookup happens inside each listener callback. On non-Control-UI runs, lifecycle end/error events have no sessionKey, and the gateway listener clears run context during those same events (clearAgentRunContext). Because listeners are invoked in registration order, deferred channel plugins (loaded later in server.impl.ts full-load path) can run after the clear and miss the terminal lifecycle event for their session, leaving per-run plugin state open even though the run ended.
Useful? React with 👍 / 👎.
4ca6245 to
35f0e24
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 35f0e249d8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
- Add thinking_start/thinking_end plugin hooks with durationMs tracking - Add token usage (input/output/cache) and toolCallCount to agent_end hook - Expose onAgentEvent() in plugin API with optional sessionKey filtering - Gate onAgentEvent behind registrationMode='full' to prevent listener leaks - Emit synthetic thinking_start before orphaned thinking_end events - Track toolCallCount independently of compaction retry resets - Fire thinking hooks for <think> tag reasoning flows (not just native events) - Hoist tag transition tracking outside if(next) gate for pure-thinking chunks
35f0e24 to
22b6034
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 22b603402b
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| extractAssistantThinking(msg) || | ||
| extractThinkingFromTaggedText(extractAssistantTextWithThinkingTags(msg)); |
There was a problem hiding this comment.
Ignore code spans when extracting fallback tagged reasoning
The message_end safety net now derives fallback thinking text with extractThinkingFromTaggedText(extractAssistantTextWithThinkingTags(msg)), but that extractor is regex-only and does not skip inline/code-fence spans. If a run has an open reasoning lifecycle (for example from native thinking_* events) and the assistant answer contains a literal code example like `<think>...</think>`, the thinking_end hook can receive bogus reasoning text from user-visible code instead of real model reasoning, causing channel plugins to render incorrect thinking blocks.
Useful? React with 👍 / 👎.
|
Codex review: needs real behavior proof before merge. Summary Reproducibility: yes. for the review findings: source inspection of current main and PR head reproduces the API-shape mismatch, duplicate native Real behavior proof Next step before merge Security Review findings
Review detailsBest possible solution: Rebase onto current main, use the host-owned grouped plugin event subscription contract unless maintainers approve a new top-level API, make thinking lifecycle delivery deterministic, and provide redacted real plugin/channel proof before merge. Do we have a high-confidence way to reproduce the issue? Yes for the review findings: source inspection of current main and PR head reproduces the API-shape mismatch, duplicate native Is this the best way to solve the issue? No, not as-is. The direction is plausible, but the maintainable solution should align with current main's grouped plugin event contract and guarantee one-to-one thinking lifecycle edges before exposing the SDK surface. Full review comments:
Overall correctness: patch is incorrect What I checked:
Likely related people:
Remaining risk / open question:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 936989a88b1d. |
Summary
Exposes agent cognitive lifecycle events to channel plugins, enabling rich agentic UIs (thinking blocks, tool call cards, usage tracking).
Changes
Commit 1: thinking hooks + enriched agent_end (5 files, +117)
thinking_start/thinking_endplugin hooks fired during reasoning phasesagent_endevent now includestokenUsage(input/output/cache/total) andtoolCallCount"thinking"toAgentEventStreamtype unionCommit 2:
api.onAgentEvent()for real-time streaming (2 files, +12)api.onAgentEvent(listener)onOpenClawPluginApiMotivation
Channel plugins currently have
before_tool_call/after_tool_callhooks but no visibility into:agent_end)This unlocks channel plugins that render:
Usage
Files Changed
src/plugins/types.ts— New hook types, enrichedAgentEndEvent,onAgentEventon APIsrc/plugins/hooks.ts—runThinkingStart()/runThinkingEnd()implementationssrc/plugins/registry.ts— WireonAgentEventinto plugin API creationsrc/agents/pi-embedded-subscribe.handlers.messages.ts— Emit thinking hookssrc/agents/pi-embedded-runner/run/attempt.ts— Thread usage/tool count into agent_endsrc/infra/agent-events.ts— Add"thinking"to stream typeCloses #7724
Related: #5086, #5279, #21184, #30285