[FEATURE] Conversation Lifecycle Hooks for Context Engineering/Memory Provider Integration

Resolved 💬 4 comments Opened Jan 21, 2026 by jackaldenryan Closed Feb 27, 2026

Preflight Checklist

  • [x] I have searched existing issues to verify this hasn't been filed before
  • [x] This is a single feature request (not multiple features)

Problem Statement

AI applications increasingly rely on context engineering/memory providers like Zep and Mem0 to build personalized, context-aware experiences. These platforms:

  • Store conversation history in knowledge graphs
  • Extract facts, preferences, and relationships from conversations
  • Retrieve relevant context to enhance each new interaction

The integration pattern requires:

  1. Sending every user message to the memory provider
  2. Sending every assistant message to the memory provider
  3. Retrieving and injecting relevant context before each response

Current Claude Code limitations prevent automatic memory integration:

| Capability Needed | Current Status |
|------------------|----------------|
| Capture user messages | ✅ UserPromptSubmit hook provides user_prompt |
| Capture assistant messages | ❌ No hook exists (see #17865) |
| Inject context into conversation | ❌ Multiple bugs block this (see below) |

Current Bugs Blocking Context Injection

Context injection via hooks is currently broken across multiple hook types:

| Issue | Hook Type | Problem |
|-------|-----------|---------|
| #19643 | UserPromptSubmit | systemMessage not injected into context |
| #19432 | PreToolUse | additionalContext received but not injected |
| #18427 | PostToolUse | No mechanism to inject context visible to Claude |
| #18534 | PostToolUse | additionalContext documented but not implemented |
| #16538 | SessionStart | additionalContext not surfaced to Claude |

Even when these bugs are fixed, the placement of injected context is not specified in the documentation. This is critical for the following reason:

Critical Requirement: Prompt Caching

Per issue #14963, Claude Code's prompt caching works sequentially from the beginning:

  • Content placed first in the prompt can be cached
  • Dynamic content placed before static content breaks caching for everything after it

Context engineering providers like Zep specifically recommend appending context after the user message to preserve caching. From Zep's documentation:

Append context block as "context message" Dynamically updating the system prompt on every chat turn has the downside of preventing prompt caching with LLM providers. In order to reap the benefits of prompt caching while still adding a new Zep context block in every chat, you can append the context block as a "context message" just after the user message in the chat history. On each new chat turn, remove the prior context message and replace it with the new one. This allows everything before the context message to be cached.

If context is injected at the BEGINNING of the prompt (e.g., in the system message), it would break caching for the entire ~16-19k token tool definition block on every single message. This would dramatically increase costs and reduce session length.

Required conversation structure for cache efficiency:

| Role      | Content                                    | Cached? |
|-----------|--------------------------------------------|---------|
| System    | Claude Code system prompt + tools (~16k)   | ✅ Yes  |
| User      | Previous user message                      | ✅ Yes  |
| Assistant | Previous assistant response                | ✅ Yes  |
| User      | Current user message                       | ✅ Yes  |
| Context   | [Memory context - replaced each turn]      | ❌ No   |

The key requirement is that context is:

  1. Injected AFTER the user message (not at the beginning)
  2. Replaced on each turn (to avoid context bloat)

Proposed Solution

1. Add AssistantResponse Hook (Related: #17865)

Fire a hook when Claude generates a response, enabling memory providers to capture assistant messages.

Hook input:

{
  "session_id": "abc123",
  "hook_event_name": "AssistantResponse",
  "response": "Claude's response text...",
  "transcript_path": "/path/to/transcript.jsonl"
}

2. Fix Context Injection Bugs AND Specify Placement

The existing bugs (#19643, #19432, #18534, #16538) need to be fixed, but more importantly, the placement of injected context must be explicitly defined:

Requirement: Context returned from UserPromptSubmit hooks (via systemMessage, additionalContext, or a new field) must be:

  • Appended AFTER the user message in the conversation (preserving prompt cache)
  • Automatically replaced on each subsequent turn (preventing context bloat)

Suggested implementation options:

Option A: Fix existing additionalContext field to inject after user message

{
  "continue": true,
  "additionalContext": "<memory_context>...</memory_context>"
}

Option B: Add explicit trailingContext field with clear semantics

{
  "continue": true,
  "trailingContext": "<memory_context>...</memory_context>"
}

The implementation details can be determined by the Claude Code team - the critical requirement is END placement to preserve prompt caching.

Alternative Solutions Considered

  1. MCP Server approach: Requires Claude to explicitly call memory tools; not automatic, and the LLM may "forget" to call them over long sessions. Context engineering should be invisible to the agent.
  1. Modifying system prompt via hooks: Would break prompt caching for the entire ~16-19k token tool definition block on every message - dramatically increasing costs.
  1. File watching transcript.jsonl: Unreliable, introduces latency, doesn't work across all platforms.
  1. Using current hook context injection: Broken across multiple hook types (see bugs above), and placement behavior is undefined.

Priority

High - Significant impact on productivity

This enables an entirely new category of Claude Code applications: context-engineered agents that leverage long-term memory for personalized, context-aware assistance.

Feature Category

Configuration and settings (Hooks system)

Use Case Example

Scenario: Building a Zep-enhanced Claude Code agent

  1. User configures hooks:
{
  "hooks": {
    "UserPromptSubmit": [{
      "type": "command",
      "command": "python ~/.claude/hooks/zep-context.py"
    }],
    "AssistantResponse": [{
      "type": "command",
      "command": "python ~/.claude/hooks/zep-save-response.py"
    }]
  }
}
  1. UserPromptSubmit hook (zep-context.py):
#!/usr/bin/env python3
import json, sys, os
from zep_cloud.client import Zep
from zep_cloud.types import Message

input_data = json.load(sys.stdin)
zep = Zep(api_key=os.environ["ZEP_API_KEY"])
thread_id = os.environ.get("ZEP_THREAD_ID", input_data["session_id"])

# 1. Send user message to Zep
zep.thread.add_messages(
    thread_id=thread_id,
    messages=[Message(role="user", content=input_data["user_prompt"])]
)

# 2. Retrieve personalized context
user_context = zep.thread.get_user_context(thread_id=thread_id)

# 3. Return trailing context (MUST be appended after user message to preserve cache)
print(json.dumps({
    "continue": True,
    "additionalContext": f"<memory_context>\n{user_context.context}\n</memory_context>"
}))
  1. AssistantResponse hook (zep-save-response.py):
#!/usr/bin/env python3
import json, sys, os
from zep_cloud.client import Zep
from zep_cloud.types import Message

input_data = json.load(sys.stdin)
zep = Zep(api_key=os.environ["ZEP_API_KEY"])
thread_id = os.environ.get("ZEP_THREAD_ID", input_data["session_id"])

# Send assistant message to Zep
zep.thread.add_messages(
    thread_id=thread_id,
    messages=[Message(role="assistant", content=input_data["response"])]
)

print(json.dumps({"continue": True}))
  1. Result: Claude Code becomes a personalized assistant that:
  • Remembers coding preferences across sessions
  • Recalls past architectural decisions
  • Maintains project context without explicit reminders
  • Preserves prompt caching for efficient token usage

Additional Context

Related Issues

| Issue | Description | Relationship |
|-------|-------------|--------------|
| #17865 | AssistantResponse Hook | Directly needed for capturing assistant messages |
| #19643 | UserPromptSubmit systemMessage not injected | Blocker bug |
| #19432 | PreToolUse additionalContext not injected | Related blocker |
| #18427 | PostToolUse cannot inject context | Related blocker |
| #18534 | PostToolUse additionalContext not implemented | Related blocker |
| #16538 | SessionStart additionalContext not surfaced | Related blocker |
| #14963 | Prompt caching inefficiency - dynamic before static | Explains why placement matters |
| #14859 | Agent hierarchy + intermediate text hooks | Related |
| #19291 | Automatic memories like ChatGPT | Same problem space |

Why This Matters

Both Zep and Mem0 are popular context engineering/memory providers with similar integration patterns:

Zep pattern:

zep.thread.add_messages(thread_id, messages=[...])  # Add messages
context = zep.thread.get_user_context(thread_id)    # Retrieve context

Mem0 pattern:

client.add(messages, user_id="...")                 # Add messages
memories = client.search(query, user_id="...")      # Retrieve context

Both require the same hook capabilities, suggesting this is a general need for the context engineering ecosystem, not specific to one vendor.

Key Requirements Summary

  1. AssistantResponse hook - Capture assistant messages automatically
  2. Fix context injection bugs - #19643, #19432, #18534, #16538
  3. Specify END placement - Context MUST be appended AFTER user message to preserve prompt caching
  4. Context replacement - Each turn's context replaces the previous (prevents bloat)

Summary

This feature request proposes completing Claude Code's conversation lifecycle hooks to enable seamless integration with context engineering/memory providers like Zep and Mem0:

  1. AssistantResponse hook (#17865) - Capture assistant messages
  2. Fix and specify context injection - Fix existing bugs AND explicitly define that context is appended AFTER the user message to preserve prompt caching

The prompt caching requirement is critical: injecting context at the beginning of the prompt would break caching for the entire ~16-19k token tool definition block, dramatically increasing costs. Context must be appended at the END.

Together, these enable automatic, hook-based memory integration without MCP servers or manual intervention.

View original on GitHub ↗

This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