← Back to PRs

#19565: feat: add agent lifecycle hook events (session, message, error)

by tag-assistant open 2026-02-17 23:38 View on GitHub →
docs agents size: S
## Summary Adds five new internal hook event types for agent lifecycle, enabling workspace/managed hooks to react to the full agent work loop — not just slash commands. ## New Events | Event | Fires When | Location | |-------|-----------|----------| | `session:start` | After `/new` or `/reset` creates a new session | `commands-core.ts` | | `session:end` | After `/stop` command | `commands-session.ts` | | `agent:error` | Agent encounters LLM/tool error | `pi-embedded-subscribe.handlers.lifecycle.ts` | | `message:received` | Inbound message arrives from user | `dispatch-from-config.ts` | | `message:sent` | Outbound message delivered to user | `deliver.ts` | ## Changes - **`src/hooks/internal-hooks.ts`**: Added `message` to `InternalHookEventType` union - **`src/auto-reply/reply/commands-core.ts`**: Fire `session:start` after /new and /reset - **`src/auto-reply/reply/commands-session.ts`**: Fire `session:end` after /stop - **`src/agents/pi-embedded-subscribe.handlers.lifecycle.ts`**: Fire `agent:error` on agent errors - **`src/auto-reply/reply/dispatch-from-config.ts`**: Fire `message:received` on inbound messages - **`src/infra/outbound/deliver.ts`**: Fire `message:sent` on outbound delivery - **`docs/automation/hooks.md`**: Moved events from 'Future Events' to documented sections ## Design - All new hooks are fire-and-forget (`void triggerInternalHook(...).catch()`) to avoid blocking the main message/agent flow - Events are emitted alongside existing plugin hooks where applicable (e.g., `message_received` plugin hook) - Minimal changes — no refactoring of unrelated code ## Testing - `npm run build` ✅ compiles clean - All existing hook tests pass (`npx vitest run src/hooks/` — 86 tests, 9 files) <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds five new internal hook event types (`session:start`, `session:end`, `agent:error`, `message:received`, `message:sent`) to enable workspace/managed hooks to react to the full agent lifecycle. All hooks follow the existing fire-and-forget pattern and are placed alongside existing plugin hooks. - The `message:sent` hook in `deliver.ts` derives its `sessionKey` from `params.mirror?.sessionKey`, but `mirror` is optional and absent at the majority of call sites (~61%). This causes the hook to fire with an empty session key in many delivery paths (heartbeat, cron, CLI sends), which limits usefulness for session-aware hook consumers. - The Event Context type example in the docs (`hooks.md` line 210) still shows the old 4-type union and is missing the newly added `'message'` type. - Code changes are otherwise clean: deduplication is respected for `message:received`, hook placement is correct relative to existing hooks, and error handling is consistent. <h3>Confidence Score: 3/5</h3> - Generally safe — hooks are fire-and-forget and won't block the main flow, but the `message:sent` session key gap warrants a fix before merging. - Most of the hook additions are clean and well-placed. However, the `message:sent` hook will frequently fire with an empty `sessionKey` due to `mirror` being absent at most call sites, and the docs have a stale type definition. These issues reduce confidence from what would otherwise be a straightforward feature addition. - `src/infra/outbound/deliver.ts` (empty sessionKey in most delivery paths), `docs/automation/hooks.md` (stale Event Context type) <sub>Last reviewed commit: 5f57b02</sub> <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs