Belajar LangChain - Memory & Conversation State
Episode 7 of 23

Belajar LangChain - Memory & Conversation State

Membuat agent yang ingat: ringkas dan simpan riwayat percakapan, memakai thread_id untuk sesi paralel, serta LangGraph Checkpointer untuk snapshot dan resume percakapan lintas request.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 6 kalian menguasai output parsers dan output terstruktur. Tapi ada satu masalah besar yang belum kita pecahkan: model tidak punya ingatan. Setiap invoke() diperlakukan sebagai percakapan baru, padahal aplikasi chat yang bagus harus ingat siapa lawan bicaranya dan apa yang sudah dibahas. Itulah fokus episode ini.

Kita akan membangun ingatan di dua lapisan. Pertama, chat history: menyimpan, merangkum, dan menyuntikkan riwayat percakapan ke prompt. Kedua, LangGraph checkpoints: mekanisme persisten yang menyimpan seluruh state graph per thread_id, lengkap dengan kemampuan snapshot dan resume. Di akhir episode, kalian punya agent yang bisa melanjutkan percakapan walaupun aplikasi sudah restart.

Kenapa Model Perlu Memory

LLM adalah fungsi stateless: input token masuk, output token keluar. Konteks "ingatan" yang kalian lihat di chat model hanya karena semua riwayat dikirim ulang setiap request sebagai message. Artinya, kualitas percakapan ditentukan oleh dua hal: seberapa banyak riwayat yang dikirim, dan seberapa baik riwayat itu diatur.

Dua pola umum yang dipakai:

  • Menyimpan semua — cocok untuk percakapan pendek, tapi boros token karena seluruh history dikirim ulang.
  • Meringkas — saat percakapan panjang, ringkas pesan lama menjadi satu ringkasan agar context window tidak meledak.

Chat History Dasar dengan Message List

Cara paling sederhana menangani riwayat adalah membiarkan LangGraph mengelola list messages di dalam state. Setiap percakapan mendapat thread_id sendiri, dan semua pesan baru di-append ke daftar tersebut melalui reducer bawaan add_messages.

PythonState percakapan dengan messages
from typing import Annotated
from langgraph.graph import StateGraph, START, END, MessagesState
 
graph = StateGraph(MessagesState)

MessagesState adalah state khusus yang sudah dilengkapi reducer add_messages untuk field messages. Berkat reducer ini, ketika sebuah node mengembalikan pesan baru, LangGraph menggabungkannya dengan riwayat yang sudah ada — bukan menimpanya. Inilah fondasi ingatan di sisi state.

thread_id sebagai Kunci Percakapan

thread_id adalah identitas sebuah thread percakapan. Dengan menaruhnya di config, kalian bisa menjalankan ribuan percakapan paralel dalam satu instance tanpa saling mencampuri.

PythonAgent dengan thread_id berbeda
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_agent
 
model = ChatOpenAI(model="gpt-4o-mini")
agent = create_agent(
    model=model,
    tools=[],
    checkpointer=MemorySaver(),
)
 
config_a = {"configurable": {"thread_id": "percakapan-a"}}
config_b = {"configurable": {"thread_id": "percakapan-b"}}
 
agent.invoke({"messages": [("human", "Halo, nama saya Arman")]}, config=config_a)
agent.invoke({"messages": [("human", "Nama saya Budi")]}, config=config_b)
hasil = agent.invoke({"messages": [("human", "Siapa nama saya?")]}, config=config_a)
print(hasil["messages"][-1].content)

Karena thread percakapan-a dan percakapan-b dipisah oleh checkpointer, jawaban untuk pertanyaan "Siapa nama saya?" pada config_a adalah Arman — bukan Budi. Ini pola inti untuk layanan chat multi-user: satu thread_id per user per session.

Message Persistence dengan Checkpointer

Di balik thread_id ada checkpointer. Ia menyimpan snapshot state setelah setiap langkah graph selesai. MemorySaver menyimpan semuanya di RAM — cepat untuk pengembangan, tapi hilang saat proses mati. Untuk produksi, gunakan penyimpanan persisten.

PythonMemilih checkpointer
from langgraph.checkpoint.memory import MemorySaver
from langgraph.checkpoint.sqlite import SqliteSaver
 
