Step 1: The Problem: A Stateless Agent
Why memory matters
The default LangGraph agent is stateless. Each agent.invoke() call starts fresh — the agent has no knowledge of what was said before. For a sales assistant, this means:
Turn 1: "I just called Acme Corp — Sarah is the VP, she's worried about integration."
→ Agent: "Got it, I can help with integration concerns."
Turn 2: "What did Sarah care about?"
→ Agent: "I'm sorry, I don't have any information about Sarah. Can you share more context?"
Every conversation starts from zero. Unusable in production.
What we'll build across this lab
Production agents need two kinds of memory:
| Type | Scope | Use case | Our implementation |
|---|---|---|---|
| Short-term | Within one conversation | Remember what we just discussed | LangGraph MemorySaver + thread_id |
| Long-term | Across all conversations | Remember facts permanently | Milvus vector store |
For step 1, we'll build the broken baseline — an agent with no memory — to see the problem firsthand. Then each subsequent step adds a layer.
How create_agent works without a checkpointer
from langchain.agents import create_agent
agent = create_agent(model=llm, tools=[])
# Each call is independent — no shared state
agent.invoke({"messages": [{"role": "user", "content": "My name is Alice"}]})
agent.invoke({"messages": [{"role": "user", "content": "What is my name?"}]})
# Agent: "I don't know your name."
The fix in later steps will be a checkpointer argument that persists state keyed by thread_id.
Your task
Create agent_no_memory.py:
- Create a
ChatNVIDIALLM pointed at the NIM proxy (usemeta/llama-3.3-70b-instruct) - Build a
create_agentwithout a checkpointer — justmodel=llm, tools=[] - Run a 2-turn conversation demonstrating the problem:
- Turn 1: Tell the agent about a client (name, role, concern)
- Turn 2: Ask the agent to recall what the client cared about
- Print both responses so you can see the agent fails to remember
This sets up the baseline we'll improve in step 2.
NCP-AAI exam note: Cognition, Planning & Memory is 10% of the exam. Key concept: agents are stateless by default — all context must be explicitly passed in the
messageslist. Understanding when you need to add memory vs. pass context via tools is a core design decision.
agent_no_memory.py, the file you edit32 lines
# Step 1: The Stateless Baseline — demonstrates the problem
from langchain_nvidia_ai_endpoints import ChatNVIDIA
from langchain.agents import create_agent
# TODO: Create ChatNVIDIA LLM
# base_url = "http://nim-proxy.labs.svc:8080/v1"
# model = "meta/llama-3.3-70b-instruct"
# temperature = 0
llm = ______
# TODO: Build an agent with NO checkpointer — just model and empty tools list
agent = ______
# Turn 1 — tell the agent about a client
print("--- Turn 1 ---")
r1 = agent.invoke({"messages": [{
"role": "user",
"content": "I just got off a call with Acme Corp. Their VP, Sarah, is interested but worried about integration time."
}]})
print(f"User: I just got off a call with Acme Corp...")
print(f"Agent: {r1['messages'][-1].content[:200]}")
# Turn 2 — ask it to recall (it will fail)
print("\n--- Turn 2 ---")
r2 = agent.invoke({"messages": [{
"role": "user",
"content": "What was Sarah's main concern?"
}]})
print(f"User: What was Sarah's main concern?")
print(f"Agent: {r2['messages'][-1].content[:200]}")
print("\n(The agent has no memory of turn 1 — that's the problem we'll fix next.)")