Chat Engines and Memory

A query engine answers one question in isolation; a chat engine holds a conversation. The difference is memory — and handling memory well is what separates a demo chatbot from one that stays coherent and affordable over a long dialogue.

A query engine treats every question as standalone. But real users have conversations: they ask a follow-up, say “what about the second one?”, refer back to something three turns ago. That requires memory — and a chat engine, which is a query engine plus conversational state. This fifth post in the LlamaIndex series covers conversational retrieval and the memory that makes it work.

Why a query engine isn’t enough

Consider the exchange: “What’s our refund policy?” → (answer) → “Does it apply to sale items?” A bare query engine embeds “Does it apply to sale items?” and retrieves on that alone — but “it” is meaningless without the prior turn. The retrieval misses, and the answer is wrong. Conversation breaks isolated retrieval, and fixing it is exactly what a chat engine does.

Chat engines: conversation over your data

A chat engine wraps retrieval in a stateful conversational interface:

chat_engine = index.as_chat_engine()
chat_engine.chat("What's our refund policy?")
chat_engine.chat("Does it apply to sale items?")  # 'it' resolved from history

The chat engine keeps the conversation history and uses it so follow-ups make sense. LlamaIndex offers different chat modes that trade off simplicity against capability — two worth knowing:

Choosing a mode is choosing how much reasoning sits between the user’s message and the retrieval: condense-question is a fixed rewrite-then-retrieve; the agentic mode lets the model decide.

Memory: the conversation’s state

Memory is where the conversation history lives, and it’s the piece that needs real engineering. The naive approach — keep every turn and stuff the whole history into each prompt — breaks down fast: the context window fills, cost and latency climb with every turn, and eventually the earliest (often most important) turns get truncated. LlamaIndex provides a memory abstraction (a chat memory buffer) that manages this, and the strategies mirror the trade-offs from the context engineering series:

The underlying reality is that context is finite and grows every turn, so memory is fundamentally about deciding what to keep, what to compress, and what to drop — a curation problem, not a storage problem.

The distinction that matters: memory vs. retrieval

It’s worth separating two things a chat engine juggles, because conflating them causes bugs. Conversation memory is the dialogue history — what the user and assistant said. Retrieval brings in knowledge from your indexed data. They’re different sources with different lifecycles: memory is per-conversation and ephemeral; the knowledge base is shared and persistent. A good chat engine uses memory to understand the current turn (resolve references, track what’s been discussed) and retrieval to ground the answer in your data. Keeping them distinct — rather than dumping retrieved chunks into memory or treating history as a knowledge source — keeps the system coherent as conversations grow.

Key takeaways

Further reading

Sources & References

Chat engines and memory