Build a LangChain AI Agent in 20 Minutes: Step‑by‑Step Guide
This tutorial walks through creating a LangChain‑based AI agent by covering model integration, tool definition with @tool, short‑ and long‑term memory handling via checkpointers and vector stores, and assembling everything with create_agent, middleware, and code examples for a functional travel assistant.
LangChain and LangGraph version shift
Since LangChain 1.0, LangGraph is the low‑level orchestration engine for stateful, multi‑turn agents, while LangChain provides higher‑level abstractions, tool integration and convenient agent building.
Model invocation
LangChain supplies integration packages for many providers. Example using DeepSeek:
from langchain_deepseek import ChatDeepSeek
model = ChatDeepSeek(
model="...",
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2,
api_key=os.getenv("DEEPSEEK_API_KEY")
)Standard OpenAI‑compatible call:
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
model="deepseek-chat",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
temperature=0.7
)Invoke with invoke or stream to get responses.
Tool definition
Use the @tool decorator with explicit name, description and parameter metadata ( Annotated, Field) so the model can select the correct tool.
from langchain_core.tools import tool
from typing import Annotated
from pydantic import Field
@tool(name_or_callable="get_weather", description="Get weather for a city on a specific date")
def get_weather(
destination: Annotated[str, Field(description="City name, e.g., 'Xi'an'")],
date: Annotated[str, Field(description="Date in YYYY‑MM‑DD format")]
) -> str:
return f"{destination} {date} weather is sunny"
@tool(name_or_callable="get_attractions", description="Get popular attractions for a city")
def get_attractions(
destination: Annotated[str, Field(description="City name, e.g., 'Beijing'")]
) -> str:
return f"{destination} popular attractions are: Forbidden City, Summer Palace, Temple of Heaven."Agent creation
Create an agent with create_agent (ReAct mode). Provide the model and the list of tools.
from langchain.agents import create_react_agent
tools = [get_weather, get_attractions]
agent = create_agent(model=model, tools=tools)
messages = {
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "I want to travel to Beijing. Can you check the weather and attractions?"}
]
}
result = agent.invoke(messages)
print(result["messages"][-1].content)ReAct workflow:
Model receives user messages, performs reasoning, decides whether a tool is needed.
If a tool is required, the model outputs a tool‑call command; the framework executes the tool and appends the result as a new message.
The updated message list is fed back to the model until a final answer is produced.
Short‑term memory
Persisted via the Checkpointer mechanism. Providing a consistent thread_id (or configurable dict) enables the agent to recall previous turns.
from langgraph.checkpoint.memory import InMemorySaver
agent = create_agent(..., checkpointer=InMemorySaver())
config = {"configurable": {"thread_id": "1"}}
result = agent.invoke(input=messages, config=config)In production replace InMemorySaver with PostgresSaver or SqliteSaver for persistence.
Long‑term memory (vector store)
Use a vector database (e.g., Chroma) with an embedding model (e.g., DashScope) to store and retrieve conversation history.
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_chroma import Chroma
from langchain_core.documents import Document
embeddings = DashScopeEmbeddings(
model="text-embedding-v4",
dashscope_api_key=os.getenv("DASHSCOPE_API_KEY")
)
vectorstore = Chroma(
embedding_function=embeddings,
persist_directory="./chroma_db",
collection_name="chat_history"
)Save a turn:
def save_messages(messages: str, user_id: int, session_id: int):
doc = Document(page_content=messages, metadata={"user_id": user_id, "session_id": session_id})
vectorstore.add_documents([doc])Load relevant history for a new query (optional user_id and session_id filters):
def load_messages(query: str, user_id: int = None, session_id: int = None):
filters = []
if user_id:
filters.append({"user_id": user_id})
if session_id:
filters.append({"session_id": session_id})
if len(filters) > 1:
filter_dict = {"$and": filters}
elif filters:
filter_dict = filters[0]
else:
filter_dict = None
if filter_dict:
docs = vectorstore.similarity_search(query=query, k=3, filter=filter_dict)
else:
docs = vectorstore.similarity_search(query=query, k=3)
return docsMiddleware for long‑term memory
Define a middleware that fetches relevant documents and appends them to the prompt before each model call.
@wrap_model_call
def add_long_memory(request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse]) -> ModelResponse:
message = request.messages[-1]
if message.type == "human":
docs = load_messages(
message.content,
config["configurable"]["user_id"],
config["configurable"]["session_id"]
)
extra = "
".join([doc.page_content for doc in docs])
request.messages.append(ChatMessage(content=extra, role="system"))
return handler(request)Attach the middleware when creating the agent:
agent = create_agent(
llm,
tools=tools,
middleware=[add_long_memory()],
checkpointer=InMemorySaver()
)Full example
config = {
"configurable": {"thread_id": "1", "user_id": 1, "session_id": 1}
}
llm = ChatOpenAI(
model="deepseek-chat",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
temperature=0.7
)
messages = {
"messages": [
{"role": "system", "content": "You are a travel planning assistant."},
{"role": "user", "content": user_message}
]
}
tools = [get_weather, get_attractions]
agent = create_agent(
llm,
tools=tools,
middleware=[add_long_memory()],
checkpointer=InMemorySaver()
)
result = agent.invoke(input=messages, config=config)
ai_message = result["messages"][-1].content
save_messages(messages=user_message + ai_message, user_id=config["configurable"]["user_id"], session_id=config["configurable"]["session_id"])Conclusion
The essential components of a LangChain agent are model, tools and memory. LangChain abstracts model differences, exposes functionality as tools with rich metadata, and provides both short‑term (checkpointer) and long‑term (vector store + middleware) memory mechanisms. Combining these enables a stateful AI assistant with minimal boilerplate.
SpringMeng
Focused on software development, sharing source code and tutorials for various systems.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
