🛠️ Lab 3 — Building Short-Term and Long-Term Memory for a LangGraph Agent (50 pts)

Goal: Implement and directly compare the two memory mechanisms from this week's lecture — thread-scoped short-term memory via a LangGraph checkpointer, and cross-session long-term memory via a LangGraph Store — using only free, local tools (Python, built-in SQLite, and either an in-memory store or a local Redis container). Steps:

  1. Set up your environment. In a fresh virtual environment, install langgraph and langchain (and your preferred free/local LLM access — e.g., a locally-served open-weight model, or a free-tier API key you already used in earlier courses). No paid backend is required for this lab.
  2. Build a minimal conversational agent graph. Create a simple LangGraph graph with one or two nodes (e.g., a chatbot node that calls your LLM) so you have something whose state is worth persisting.
  3. Add short-term memory with InMemorySaver. Wire an InMemorySaver checkpointer into your graph. Run a multi-turn conversation under a single thread_id and confirm the agent correctly references earlier turns.
  4. Kill the process, then prove InMemorySaver forgets. Restart your Python process and try to resume the same thread_id. Confirm (and note in your writeup) that the conversation state is gone — this is expected and is the point of the exercise.
  5. Swap in SqliteSaver. Replace InMemorySaver with LangGraph's SqliteSaver, backed by Python's built-in sqlite3 (a local .db file — no server, no external service). Repeat the multi-turn conversation under a thread_id.
  6. Restart the process again and resume by thread_id. This time, confirm the conversation state does survive the restart, because it was checkpointed to disk. Capture the terminal output or a screenshot as evidence.
  7. Build a "remember-my-preferences" agent using a LangGraph Store. Using either the built-in in-memory Store or a local Redis container (e.g., docker run -p 6379:6379 redis) as the backend, write a small agent that: (a) extracts a stated user preference from a conversation (e.g., "I prefer concise answers" or "call me by my first name"), (b) writes it into the store under a namespace/key you design, and (c) in a brand-new session/thread, retrieves and applies that preference without the user restating it.
  8. Contrast the two mechanisms in a short writeup (300–500 words). Explain, in your own words, why SqliteSaver alone would not have solved the preferences problem in Step 7, and why the Store alone would not have solved the multi-turn conversational continuity problem in Steps 3–6.

Deliverables: Submit your commented Python source file(s) or notebook (online_upload), plus your 300–500 word contrast writeup with evidence (terminal output/screenshots) that state survived the restart in Step 6 and that the preference was recalled in a new session in Step 7 (online_text_entry).