Chat History & MemoryLesson 4

Redis Chat Message History

The last lesson stored history in a Python dict. Replace that with RedisChatMessageHistory and turns persist after the script exits. RunnableWithMessageHistory stays the same — only get_session_history changes. Set REDIS_URL (default redis://localhost:6379), pass session_id in config, and use optional ttl to drop old keys.

Before you start

Complete RunnableWithMessageHistory (In-Memory) first. Here you swap the storage backend only — chain, template, and invoke stay the same.

How it works

Each session_id maps to one Redis key. On invoke, the wrapper loads prior messages, runs the chain, then saves the new turn.

One Redis key per session_id:

invoke config

session_id = "demo-1"

Redis

key → messages for demo-1

RunnableWithMessageHistory

load → chain → save

REDIS_URL=redis://localhost:6379 · ttl=3600s

Each session_id gets its own Redis key.

Install

Install the Redis integration package. You also need a Redis server — see Redis install docs or run Docker: docker run -p 6379:6379 redis.

pip install langchain-redis

get_session_history

Read REDIS_URL from the environment so you can point at local Redis or a managed instance without changing code.

get_session_history — swap from in-memory

def get_session_history(session_id: str):
    return RedisChatMessageHistory(
        session_id=session_id,
        redis_url=REDIS_URL,   # os.getenv, default localhost:6379
        ttl=3600,              # optional expiry in seconds
    )

# RunnableWithMessageHistory calls this on every invoke.
Same interface as InMemoryChatMessageHistory — the wrapper code does not change.
import os
from langchain_redis import RedisChatMessageHistory

REDIS_URL = os.getenv("REDIS_URL", "redis://localhost:6379")

def get_session_history(session_id: str):
    return RedisChatMessageHistory(
        session_id=session_id,
        redis_url=REDIS_URL,
        ttl=3600,  # optional: expire after 1 hour
    )

Wrap and invoke

Identical to the RunnableWithMessageHistory lesson — only get_session_history differs.

chain_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history",
)
config = {"configurable": {"session_id": "demo-1"}}

reply = chain_with_history.invoke(
    {"input": question},
    config=config,
)

The demo script

redis_chat_message_history_demo.py runs the same two HTML <a> questions with session_id="demo-1" stored in Redis.

redis_chat_message_history_demo.py
"""redis_chat_message_history_demo.py"""
RedisChatMessageHistory(session_id, redis_url, ttl=3600)
RunnableWithMessageHistory(chain, get_session_history, …)
invoke({"input": question}, config=session_id)

Download the code

redis_chat_message_history_demo.py

Two HTML questions — Redis backend

Download .py
Requires a running Redis instance and langchain-redis. Venv from Project Setup.

Run it

Start Redis, activate the venv from Project Setup, then:

python redis_chat_message_history_demo.py
PowerShell — (.venv) active · Redis running
(.venv) PS C:\projects\langchain-course> python redis_chat_message_history_demo.py
Human: What does the HTML <a> tag do?
AI: The <a> tag creates a hyperlink to another page or resource.
Human: What attribute opens the link in a new tab?
AI: Use target="_blank" on the <a> tag.
History stored in Redis (redis://localhost:6379)
The second answer works because both invokes share the same session_id in Redis.

Quick reference

  • RedisChatMessageHistory — from langchain_redis; same .messages / add methods as in-memory.
  • REDIS_URL — env var, default redis://localhost:6379.
  • ttl=3600 — optional seconds until the Redis key is deleted; omit to keep keys until you clear them.
  • session_id — set in config["configurable"]; one Redis key per id.
  • Docs: RedisChatMessageHistory · RunnableWithMessageHistory · Message history how-to.

What's Next

Next: PostgreSQL Chat Message History — durable SQL storage for the same wrapper pattern.