{"id":119876,"date":"2026-10-07T16:35:29","date_gmt":"2026-10-07T11:05:29","guid":{"rendered":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/"},"modified":"2026-10-07T16:40:40","modified_gmt":"2026-10-07T11:10:40","slug":"langgraph-tutorial-how-to-build-a-stateful-ai-agent","status":"publish","type":"post","link":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/","title":{"rendered":"LangGraph Tutorial: Build a Stateful AI Agent"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.mygreatlearning.com\/blog\/ai-agents-across-enterprise-systems\/\">Building an AI agent<\/a> is more than connecting an <a href=\"https:\/\/www.mygreatlearning.com\/blog\/what-is-llm\/\">LLM<\/a> to a <a href=\"https:\/\/www.mygreatlearning.com\/blog\/prompt-engineering-complete-guide\/\">prompt<\/a>. As soon as an application needs to plan a task, call a tool, retain intermediate results, and use those results to produce an answer, the workflow becomes stateful.<\/p>\n\n\n\n<p>This is where LangGraph becomes useful.<\/p>\n\n\n\n<p>In this <a href=\"https:\/\/www.langchain.com\/langgraph\"><strong>LangGraph<\/strong><\/a><strong> tutorial<\/strong>, you will build a small but complete <a href=\"https:\/\/www.mygreatlearning.com\/blog\/what-are-ai-agents\/\">AI agent<\/a> in <a href=\"https:\/\/www.mygreatlearning.com\/blog\/python\/\">Python<\/a> with three nodes:<\/p>\n\n\n\n<p><strong>Plan \u2192 Tool Call \u2192 Answer<\/strong><\/p>\n\n\n\n<p>The workflow will accept a user request, create a structured plan, call a tool based on that plan, and use the tool result to generate the final response.&nbsp;<\/p>\n\n\n\n<p>This fixed workflow provides a simple foundation for understanding how LangGraph manages <strong>state, nodes, tools, and execution flow<\/strong>.<\/p>\n\n\n\n<p>You will then extend the basic workflow with <strong>persistence and conditional routing<\/strong> to show how LangGraph can move toward more agentic behavior, where the next step can depend on the current state and model output.<\/p>\n\n\n\n<p>The final workflow will look like this:<\/p>\n\n\n<figure class=\"wp-block-image size-large zoomable\" data-full=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12.png\"><img decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12-1024x683.png\" alt=\"\" class=\"wp-image-119878\" srcset=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12-1024x683.png 1024w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12-300x200.png 300w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12-768x512.png 768w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12-150x100.png 150w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-12.png 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>By the end, you will have a working LangGraph application that you can extend with more tools, conditional routing, memory, human approval, or additional agent steps.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-langgraph-and-why-is-it-used-for-stateful-ai-agents\"><strong>What Is LangGraph and Why Is It Used for Stateful AI Agents?<\/strong><\/h2>\n\n\n\n<p><a href=\"https:\/\/www.langchain.com\/langgraph\"><strong>LangGraph<\/strong><\/a><strong> is a framework for building stateful AI agents and multi-step LLM workflows.<\/strong> It models an AI application as a graph of <strong>nodes and edges<\/strong>, with shared state used to store and pass information between steps.&nbsp;<\/p>\n\n\n\n<p>This allows developers to build agents that can <strong>plan tasks, call tools, make decisions, maintain context, and execute complex workflows<\/strong> in a controlled manner.<\/p>\n\n\n\n<p>LangGraph is particularly useful when an AI application needs explicit control over its execution flow.&nbsp;<\/p>\n\n\n\n<p>Developers can define what each step does, determine what happens next, and preserve relevant information throughout the workflow, making it well suited for <strong>tool-using agents, conditional workflows, and stateful AI applications<\/strong>.<\/p>\n\n\n\n<p>If you want to build practical skills with LangGraph, explore <a href=\"https:\/\/www.mygreatlearning.com\/academy\/learn-for-free\/courses\/ai-agent-workflows-using-langgraph?utm_source=blog\"><strong>Great Learning\u2019s AI Agents in LangGraph<\/strong><\/a>. It covers LangGraph fundamentals, graph-based workflows, stateful AI agents, and multi-agent orchestration using Python.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"1-set-up-the-langgraph-project\"><strong>1. Set Up the LangGraph Project<\/strong><\/h2>\n\n\n\n<p>We will use Python and an OpenAI-compatible chat model through <a href=\"https:\/\/docs.langchain.com\/oss\/python\/integrations\/llms\/openai\">LangChain's OpenAI integration<\/a>.<\/p>\n\n\n\n<p><strong>Create a project directory:<\/strong><\/p>\n\n\n\n<div id=\"copy-6acb9e56a014e\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>mkdir langgraph-agent\ncd langgraph-agent<\/code><\/pre><\/div>\n\n\n\n<p>Create a virtual environment:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0161\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>python -m venv .venv<\/code><\/pre><\/div>\n\n\n\n<p>Activate it on macOS or Linux:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a016a\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>source .venv\/bin\/activate<\/code><\/pre><\/div>\n\n\n\n<p>On Windows:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0172\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>.venv\\Scripts\\activate<\/code><\/pre><\/div>\n\n\n\n<p>Install the required packages:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a017a\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>pip install -U langgraph langchain-openai<\/code><\/pre><\/div>\n\n\n\n<p>LangGraph provides the graph orchestration layer, while langchain-openai provides the ChatOpenAI integration used by the example.<\/p>\n\n\n\n<p>Set your API key as an environment variable.<\/p>\n\n\n\n<p>On macOS or Linux:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a01a7\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>export OPENAI_API_KEY=&quot;your-api-key&quot;<\/code><\/pre><\/div>\n\n\n\n<p>On Windows PowerShell:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a01bb\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">bash<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>$env:OPENAI_API_KEY=&quot;your-api-key&quot;<\/code><\/pre><\/div>\n\n\n\n<p>For a real project, store credentials through your environment or secret-management system rather than hard-coding them in Python.<\/p>\n\n\n\n<p>Create an agent.py file:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a01c6\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">folder structure<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>langgraph-agent\/\n\u2502\n\u251c\u2500\u2500 .venv\/\n\u2514\u2500\u2500 agent.py<\/code><\/pre><\/div>\n\n\n\n<p>The rest of the tutorial will be implemented in this file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"2-define-the-state-for-the-agent\"><strong>2. Define the State for the Agent<\/strong><\/h2>\n\n\n\n<p>The first thing to define in a LangGraph workflow is the <strong>state<\/strong>.<\/p>\n\n\n\n<p>State is the shared data that nodes can read and update as the graph executes. LangGraph's documentation recommends keeping state focused on information that needs to persist between steps rather than storing values that can simply be derived again.<\/p>\n\n\n\n<p>For this agent, we need four pieces of information:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The user's request<\/li>\n\n\n\n<li>The plan created by the planning node<\/li>\n\n\n\n<li>The result returned by the tool<\/li>\n\n\n\n<li>The final answer<\/li>\n<\/ul>\n\n\n\n<p>Add the following to agent.py:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a028a\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">from<\/span> typing_extensions <span class=\"kw\">import<\/span> NotRequired, TypedDict\n\n<span class=\"kw\">class<\/span> <span class=\"fn\">AgentState<\/span>(TypedDict):\n    user_request: str\n    plan: NotRequired[str]\n    tool_result: NotRequired[str]\n    answer: NotRequired[str]<\/code><\/pre><\/div>\n\n\n\n<p>The important point is that the nodes do not need to manually pass values to one another.<\/p>\n\n\n\n<p>Instead, they operate on the same state.<\/p>\n\n\n\n<p>Initially, the graph might receive:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a02b7\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>After the planning node executes, the state can become:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a02ed\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>,\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Use the addition tool with 27 and 43.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>After the tool node:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a031f\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>,\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Use the addition tool with 27 and 43.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>Finally, the answer node adds:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0360\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>,\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Use the addition tool with 27 and 43.&quot;<\/span>,\n    <span class=\"st\">&quot;tool_result&quot;<\/span>: <span class=\"st\">&quot;70&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>That is the basic state model behind the agent.<\/p>\n\n\n\n<p>Developers who want to build practical AI agents can explore <a href=\"https:\/\/www.mygreatlearning.com\/academy\/learn-for-free\/courses\/building-intelligent-ai-agents?utm_source=blog\">Great Learning\u2019s Building Intelligent AI Agents course<\/a>, which covers LangGraph implementation, workflow design, and AI agent design patterns.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"3-create-the-plan-tool-and-answer-nodes\"><strong>3. Create the Plan, Tool, and Answer Nodes<\/strong><\/h2>\n\n\n\n<p>Now we can build the three actual nodes.<\/p>\n\n\n\n<p>A LangGraph node is a function that receives the current state and returns updates to that state. Nodes can perform different kinds of work, including LLM calls, API calls, database operations, or other application logic.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"create-the-planning-node\"><strong>Create the Planning Node<\/strong><\/h3>\n\n\n\n<p>For the planning step, we want the LLM to determine which numbers need to be added.<\/p>\n\n\n\n<p>Instead of asking the model to return free-form text and then parsing it ourselves, we can ask it for structured output.<\/p>\n\n\n\n<p>Add these imports:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0378\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">from<\/span> pydantic <span class=\"kw\">import<\/span> BaseModel, Field\n<span class=\"kw\">from<\/span> langchain_openai <span class=\"kw\">import<\/span> ChatOpenAI<\/code><\/pre><\/div>\n\n\n\n<p>Define the planning schema:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a03ab\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">class<\/span> <span class=\"fn\">AdditionPlan<\/span>(BaseModel):\n    first_number: float = <span class=\"fn\">Field<\/span>(description=<span class=\"st\">&quot;The first number to add&quot;<\/span>)\n    second_number: float = <span class=\"fn\">Field<\/span>(description=<span class=\"st\">&quot;The second number to add&quot;<\/span>)<\/code><\/pre><\/div>\n\n\n\n<p>Initialize the model:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a03bd\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>model = <span class=\"fn\">ChatOpenAI<\/span>(model=<span class=\"st\">&quot;gpt-4.1-mini&quot;<\/span>)<\/code><\/pre><\/div>\n\n\n\n<p>Create a structured-output version:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a03c6\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>planner = model.<span class=\"fn\">with_structured_output<\/span>(AdditionPlan)<\/code><\/pre><\/div>\n\n\n\n<p>Now define the planning node:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0412\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">def<\/span> <span class=\"fn\">plan_node<\/span>(state: AgentState):\n    result = planner.<span class=\"fn\">invoke<\/span>(\n        f<span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;\n        Identify the two numbers that need to be added\n        based on the user&#039;s request.\n\n        User request:\n        {state[&quot;<\/span>user_request<span class=\"st\">&quot;]}\n        &quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    )\n\n    plan = (\n        f<span class=\"st\">&quot;Add {result.first_number} &quot;<\/span>\n        f<span class=\"st\">&quot;and {result.second_number}.&quot;<\/span>\n    )\n\n    <span class=\"kw\">return<\/span> {\n        <span class=\"st\">&quot;plan&quot;<\/span>: plan\n    }<\/code><\/pre><\/div>\n\n\n\n<p>The node reads:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0428\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>state[<span class=\"st\">&quot;user_request&quot;<\/span>]<\/code><\/pre><\/div>\n\n\n\n<p>and returns:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0439\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Add 27 and 43.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>It does not need to return the entire state. LangGraph applies the returned update to the existing state.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"create-the-tool\"><strong>Create the Tool<\/strong><\/h3>\n\n\n\n<p>Next, create the actual tool that performs the calculation.<\/p>\n\n\n\n<p>LangChain tools can be defined using the @tool decorator.<\/p>\n\n\n\n<p>Add:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0442\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">from<\/span> langchain.tools <span class=\"kw\">import<\/span> tool<\/code><\/pre><\/div>\n\n\n\n<p>Then define the tool:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0466\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>@tool\n<span class=\"kw\">def<\/span> <span class=\"fn\">add_numbers<\/span>(first_number: float, second_number: float) -&gt; str:\n    <span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;Add two numbers and return the result.&quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    result = first_number + second_number\n    <span class=\"kw\">return<\/span> <span class=\"fn\">str<\/span>(result)<\/code><\/pre><\/div>\n\n\n\n<p>The tool has one simple responsibility: perform the addition.<\/p>\n\n\n\n<p>Now create the tool node:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a04cd\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">def<\/span> <span class=\"fn\">tool_node<\/span>(state: AgentState):\n    plan_result = planner.<span class=\"fn\">invoke<\/span>(\n        f<span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;\n        Extract the two numbers from this plan.\n\n        Plan:\n        {state[&quot;<\/span>plan<span class=\"st\">&quot;]}\n        &quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    )\n\n    result = add_numbers.<span class=\"fn\">invoke<\/span>(\n        {\n            <span class=\"st\">&quot;first_number&quot;<\/span>: plan_result.first_number,\n            <span class=\"st\">&quot;second_number&quot;<\/span>: plan_result.second_number,\n        }\n    )\n\n    <span class=\"kw\">return<\/span> {\n        <span class=\"st\">&quot;tool_result&quot;<\/span>: result\n    }<\/code><\/pre><\/div>\n\n\n\n<p>There is a small design improvement we can make here.<\/p>\n\n\n\n<p>The planning node already has the structured numbers, but our state currently stores only the formatted plan. In a production application, it would be better to store the structured planning result itself rather than reconstructing it from text.<\/p>\n\n\n\n<p>For this tutorial, however, keeping plan as a readable string makes the state easier to inspect.<\/p>\n\n\n\n<p>A production version could instead define:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a04ec\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">class<\/span> <span class=\"fn\">AgentState<\/span>(TypedDict):\n    user_request: str\n    plan: NotRequired[AdditionPlan]\n    tool_result: NotRequired[str]\n    answer: NotRequired[str]<\/code><\/pre><\/div>\n\n\n\n<p>and return the structured object directly from the planning node.<\/p>\n\n\n\n<p>The important principle is to avoid storing information in state merely as formatted prompt text when the raw structured data is more useful. LangGraph's documentation recommends keeping raw data in state and formatting prompts when a node needs them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"create-the-answer-node\"><strong>Create the Answer Node<\/strong><\/h3>\n\n\n\n<p>The final node will use the original request and the tool result to generate the answer.<\/p>\n\n\n\n<p>Add:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0521\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">def<\/span> <span class=\"fn\">answer_node<\/span>(state: AgentState):\n    response = model.<span class=\"fn\">invoke<\/span>(\n        f<span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;\n        Answer the user&#039;s request using the tool result.\n\n        User request:\n        {state[&quot;<\/span>user_request<span class=\"st\">&quot;]}\n\n        Tool result:\n        {state[&quot;<\/span>tool_result<span class=\"st\">&quot;]}\n\n        Give a concise and clear answer.\n        &quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    )\n\n    <span class=\"kw\">return<\/span> {\n        <span class=\"st\">&quot;answer&quot;<\/span>: response.content\n    }<\/code><\/pre><\/div>\n\n\n\n<p>At this point, the three nodes are ready:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a052b\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>plan_node()\n    \u2193\ntool_node()\n    \u2193\nanswer_node()<\/code><\/pre><\/div>\n\n\n\n<p>But defining functions does not create a LangGraph workflow.<\/p>\n\n\n\n<p>We still need to connect them.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"4-connect-the-three-nodes-with-langgraph-edges\"><strong>4. Connect the Three Nodes With LangGraph Edges<\/strong><\/h2>\n\n\n\n<p>Import the graph primitives:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0535\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">from<\/span> langgraph.graph <span class=\"kw\">import<\/span> StateGraph, START, END<\/code><\/pre><\/div>\n\n\n\n<p>Create a graph builder using the state schema:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a053d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>builder = <span class=\"fn\">StateGraph<\/span>(AgentState)<\/code><\/pre><\/div>\n\n\n\n<p>Register the three nodes:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0558\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>builder.<span class=\"fn\">add_node<\/span>(<span class=\"st\">&quot;plan&quot;<\/span>, plan_node)\nbuilder.<span class=\"fn\">add_node<\/span>(<span class=\"st\">&quot;tool&quot;<\/span>, tool_node)\nbuilder.<span class=\"fn\">add_node<\/span>(<span class=\"st\">&quot;answer&quot;<\/span>, answer_node)<\/code><\/pre><\/div>\n\n\n\n<p>Now connect them:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0582\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>builder.<span class=\"fn\">add_edge<\/span>(START, <span class=\"st\">&quot;plan&quot;<\/span>)\nbuilder.<span class=\"fn\">add_edge<\/span>(<span class=\"st\">&quot;plan&quot;<\/span>, <span class=\"st\">&quot;tool&quot;<\/span>)\nbuilder.<span class=\"fn\">add_edge<\/span>(<span class=\"st\">&quot;tool&quot;<\/span>, <span class=\"st\">&quot;answer&quot;<\/span>)\nbuilder.<span class=\"fn\">add_edge<\/span>(<span class=\"st\">&quot;answer&quot;<\/span>, END)<\/code><\/pre><\/div>\n\n\n\n<p>Finally, compile the graph:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a058a\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>graph = builder.<span class=\"fn\">compile<\/span>()<\/code><\/pre><\/div>\n\n\n\n<p>The complete workflow is now:<\/p>\n\n\n<figure class=\"wp-block-image size-large zoomable\" data-full=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13.png\"><img decoding=\"async\" width=\"1024\" height=\"376\" src=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13-1024x376.png\" alt=\"\" class=\"wp-image-119879\" srcset=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13-1024x376.png 1024w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13-300x110.png 300w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13-768x282.png 768w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13-1536x564.png 1536w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13-150x55.png 150w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-13.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Here, the <strong>nodes<\/strong> represent the work and the <strong>edges<\/strong> represent execution flow.<\/p>\n\n\n\n<p>START is the graph's entry point, while END marks completion. StateGraph lets you register nodes and connect them with edges before compiling the workflow into a runnable graph.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"5-run-the-langgraph-agent\"><strong>5. Run the LangGraph Agent<\/strong><\/h2>\n\n\n\n<p>Now invoke the graph with the initial state.<\/p>\n\n\n\n<p>Add:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a05b4\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>result = graph.<span class=\"fn\">invoke<\/span>(\n    {\n        <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>\n    }\n)\n\n<span class=\"fn\">print<\/span>(result[<span class=\"st\">&quot;answer&quot;<\/span>])<\/code><\/pre><\/div>\n\n\n\n<p>The execution follows this sequence:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a05c7\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>User Request\n     \u2502\n     \u25bc\nPlan Node\n     \u2502\n     \u2502  &quot;Add 27 and 43&quot;\n     \u25bc\nTool Node\n     \u2502\n     \u2502  &quot;70&quot;\n     \u25bc\nAnswer Node\n     \u2502\n     \u2502  &quot;27 + 43 equals 70.&quot;\n     \u25bc\nFinal State<\/code><\/pre><\/div>\n\n\n\n<p>The final result contains the state produced by the graph:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0614\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>,\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Add 27.0 and 43.0.&quot;<\/span>,\n    <span class=\"st\">&quot;tool_result&quot;<\/span>: <span class=\"st\">&quot;70.0&quot;<\/span>,\n    <span class=\"st\">&quot;answer&quot;<\/span>: <span class=\"st\">&quot;27 + 43 equals 70.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>The exact wording of the generated plan and answer can vary because those portions are generated by the model.<\/p>\n\n\n\n<p>The important part is the execution path:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a061d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>request \u2192 plan \u2192 tool result \u2192 answer<\/code><\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"6-see-how-state-moves-through-the-agent\"><strong>6. See How State Moves Through the Agent<\/strong><\/h2>\n\n\n\n<p>The easiest way to understand LangGraph is to stop thinking of each node as an isolated function.<\/p>\n\n\n\n<p>Instead, think of the graph as repeatedly transforming shared state.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"before-the-plan-node\"><strong>Before the Plan Node<\/strong><\/h3>\n\n\n\n<div id=\"copy-6acb9e56a062d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>The planning node reads user_request and returns:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a063d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Add 27 and 43.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>LangGraph applies that update to the existing state.<\/p>\n\n\n\n<p>The state becomes:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0655\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>,\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Add 27 and 43.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"after-the-tool-node\"><strong>After the Tool Node<\/strong><\/h3>\n\n\n\n<p>The tool node reads the plan and calls:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a065d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>add_numbers.<span class=\"fn\">invoke<\/span>(...)<\/code><\/pre><\/div>\n\n\n\n<p>It returns:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a066c\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;tool_result&quot;<\/span>: <span class=\"st\">&quot;70&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>The state becomes:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a068d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>,\n    <span class=\"st\">&quot;plan&quot;<\/span>: <span class=\"st\">&quot;Add 27 and 43.&quot;<\/span>,\n    <span class=\"st\">&quot;tool_result&quot;<\/span>: <span class=\"st\">&quot;70&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"after-the-answer-node\"><strong>After the Answer Node<\/strong><\/h3>\n\n\n\n<p>The final node reads the relevant state:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06a4\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>state[<span class=\"st\">&quot;user_request&quot;<\/span>]\nstate[<span class=\"st\">&quot;tool_result&quot;<\/span>]<\/code><\/pre><\/div>\n\n\n\n<p>and returns:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06b5\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>{\n    <span class=\"st\">&quot;answer&quot;<\/span>: <span class=\"st\">&quot;27 + 43 equals 70.&quot;<\/span>\n}<\/code><\/pre><\/div>\n\n\n\n<p>The final state therefore contains the complete execution context.<\/p>\n\n\n\n<p>This is the core idea behind LangGraph:<\/p>\n\n\n\n<p><strong>Nodes perform work. State carries information. Edges control what runs next.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"7-add-persistence-so-the-agent-can-remember-state\"><strong>7. Add Persistence So the Agent Can Remember State<\/strong><\/h2>\n\n\n\n<p>The graph above maintains state during a single graph execution. If you want the graph to <strong>retain state between separate invocations<\/strong>, you need a <strong>checkpointer<\/strong>.<\/p>\n\n\n\n<p>LangGraph supports checkpointers for <strong>short-term, thread-level persistence<\/strong>. A checkpointer saves the graph's state as checkpoints, while a thread_id identifies the conversation or execution thread whose state should be retrieved during a later invocation.<\/p>\n\n\n\n<p>For local development and testing, LangGraph provides InMemorySaver.<\/p>\n\n\n\n<p>First, import it:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06be\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">from<\/span> langgraph.checkpoint.memory <span class=\"kw\">import<\/span> InMemorySaver<\/code><\/pre><\/div>\n\n\n\n<p>Create a checkpointer:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06c6\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>checkpointer = <span class=\"fn\">InMemorySaver<\/span>()<\/code><\/pre><\/div>\n\n\n\n<p>Then compile the graph with the checkpointer:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06cd\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>graph = builder.<span class=\"fn\">compile<\/span>(\n    checkpointer=checkpointer\n)<\/code><\/pre><\/div>\n\n\n\n<p>Next, provide a thread_id when invoking the graph:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06e2\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>config = {\n    <span class=\"st\">&quot;configurable&quot;<\/span>: {\n        <span class=\"st\">&quot;thread_id&quot;<\/span>: <span class=\"st\">&quot;user-123&quot;<\/span>\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p>You can now run the first request:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a06ff\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>result = graph.<span class=\"fn\">invoke<\/span>(\n    {\n        <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>\n    },\n    config\n)\n<span class=\"fn\">print<\/span>(result[<span class=\"st\">&quot;answer&quot;<\/span>])<\/code><\/pre><\/div>\n\n\n\n<p>The graph creates a checkpoint associated with:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0705\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>thread_id = user-123<\/code><\/pre><\/div>\n\n\n\n<p>The same thread can then be used for another invocation:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0723\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>result = graph.<span class=\"fn\">invoke<\/span>(\n    {\n        <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;Subtract 10 from 50.&quot;<\/span>\n    },\n    config\n)\n<span class=\"fn\">print<\/span>(result[<span class=\"st\">&quot;answer&quot;<\/span>])<\/code><\/pre><\/div>\n\n\n\n<p>In this example, the second request explicitly provides both values required for the calculation. This is important because <strong>using the same <\/strong><strong>thread_id<\/strong><strong> does not automatically make the planner understand references to previous results<\/strong>. The planner must be explicitly designed to read relevant information from the persisted state.<\/p>\n\n\n\n<p>For example, a request such as:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a072c\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>&quot;Now subtract 10 from that result.&quot;<\/code><\/pre><\/div>\n\n\n\n<p>would require additional state-aware planning logic to identify what <strong>\"that result\"<\/strong> refers to. Simply adding a checkpointer does not provide that capability automatically.<\/p>\n\n\n\n<p>The checkpointer allows the graph to <strong>save and retrieve state associated with a specific thread<\/strong>, but it should not be confused with a complete long-term memory system.<\/p>\n\n\n\n<p>There is an important distinction:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Short-term memory:<\/strong> preserves state within a specific thread or conversation.<\/li>\n\n\n\n<li><strong>Long-term memory:<\/strong> stores information that can be retrieved across different threads or sessions.<\/li>\n<\/ul>\n\n\n\n<p>For this tutorial, InMemorySaver is sufficient for demonstrating thread-level persistence. However, it stores data in memory and is intended for development and testing rather than production persistence.&nbsp;<\/p>\n\n\n\n<p>For production applications, a durable database-backed checkpointer, such as a PostgreSQL-based implementation, is more appropriate.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"8-understand-what-makes-this-agent-stateful\"><strong>8. Understand What Makes This Agent Stateful<\/strong><\/h2>\n\n\n\n<p>It is tempting to call every multi-step LLM workflow \u201cstateful,\u201d but there are two different ideas involved.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"state-during-a-run\"><strong>State During a Run<\/strong><\/h3>\n\n\n\n<p>Even without a checkpointer, the graph has state:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0731\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Request\n   \u2193\nPlan\n   \u2193\nTool Result\n   \u2193\nAnswer<\/code><\/pre><\/div>\n\n\n\n<p>Each node can access the updates made by earlier nodes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"state-across-runs\"><strong>State Across Runs<\/strong><\/h3>\n\n\n\n<p>With a checkpointer and a thread_id, LangGraph can persist checkpoints and restore the state associated with that thread in later invocations.<\/p>\n\n\n\n<p>The difference is:<\/p>\n\n\n<figure class=\"wp-block-image size-large zoomable\" data-full=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14.png\"><img decoding=\"async\" width=\"1024\" height=\"427\" src=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14-1024x427.png\" alt=\"\" class=\"wp-image-119880\" srcset=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14-1024x427.png 1024w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14-300x125.png 300w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14-768x320.png 768w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14-1536x640.png 1536w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14-150x62.png 150w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-14.png 1942w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Versus:<\/p>\n\n\n<figure class=\"wp-block-image size-large zoomable\" data-full=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15.png\"><img decoding=\"async\" width=\"1024\" height=\"381\" src=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15-1024x381.png\" alt=\"\" class=\"wp-image-119881\" srcset=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15-1024x381.png 1024w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15-300x111.png 300w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15-768x285.png 768w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15-1536x571.png 1536w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15-150x56.png 150w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-15.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>This distinction becomes important when building conversational agents, approval workflows, long-running processes, or applications that need to resume execution.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"9-add-conditional-routing-to-the-agent\"><strong>9. Add Conditional Routing to the Agent<\/strong><\/h2>\n\n\n\n<p>Our current graph always follows the same path:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0736\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan \u2192 Tool \u2192 Answer<\/code><\/pre><\/div>\n\n\n\n<p>Real agents rarely work this way.<\/p>\n\n\n\n<p>An agent may need to choose between multiple tools depending on the request.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n<figure class=\"wp-block-image size-large zoomable\" data-full=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16.png\"><img decoding=\"async\" width=\"1024\" height=\"376\" src=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16-1024x376.png\" alt=\"\" class=\"wp-image-119882\" srcset=\"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16-1024x376.png 1024w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16-300x110.png 300w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16-768x282.png 768w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16-1536x564.png 1536w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16-150x55.png 150w, https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-16.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>LangGraph supports conditional edges for this type of routing. The official Python quickstart demonstrates routing from an LLM node to a tool node or END based on whether a tool call was produced.<\/p>\n\n\n\n<p>For example, you could define:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a075d\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">def<\/span> <span class=\"fn\">route_after_plan<\/span>(state: AgentState):\n    <span class=\"kw\">if<\/span> <span class=\"st\">&quot;search&quot;<\/span> <span class=\"kw\">in<\/span> state[<span class=\"st\">&quot;plan&quot;<\/span>].<span class=\"fn\">lower<\/span>():\n        <span class=\"kw\">return<\/span> <span class=\"st\">&quot;search&quot;<\/span>\n    <span class=\"kw\">return<\/span> <span class=\"st\">&quot;tool&quot;<\/span><\/code><\/pre><\/div>\n\n\n\n<p>Then register the conditional routes:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a077c\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>builder.<span class=\"fn\">add_conditional_edges<\/span>(\n    <span class=\"st\">&quot;plan&quot;<\/span>,\n    route_after_plan,\n    {\n        <span class=\"st\">&quot;tool&quot;<\/span>: <span class=\"st\">&quot;tool&quot;<\/span>,\n        <span class=\"st\">&quot;search&quot;<\/span>: <span class=\"st\">&quot;search&quot;<\/span>\n    }\n)<\/code><\/pre><\/div>\n\n\n\n<p>The graph can now choose the next node based on the current state.<\/p>\n\n\n\n<p>This is where a simple three-node workflow starts becoming an actual agent architecture.<\/p>\n\n\n\n<p>For professionals looking to build a broader technical foundation around these systems, the <a href=\"https:\/\/professional-education-gl.mit.edu\/mit-online-data-science-program?utm_source=blog\">Data Science course from MIT<\/a> covers AI, machine learning, generative AI, and agentic AI, including single- and multi-agent systems and agentic workflows with tools such as LangGraph.<\/p>\n\n\n\n    <div class=\"courses-cta-container\">\n        <div class=\"courses-cta-card\">\n            <div class=\"courses-cta-header\">\n                <div class=\"courses-learn-icon\"><\/div>\n                <span class=\"courses-learn-text\">Explore Data Science Program<\/span>\n            <\/div>\n            <p class=\"courses-cta-title\">\n                <a href=\"https:\/\/professional-education-gl.mit.edu\/mit-online-data-science-program\" class=\"courses-cta-title-link\">MIT Professional Education's Data Science Course<\/a>\n            <\/p>\n            <p class=\"courses-cta-description\">Gain the expertise top companies seek and open doors to Data Science jobs.<\/p>\n            <div class=\"courses-cta-stats\">\n                <div class=\"courses-stat-item\">\n                    <div class=\"courses-stat-icon courses-user-icon\"><\/div>\n                    <span>Duration: 12 weeks<\/span>\n                <\/div>\n                <div class=\"courses-stat-item\">\n                    <div class=\"courses-stat-icon courses-star-icon\"><\/div>\n                    <span>Ratings: 3<\/span>\n                <\/div>\n            <\/div>\n            <a href=\"https:\/\/professional-education-gl.mit.edu\/mit-online-data-science-program\" class=\"courses-cta-button\">\n                Discover the Program\n                <div class=\"courses-arrow-icon\"><\/div>\n            <\/a>\n        <\/div>\n    <\/div>\n\n\n\n<p>The agent starts by creating a plan, passes the required information to the tool node, and then uses the tool result to generate the final answer.<\/p>\n\n\n\n<p>If you want to explore how AI agents are being applied beyond individual workflows, read this guide on <a href=\"https:\/\/www.mygreatlearning.com\/blog\/agentic-ai-for-non-coders\/\">Agentic AI courses for non-coders<\/a> to understand the broader Agentic AI ecosystem and learning paths.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"10-full-langgraph-agent-code\"><strong>10. Full LangGraph Agent Code<\/strong><\/h2>\n\n\n\n<p>Here is the complete version of the basic three-node agent in one file:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a09f6\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\">python<\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code><span class=\"kw\">from<\/span> typing_extensions <span class=\"kw\">import<\/span> NotRequired, TypedDict\n\n<span class=\"kw\">from<\/span> pydantic <span class=\"kw\">import<\/span> BaseModel, Field\n\n<span class=\"kw\">from<\/span> langchain_openai <span class=\"kw\">import<\/span> ChatOpenAI\n<span class=\"kw\">from<\/span> langchain.tools <span class=\"kw\">import<\/span> tool\n\n<span class=\"kw\">from<\/span> langgraph.graph <span class=\"kw\">import<\/span> StateGraph, START, END\n<span class=\"kw\">from<\/span> langgraph.checkpoint.memory <span class=\"kw\">import<\/span> InMemorySaver\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 1. Define the agent state<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\n<span class=\"kw\">class<\/span> <span class=\"fn\">AgentState<\/span>(TypedDict):\n    user_request: str\n    plan: NotRequired[str]\n    tool_result: NotRequired[str]\n    answer: NotRequired[str]\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 2. Initialize the model<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\nmodel = <span class=\"fn\">ChatOpenAI<\/span>(model=<span class=\"st\">&quot;gpt-4.1-mini&quot;<\/span>)\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 3. Define structured plan<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\n<span class=\"kw\">class<\/span> <span class=\"fn\">AdditionPlan<\/span>(BaseModel):\n    first_number: float = <span class=\"fn\">Field<\/span>(\n        description=<span class=\"st\">&quot;The first number to add&quot;<\/span>\n    )\n\n    second_number: float = <span class=\"fn\">Field<\/span>(\n        description=<span class=\"st\">&quot;The second number to add&quot;<\/span>\n    )\n\n\nplanner = model.<span class=\"fn\">with_structured_output<\/span>(AdditionPlan)\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 4. Plan node<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\n<span class=\"kw\">def<\/span> <span class=\"fn\">plan_node<\/span>(state: AgentState):\n    result = planner.<span class=\"fn\">invoke<\/span>(\n        f<span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;\n        Identify the two numbers that need to be added\n        based on the user&#039;s request.\n\n        User request:\n        {state[&quot;<\/span>user_request<span class=\"st\">&quot;]}\n        &quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    )\n\n    <span class=\"kw\">return<\/span> {\n        <span class=\"st\">&quot;plan&quot;<\/span>: (\n            f<span class=\"st\">&quot;Add {result.first_number} &quot;<\/span>\n            f<span class=\"st\">&quot;and {result.second_number}.&quot;<\/span>\n        )\n    }\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 5. Tool<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\n@tool\n<span class=\"kw\">def<\/span> <span class=\"fn\">add_numbers<\/span>(\n    first_number: float,\n    second_number: float\n) -&gt; str:\n    <span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;Add two numbers and return the result.&quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n\n    <span class=\"kw\">return<\/span> <span class=\"fn\">str<\/span>(first_number + second_number)\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 6. Tool node<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\n<span class=\"kw\">def<\/span> <span class=\"fn\">tool_node<\/span>(state: AgentState):\n    plan = planner.<span class=\"fn\">invoke<\/span>(\n        f<span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;\n        Extract the two numbers from this plan.\n\n        Plan:\n        {state[&quot;<\/span>plan<span class=\"st\">&quot;]}\n        &quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    )\n\n    result = add_numbers.<span class=\"fn\">invoke<\/span>(\n        {\n            <span class=\"st\">&quot;first_number&quot;<\/span>: plan.first_number,\n            <span class=\"st\">&quot;second_number&quot;<\/span>: plan.second_number,\n        }\n    )\n\n    <span class=\"kw\">return<\/span> {\n        <span class=\"st\">&quot;tool_result&quot;<\/span>: result\n    }\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 7. Answer node<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\n<span class=\"kw\">def<\/span> <span class=\"fn\">answer_node<\/span>(state: AgentState):\n    response = model.<span class=\"fn\">invoke<\/span>(\n        f<span class=\"st\">&quot;&quot;<\/span><span class=\"st\">&quot;\n        Answer the user&#039;s request using the tool result.\n\n        User request:\n        {state[&quot;<\/span>user_request<span class=\"st\">&quot;]}\n\n        Tool result:\n        {state[&quot;<\/span>tool_result<span class=\"st\">&quot;]}\n\n        Give a concise and clear answer.\n        &quot;<\/span><span class=\"st\">&quot;&quot;<\/span>\n    )\n\n    <span class=\"kw\">return<\/span> {\n        <span class=\"st\">&quot;answer&quot;<\/span>: response.content\n    }\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 8. Build the graph<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\nbuilder = <span class=\"fn\">StateGraph<\/span>(AgentState)\n\nbuilder.<span class=\"fn\">add_node<\/span>(<span class=\"st\">&quot;plan&quot;<\/span>, plan_node)\nbuilder.<span class=\"fn\">add_node<\/span>(<span class=\"st\">&quot;tool&quot;<\/span>, tool_node)\nbuilder.<span class=\"fn\">add_node<\/span>(<span class=\"st\">&quot;answer&quot;<\/span>, answer_node)\n\nbuilder.<span class=\"fn\">add_edge<\/span>(START, <span class=\"st\">&quot;plan&quot;<\/span>)\nbuilder.<span class=\"fn\">add_edge<\/span>(<span class=\"st\">&quot;plan&quot;<\/span>, <span class=\"st\">&quot;tool&quot;<\/span>)\nbuilder.<span class=\"fn\">add_edge<\/span>(<span class=\"st\">&quot;tool&quot;<\/span>, <span class=\"st\">&quot;answer&quot;<\/span>)\nbuilder.<span class=\"fn\">add_edge<\/span>(<span class=\"st\">&quot;answer&quot;<\/span>, END)\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 9. Add persistence<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\ncheckpointer = <span class=\"fn\">InMemorySaver<\/span>()\n\ngraph = builder.<span class=\"fn\">compile<\/span>(\n    checkpointer=checkpointer\n)\n\n\n<span class=\"cm\"># -----------------------------<\/span>\n<span class=\"cm\"># 10. Run the agent<\/span>\n<span class=\"cm\"># -----------------------------<\/span>\n\nconfig = {\n    <span class=\"st\">&quot;configurable&quot;<\/span>: {\n        <span class=\"st\">&quot;thread_id&quot;<\/span>: <span class=\"st\">&quot;demo-thread&quot;<\/span>\n    }\n}\n\nresult = graph.<span class=\"fn\">invoke<\/span>(\n    {\n        <span class=\"st\">&quot;user_request&quot;<\/span>: <span class=\"st\">&quot;What is 27 + 43?&quot;<\/span>\n    },\n    config\n)\n\n<span class=\"fn\">print<\/span>(<span class=\"st\">&quot;Final answer:&quot;<\/span>)\n<span class=\"fn\">print<\/span>(result[<span class=\"st\">&quot;answer&quot;<\/span>])<\/code><\/pre><\/div>\n\n\n\n<p>The important architecture is not the calculator itself. The calculator is deliberately simple so that the graph mechanics remain visible.<\/p>\n\n\n\n<p>The reusable pattern is:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a0a\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Input\n  \u2193\nPlanning Node\n  \u2193\nTool Node\n  \u2193\nAnswer Node\n  \u2193\nOutput<\/code><\/pre><\/div>\n\n\n\n<p>You can replace the calculator with a database lookup, search API, CRM operation, internal service, code execution tool, or another application-specific function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"11-how-to-extend-this-langgraph-agent\"><strong>11. How to Extend This LangGraph Agent<\/strong><\/h2>\n\n\n\n<p>Once the basic workflow works, you can expand it without changing the fundamental state-node-edge model.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"add-more-tools\"><strong>Add More Tools<\/strong><\/h3>\n\n\n\n<p>Instead of one tool:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a15\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan\n  \u2193\nTool<\/code><\/pre><\/div>\n\n\n\n<p>you can create:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a1e\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan\n  \u2193\nRouter\n \u251c\u2500\u2500 Search Tool\n \u251c\u2500\u2500 Calculator\n \u251c\u2500\u2500 Database\n \u2514\u2500\u2500 API\n  \u2193\nAnswer<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"add-validation\"><strong>Add Validation<\/strong><\/h3>\n\n\n\n<p>A validation node can check whether the tool result is usable:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a25\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan\n \u2193\nTool\n \u2193\nValidate\n \u251c\u2500\u2500 Valid \u2192 Answer\n \u2514\u2500\u2500 Invalid \u2192 Tool<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"add-human-approval\"><strong>Add Human Approval<\/strong><\/h3>\n\n\n\n<p>For sensitive operations, the graph can pause for human input using LangGraph's interrupt functionality and resume from the saved state. LangGraph's persistence model is designed to support these pause-and-resume workflows.<\/p>\n\n\n\n<p>A workflow could become:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a2c\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan\n  \u2193\nTool\n  \u2193\nHuman Approval\n  \u2193\nAnswer<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"add-error-recovery\"><strong>Add Error Recovery<\/strong><\/h3>\n\n\n\n<p>Production agents also need to handle failures.<\/p>\n\n\n\n<p>A temporary network error might be retried, while a user-fixable problem might require additional input. LangGraph supports node-level retry policies and workflows that can route based on errors or human input.<\/p>\n\n\n\n<p>The graph therefore becomes more than a sequence of LLM calls. It becomes an explicit execution model.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"12-best-practices-for-building-langgraph-agents\"><strong>12. Best Practices for Building LangGraph Agents<\/strong><\/h2>\n\n\n\n<p>A few design principles become important as the graph grows.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"keep-state-focused\"><strong>Keep State Focused<\/strong><\/h3>\n\n\n\n<p>Do not put every possible value into state.<\/p>\n\n\n\n<p>Store information that downstream nodes actually need. If something can be derived cheaply from existing state, it usually does not need its own state field. LangGraph's documentation specifically recommends designing state around information that must persist between steps.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"keep-nodes-focused\"><strong>Keep Nodes Focused<\/strong><\/h3>\n\n\n\n<p>A node should have a clear responsibility.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a34\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan Node  \u2192 Decide what needs to happen\nTool Node  \u2192 Perform the operation\nAnswer Node \u2192 Produce the response<\/code><\/pre><\/div>\n\n\n\n<p>This makes the workflow easier to test and debug.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"store-raw-data-where-possible\"><strong>Store Raw Data Where Possible<\/strong><\/h3>\n\n\n\n<p>Avoid filling state with large prompt templates or instructions.<\/p>\n\n\n\n<p>Instead, keep useful raw information in state and construct prompts inside the node that needs them. This keeps the state reusable across different nodes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"use-checkpointers-for-persistent-workflows\"><strong>Use Checkpointers for Persistent Workflows<\/strong><\/h3>\n\n\n\n<p>If an application needs to resume conversations or long-running workflows, compile the graph with an appropriate checkpointer and provide a stable thread_id.<\/p>\n\n\n\n<p>For local experiments, InMemorySaver is useful. For production, use a durable backend such as PostgreSQL rather than relying on in-memory storage.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"make-routing-explicit\"><strong>Make Routing Explicit<\/strong><\/h3>\n\n\n\n<p>As the workflow becomes more complex, make transitions visible through graph edges or explicit routing logic.<\/p>\n\n\n\n<p>A developer should be able to look at the graph and understand:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0a3b\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>What happens first?\nWhat happens next?\nWhen does a tool run?\nWhen can the workflow stop?\nWhen can it loop?<\/code><\/pre><\/div>\n\n\n\n<p>That visibility is one of the main benefits of using a graph-based architecture.<\/p>\n\n\n\n<p>As LangGraph workflows move toward production, developers also need to consider evaluation, security, reliability, and how multiple agentic components work together.&nbsp;<\/p>\n\n\n\n<p>The <a href=\"https:\/\/online.lifelonglearning.jhu.edu\/jhu-certificate-program-applied-generative-ai?utm_source=blog\">Generative AI course Johns Hopkins University<\/a> provides practical coverage of generative AI, agentic workflows, RAG, evaluation, and secure AI development.<\/p>\n\n\n\n    <div class=\"courses-cta-container\">\n        <div class=\"courses-cta-card\">\n            <div class=\"courses-cta-header\">\n                <div class=\"courses-learn-icon\"><\/div>\n                <span class=\"courses-learn-text\">Master Gen AI Skills<\/span>\n            <\/div>\n            <p class=\"courses-cta-title\">\n                <a href=\"https:\/\/online.lifelonglearning.jhu.edu\/jhu-certificate-program-applied-generative-ai\" class=\"courses-cta-title-link\">Certificate Program in Applied Generative AI<\/a>\n            <\/p>\n            <p class=\"courses-cta-description\">Master the tools and techniques behind generative AI with expert-led, project-based training from Johns Hopkins University.<\/p>\n            <div class=\"courses-cta-stats\">\n                <div class=\"courses-stat-item\">\n                    <div class=\"courses-stat-icon courses-user-icon\"><\/div>\n                    <span>Duration: 16 weeks<\/span>\n                <\/div>\n                <div class=\"courses-stat-item\">\n                    <div class=\"courses-stat-icon courses-star-icon\"><\/div>\n                    <span>Weekly Live Sessions<\/span>\n                <\/div>\n            <\/div>\n            <a href=\"https:\/\/online.lifelonglearning.jhu.edu\/jhu-certificate-program-applied-generative-ai\" class=\"courses-cta-button\">\n                Discover the Program\n                <div class=\"courses-arrow-icon\"><\/div>\n            <\/a>\n        <\/div>\n    <\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"conclusion\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>A LangGraph agent does not have to start with a complex multi-agent architecture.<\/p>\n\n\n\n<p>A three-node workflow is enough to understand the core model:<\/p>\n\n\n\n<div id=\"copy-6acb9e56a0aaa\" class=\"copy-code-wrapper\"><div class=\"copy-code-header\"><span class=\"copy-code-lang\"><\/span><button type=\"button\" class=\"copy-button\" aria-label=\"Copy code\"><svg class=\"icon-copy\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M16 1H4C2.9 1 2 1.9 2 3V17H4V3H16V1Z\"\/><path d=\"M20 5H8C6.9 5 6 5.9 6 7V21C6 22.1 6.9 23 8 23H20C21.1 23 22 22.1 22 21V7C22 5.9 21.1 5 20 5ZM20 21H8V7H20V21Z\"\/><\/svg><svg class=\"icon-check\" viewBox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z\"\/><\/svg><span class=\"btn-label\">Copy<\/span><\/button><\/div><pre><code>Plan \u2192 Tool \u2192 Answer<\/code><\/pre><\/div>\n\n\n\n<p>The <strong>state<\/strong> carries information between those steps. The <strong>nodes<\/strong> perform the individual operations. The <strong>edges<\/strong> define how execution moves through the workflow.<\/p>\n\n\n\n<p>In this tutorial, the agent:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Received a user request.<\/li>\n\n\n\n<li>Created a structured plan.<\/li>\n\n\n\n<li>Called a tool based on that plan.<\/li>\n\n\n\n<li>Stored the tool result in state.<\/li>\n\n\n\n<li>Generated an answer using the accumulated state.<\/li>\n\n\n\n<li>Used a checkpointer to demonstrate thread-level persistence.<\/li>\n<\/ol>\n\n\n\n<p>From here, the same architecture can be extended with multiple tools, conditional routing, validation, retries, human approval, and more persistent storage.<\/p>\n\n\n\n<p>The key is to start with a graph that is easy to reason about and add complexity only when the workflow requires it.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn how to build a stateful AI agent with LangGraph and Python. This tutorial covers graph state, nodes, tools, persistence, conditional routing, and practical agent workflows.<\/p>\n","protected":false},"author":41,"featured_media":119887,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_uag_custom_page_level_css":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[36890],"tags":[36910,37007,36796,37006],"content_type":[],"class_list":["post-119876","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-gen-ai","tag-langgraph","tag-langgraph-and-python","tag-python","tag-stateful-ai-agent"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v27.3 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>How to Build a Stateful AI Agent Using LangGraph and Python<\/title>\n<meta name=\"description\" content=\"Learn how to build a stateful AI agent with LangGraph and Python using nodes, state, tools, persistence, and conditional routing.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"LangGraph Tutorial: Build a Stateful AI Agent\" \/>\n<meta property=\"og:description\" content=\"Learn how to build a stateful AI agent with LangGraph and Python using nodes, state, tools, persistence, and conditional routing.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/\" \/>\n<meta property=\"og:site_name\" content=\"Great Learning Blog: Free Resources what Matters to shape your Career!\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/GreatLearningOfficial\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-07T11:05:29+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-07T11:10:40+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1734\" \/>\n\t<meta property=\"og:image:height\" content=\"907\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Great Learning Editorial Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/Great_Learning\" \/>\n<meta name=\"twitter:site\" content=\"@Great_Learning\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Great Learning Editorial Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/\"},\"author\":{\"name\":\"Great Learning Editorial Team\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#\\\/schema\\\/person\\\/6f993d1be4c584a335951e836f2656ad\"},\"headline\":\"LangGraph Tutorial: Build a Stateful AI Agent\",\"datePublished\":\"2026-10-07T11:05:29+00:00\",\"dateModified\":\"2026-10-07T11:10:40+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/\"},\"wordCount\":3710,\"publisher\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/image-17.png\",\"keywords\":[\"LangGraph\",\"langgraph and python\",\"python\",\"stateful ai agent\"],\"articleSection\":[\"Generative AI and Agentic AI\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/\",\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/\",\"name\":\"How to Build a Stateful AI Agent Using LangGraph and Python\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/image-17.png\",\"datePublished\":\"2026-10-07T11:05:29+00:00\",\"dateModified\":\"2026-10-07T11:10:40+00:00\",\"description\":\"Learn how to build a stateful AI agent with LangGraph and Python using nodes, state, tools, persistence, and conditional routing.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/image-17.png\",\"contentUrl\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/10\\\/image-17.png\",\"width\":1734,\"height\":907,\"caption\":\"- Learn how LangGraph uses state, nodes, tools, and graph-based workflows to build stateful AI agents.\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Blog\",\"item\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Generative AI and Agentic AI\",\"item\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/gen-ai\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"LangGraph Tutorial: Build a Stateful AI Agent\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/\",\"name\":\"Great Learning Blog\",\"description\":\"Learn, Upskill &amp; Career Development Guide and Resources\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#organization\"},\"alternateName\":\"Great Learning\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#organization\",\"name\":\"Great Learning\",\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/GL-Logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/GL-Logo.jpg\",\"width\":900,\"height\":900,\"caption\":\"Great Learning\"},\"image\":{\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/GreatLearningOfficial\\\/\",\"https:\\\/\\\/x.com\\\/Great_Learning\",\"https:\\\/\\\/www.instagram.com\\\/greatlearningofficial\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/school\\\/great-learning\\\/\",\"https:\\\/\\\/in.pinterest.com\\\/greatlearning12\\\/\",\"https:\\\/\\\/www.youtube.com\\\/user\\\/beaconelearning\\\/\"],\"description\":\"Great Learning is a leading global ed-tech company for professional training and higher education. It offers comprehensive, industry-relevant, hands-on learning programs across various business, technology, and interdisciplinary domains driving the digital economy. These programs are developed and offered in collaboration with the world's foremost academic institutions.\",\"email\":\"info@mygreatlearning.com\",\"legalName\":\"Great Learning Education Services Pvt. Ltd\",\"foundingDate\":\"2013-11-29\",\"numberOfEmployees\":{\"@type\":\"QuantitativeValue\",\"minValue\":\"1001\",\"maxValue\":\"5000\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/#\\\/schema\\\/person\\\/6f993d1be4c584a335951e836f2656ad\",\"name\":\"Great Learning Editorial Team\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/02\\\/unnamed.webp\",\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/02\\\/unnamed.webp\",\"contentUrl\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/wp-content\\\/uploads\\\/2022\\\/02\\\/unnamed.webp\",\"caption\":\"Great Learning Editorial Team\"},\"description\":\"The Great Learning Editorial Staff includes a dynamic team of subject matter experts, instructors, and education professionals who combine their deep industry knowledge with innovative teaching methods. Their mission is to provide learners with the skills and insights needed to excel in their careers, whether through upskilling, reskilling, or transitioning into new fields.\",\"sameAs\":[\"https:\\\/\\\/www.mygreatlearning.com\\\/\",\"https:\\\/\\\/in.linkedin.com\\\/school\\\/great-learning\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/Great_Learning\",\"https:\\\/\\\/www.youtube.com\\\/channel\\\/UCObs0kLIrDjX2LLSybqNaEA\"],\"award\":[\"Best EdTech Company of the Year 2024\",\"Education Economictimes Outstanding Education\\\/Edtech Solution Provider of the Year 2024\",\"Leading E-learning Platform 2024\"],\"url\":\"https:\\\/\\\/www.mygreatlearning.com\\\/blog\\\/author\\\/greatlearning\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to Build a Stateful AI Agent Using LangGraph and Python","description":"Learn how to build a stateful AI agent with LangGraph and Python using nodes, state, tools, persistence, and conditional routing.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/","og_locale":"en_US","og_type":"article","og_title":"LangGraph Tutorial: Build a Stateful AI Agent","og_description":"Learn how to build a stateful AI agent with LangGraph and Python using nodes, state, tools, persistence, and conditional routing.","og_url":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/","og_site_name":"Great Learning Blog: Free Resources what Matters to shape your Career!","article_publisher":"https:\/\/www.facebook.com\/GreatLearningOfficial\/","article_published_time":"2026-10-07T11:05:29+00:00","article_modified_time":"2026-10-07T11:10:40+00:00","og_image":[{"width":1734,"height":907,"url":"http:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png","type":"image\/png"}],"author":"Great Learning Editorial Team","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/Great_Learning","twitter_site":"@Great_Learning","twitter_misc":{"Written by":"Great Learning Editorial Team","Est. reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#article","isPartOf":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/"},"author":{"name":"Great Learning Editorial Team","@id":"https:\/\/www.mygreatlearning.com\/blog\/#\/schema\/person\/6f993d1be4c584a335951e836f2656ad"},"headline":"LangGraph Tutorial: Build a Stateful AI Agent","datePublished":"2026-10-07T11:05:29+00:00","dateModified":"2026-10-07T11:10:40+00:00","mainEntityOfPage":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/"},"wordCount":3710,"publisher":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png","keywords":["LangGraph","langgraph and python","python","stateful ai agent"],"articleSection":["Generative AI and Agentic AI"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/","url":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/","name":"How to Build a Stateful AI Agent Using LangGraph and Python","isPartOf":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#primaryimage"},"image":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#primaryimage"},"thumbnailUrl":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png","datePublished":"2026-10-07T11:05:29+00:00","dateModified":"2026-10-07T11:10:40+00:00","description":"Learn how to build a stateful AI agent with LangGraph and Python using nodes, state, tools, persistence, and conditional routing.","breadcrumb":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#primaryimage","url":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png","contentUrl":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png","width":1734,"height":907,"caption":"- Learn how LangGraph uses state, nodes, tools, and graph-based workflows to build stateful AI agents."},{"@type":"BreadcrumbList","@id":"https:\/\/www.mygreatlearning.com\/blog\/langgraph-tutorial-how-to-build-a-stateful-ai-agent\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Blog","item":"https:\/\/www.mygreatlearning.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Generative AI and Agentic AI","item":"https:\/\/www.mygreatlearning.com\/blog\/gen-ai\/"},{"@type":"ListItem","position":3,"name":"LangGraph Tutorial: Build a Stateful AI Agent"}]},{"@type":"WebSite","@id":"https:\/\/www.mygreatlearning.com\/blog\/#website","url":"https:\/\/www.mygreatlearning.com\/blog\/","name":"Great Learning Blog","description":"Learn, Upskill &amp; Career Development Guide and Resources","publisher":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/#organization"},"alternateName":"Great Learning","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.mygreatlearning.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.mygreatlearning.com\/blog\/#organization","name":"Great Learning","url":"https:\/\/www.mygreatlearning.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.mygreatlearning.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2022\/06\/GL-Logo.jpg","contentUrl":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2022\/06\/GL-Logo.jpg","width":900,"height":900,"caption":"Great Learning"},"image":{"@id":"https:\/\/www.mygreatlearning.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/GreatLearningOfficial\/","https:\/\/x.com\/Great_Learning","https:\/\/www.instagram.com\/greatlearningofficial\/","https:\/\/www.linkedin.com\/school\/great-learning\/","https:\/\/in.pinterest.com\/greatlearning12\/","https:\/\/www.youtube.com\/user\/beaconelearning\/"],"description":"Great Learning is a leading global ed-tech company for professional training and higher education. It offers comprehensive, industry-relevant, hands-on learning programs across various business, technology, and interdisciplinary domains driving the digital economy. These programs are developed and offered in collaboration with the world's foremost academic institutions.","email":"info@mygreatlearning.com","legalName":"Great Learning Education Services Pvt. Ltd","foundingDate":"2013-11-29","numberOfEmployees":{"@type":"QuantitativeValue","minValue":"1001","maxValue":"5000"}},{"@type":"Person","@id":"https:\/\/www.mygreatlearning.com\/blog\/#\/schema\/person\/6f993d1be4c584a335951e836f2656ad","name":"Great Learning Editorial Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2022\/02\/unnamed.webp","url":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2022\/02\/unnamed.webp","contentUrl":"https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2022\/02\/unnamed.webp","caption":"Great Learning Editorial Team"},"description":"The Great Learning Editorial Staff includes a dynamic team of subject matter experts, instructors, and education professionals who combine their deep industry knowledge with innovative teaching methods. Their mission is to provide learners with the skills and insights needed to excel in their careers, whether through upskilling, reskilling, or transitioning into new fields.","sameAs":["https:\/\/www.mygreatlearning.com\/","https:\/\/in.linkedin.com\/school\/great-learning\/","https:\/\/x.com\/https:\/\/twitter.com\/Great_Learning","https:\/\/www.youtube.com\/channel\/UCObs0kLIrDjX2LLSybqNaEA"],"award":["Best EdTech Company of the Year 2024","Education Economictimes Outstanding Education\/Edtech Solution Provider of the Year 2024","Leading E-learning Platform 2024"],"url":"https:\/\/www.mygreatlearning.com\/blog\/author\/greatlearning\/"}]}},"uagb_featured_image_src":{"full":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png",1734,907,false],"thumbnail":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-150x150.png",150,150,true],"medium":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-300x157.png",300,157,true],"medium_large":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-768x402.png",768,402,true],"large":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-1024x536.png",1024,536,true],"1536x1536":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-1536x803.png",1536,803,true],"2048x2048":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17.png",1734,907,false],"web-stories-poster-portrait":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-640x853.png",640,853,true],"web-stories-publisher-logo":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-96x96.png",96,96,true],"web-stories-thumbnail":["https:\/\/www.mygreatlearning.com\/blog\/wp-content\/uploads\/2026\/10\/image-17-150x78.png",150,78,true]},"uagb_author_info":{"display_name":"Great Learning Editorial Team","author_link":"https:\/\/www.mygreatlearning.com\/blog\/author\/greatlearning\/"},"uagb_comment_info":0,"uagb_excerpt":"Learn how to build a stateful AI agent with LangGraph and Python. This tutorial covers graph state, nodes, tools, persistence, conditional routing, and practical agent workflows.","_links":{"self":[{"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/posts\/119876","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/comments?post=119876"}],"version-history":[{"count":5,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/posts\/119876\/revisions"}],"predecessor-version":[{"id":119906,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/posts\/119876\/revisions\/119906"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/media\/119887"}],"wp:attachment":[{"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/media?parent=119876"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/categories?post=119876"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/tags?post=119876"},{"taxonomy":"content_type","embeddable":true,"href":"https:\/\/www.mygreatlearning.com\/blog\/wp-json\/wp\/v2\/content_type?post=119876"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}