# RAM: cepat, hilang saat restart
memory_saver = MemorySaver()
 
# SQLite: persisten di file, cocok untuk single-node
sqlite_saver = SqliteSaver.from_conn_string("checkpoints.db")

SqliteSaver menyimpan checkpoint ke file SQLite sehingga riwayat bertahan meskipun aplikasi dimulai ulang. Untuk lingkungan multi-instance yang terskalakan, PostgresSaver dari langgraph-checkpoint-postgres menjadi pilihan — kita bedah lebih dalam di episode 17 soal LangGraph lanjutan.

Warning

MemorySaver hanya untuk development. Begitu Anda butuh resume lintas restart atau horizontal scaling, segera pindah ke SqliteSaver atau PostgresSaver.

Snapshot dan Resume Percakapan

Kelebihan checkpointer adalah snapshot: kalian bisa membaca state percakapan kapan pun, dan resume dari titik terakhir tanpa harus menyalin ulang seluruh history secara manual.

PythonMembaca snapshot dan resume
from langgraph.checkpoint.memory import MemorySaver
 
checkpointer = MemorySaver()
agent = create_agent(model=model, tools=[], checkpointer=checkpointer)
config = {"configurable": {"thread_id": "thread-resume"}}
 
agent.invoke({"messages": [("human", "Ingat angka 42")]}, config=config)
 
# Snapshot: ambil riwayat lengkap thread ini
state_sekarang = checkpointer.get(config)
print(len(state_sekarang["messages"]))  # jumlah pesan tersimpan
 
# Resume: melanjutkan tanpa kehilangan konteks
resume = agent.invoke(
    {"messages": [("human", "Angka apa yang saya sebut tadi?")]},
    config=config,
)
print(resume["messages"][-1].content)

checkpointer.get(config) mengembalikan snapshot state thread saat itu — berguna untuk audit, pembuatan ringkasan, atau menampilkan riwayat ke frontend. Resume cukup memanggil invoke lagi dengan config yang sama; graph meneruskan dari checkpoint terakhir sehingga konteks angka 42 tetap tersedia.

Meringkas Riwayat Panjang

Percakapan yang terlalu panjang akan memakan context window. Solusinya: kurasi riwayat dengan ringkasan. Anda bisa memotong pesan lama menjadi satu pesan ringkasan system sehingga konteks tetap terjaga tanpa membawa semua token.

PythonPola trimming riwayat
from langchain_core.messages import SystemMessage, TrimMessage
from langgraph.prebuilt import create_agent
 
agent = create_agent(
    model=model,
    tools=[],
    checkpointer=MemorySaver(),
    before_model=TrimMessage(
        strategy="last",
        max_tokens=2000,
        token_counter=model,
        include_system=True,
    ),
)

TrimMessage memangkas pesan tertua ketika total token melewati max_tokens, sambil tetap menyimpan pesan system. Kombinasi pemangkasan plus ringkasan berkala adalah strategi standar untuk percakapan panjang di produksi — konteks tetap ringkas dan biaya token terkendali.

Penutup

Memory bukan fitur tersembunyi di dalam model, melainkan lapisan yang Anda bangun sendiri. Kalian sekarang bisa menyimpan riwayat percakapan, memisahkan sesi lewat thread_id, memakai checkpointer untuk snapshot dan resume, serta meringkas percakapan panjang agar tetap hemat token.

Inti yang harus dibawa pulang:

  • Model stateless; ingatan dibangun dari riwayat pesan yang disuntikkan ulang ke prompt.
  • MessagesState dengan reducer add_messages menjadi fondasi state percakapan di LangGraph.
  • thread_id memisahkan sesi percakapan sehingga banyak user bisa berjalan paralel tanpa tercampur.
  • MemorySaver untuk development; SqliteSaver dan PostgresSaver untuk produksi yang persisten dan scalable.
  • Checkpointer memungkinkan snapshot state dan resume percakapan lintas request maupun restart.
  • Percakapan panjang perlu kurasi: TrimMessage untuk memangkas dan ringkasan untuk memadatkan konteks.

Di episode 8 kita naik kelas: Tools & Function Calling — memberi agent kemampuan bertindak lewat dekorator @tool, mengikat tools ke model dengan bind_tools, dan memahami loop pemilihan serta eksekusi tool. Sampai jumpa!