Skip to content

Stop hook should include recent messages to enable external memory systems #1306

Description

@Liewzheng

Problem

Currently the Stop hook payload only carries a minimal set of metadata (e.g. aborted). For external memory systems that want to observe and learn from a completed turn, this is insufficient: they can see that the agent stopped, but not what was said during the turn.

Without the assistant reply, a memory hook cannot store the full user/assistant exchange. It must rely on:

  • Earlier hooks such as UserPromptSubmit (which only sees the user message), or
  • Asking the model to explicitly call memory tools, which is unreliable and adds latency.

How other agent CLIs solve this

We surveyed the hook/event designs of several popular agent CLIs in the ecosystem:

Claude Code

  • Stop hook receives transcript_path pointing to a JSONL transcript file.
  • Hooks can read the transcript to extract recent user/assistant messages.
  • Source: plugins/plugin-dev/skills/hook-development/SKILL.md

OpenAI Codex

  • Stop hook receives last_assistant_message inline, plus transcript_path to the rollout JSONL.
  • There is also a legacy AfterAgent hook that passes recent user messages inline.
  • Source: codex-rs/hooks/src/schema.rs, codex-rs/hooks/schema/generated/stop.command.input.schema.json

OpenCode

  • No direct Stop hook, but plugins can listen to:
    • chat.message for each new user turn,
    • event for durable assistant/tool/text events,
    • experimental.chat.messages.transform to read the full message list before the LLM call.
  • Source: packages/plugin/src/index.ts, packages/opencode/src/plugin/index.ts

kimi-cli (previous generation)

  • Stop hook only receives stop_hook_active, similar to the current kimi-code behavior.
  • Conversation is available only by reading session files from disk.
  • Source: src/kimi_cli/hooks/events.py, src/kimi_cli/wire/types.py

Why PR #1299 is the right fix

PR #1299 (#1299) extends the Stop hook inputData with a messages array containing the recent user/assistant messages, with non-text content parts filtered out for JSON safety.

This brings kimi-code in line with the ecosystem:

  • Codex provides last_assistant_message + transcript path.
  • Claude Code provides transcript path.
  • kimi-code would provide the recent messages inline, which is the most hook-friendly approach and avoids requiring filesystem access or parsing JSONL transcripts.

Benefits

  1. External memory systems can learn from full turns. A memory hook can store user preferences, decisions, and facts from both the user prompt and the assistant reply.
  2. Backward compatible. Existing Stop hooks that ignore messages continue to work unchanged.
  3. No extra model/tool calls needed. The hook receives the context deterministically at the end of each turn.
  4. Aligns with user expectations. Developers coming from Claude Code or Codex expect lifecycle hooks to expose enough context to build memory, logging, and observability integrations.

Request

Please review and consider merging PR #1299. The implementation is minimal, tested, and includes documentation and a changeset.

cc @wbxl2000 @liruifengv @RealKai42 — would love your feedback on this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions