- Fetch and preprocess documents for retrieval.
- Index those documents for semantic search and create a retriever tool for the agent.
- Build an agentic RAG system that can decide when to use the retriever tool.

Concepts
This tutorial covers the following concepts:Setup
Install the required packages and set your API keys:Set up LangSmith
RAG applications run retrieval and generation in sequence. When you run the examples in this tutorial, LangSmith logs a trace for each query so you can inspect retrieval, tool calls, and model responses. After you sign up for LangSmith, set your environment variables to start logging traces:Preprocess documents
1
Fetch documents
Use three posts from Lilian Weng’s blog. Fetch page content with a minimal helper built on
requests and BeautifulSoup.2
Split documents
Split the fetched documents into smaller chunks for indexing into the vector store:
Create a retriever tool
Index the split documents into a vector store for semantic search.1
Index documents
Use an in-memory vector store and OpenAI embeddings:
2
Create the retriever tool
Create a retriever tool using the
@tool decorator:3
Test the tool
Generate a query or respond
With the retriever tool ready, start building the agent as a LangGraph graph. In the Graph API, a graph is made of:-
State: Shared data that nodes read and update. This tutorial uses
MessagesState, which stores amessageslist of chat messages. - Nodes: Functions that take the current state, run a step (for example, call a model or a tool), and return state updates.
- Edges: Connections that define which node runs next, including conditional edges that branch based on the state.
1
Build the node
Build a
generate_query_or_respond node that calls the model on the current messages and binds the retriever_tool with .bind_tools:2
Try a simple greeting
3
Ask a retrieval question
Ask a question that requires semantic search:Output:
Grade documents
A normal edge always sends the graph to the same next node. A conditional edge chooses the next node at runtime by running a function over the current state. After retrieval, use that pattern to grade whether the documents are relevant: continue to answer generation if they are, or rewrite the question and try again if they are not.1
Add document grading
Add a
grade_documents routing function that uses a model with a structured output schema GradeDocuments. It returns the name of the next node based on the grading decision (generate_answer or rewrite_question):2
Test with irrelevant documents
Run this with irrelevant documents in the tool response:
3
Test with relevant documents
Confirm that relevant documents are classified as such:
Rewrite the question
If the grader marks the retrieved documents as irrelevant, the graph should not answer from that context. Instead, rewrite the original user question into a clearer search query, then send control back to the generate-query-or-respond node so the agent can retrieve again. This retry loop is how the agent recovers from a weak first retrieval instead of stopping or hallucinating an answer.1
Build the rewrite node
Build the
rewrite_question node to improve the original user question when retrieval misses:2
Try it out
Generate an answer
When the grader accepts the retrieved documents, the graph moves to answer generation. This node is the classic RAG step: combine the original user question with the tool message that holds the retrieved context, then ask the model to produce a grounded reply. Keep the prompt tight so the model answers from the provided context instead of inventing details.1
Build the answer node
Build the
generate_answer node to produce the final reply from the question and retrieved context:2
Try it
Assemble the graph
Assemble the nodes and edges into a complete graph:- Start with
generate_query_or_respondand determine whether to callretriever_tool. - Route to the next step based on whether the model made tool calls:
- If
generate_query_or_respondreturnedtool_calls, callretriever_toolto retrieve context. - Otherwise, respond directly to the user.
- If
- Grade retrieved document content for relevance to the question (
grade_documents) and route to the next step:- If not relevant, rewrite the question using
rewrite_questionand then callgenerate_query_or_respondagain. - If relevant, proceed to
generate_answerand generate the final response using the ToolMessage with the retrieved document context.
- If not relevant, rewrite the question using

Run the agentic RAG
Test the complete graph by running it with a question:See also
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

