LangChain LangGraph
Module 1 Module 2 Module 3 Module 4 Module 5 Module 6
Module 1 · Basic Introduction
1 1-1 Simple Graph
2 1-2 Chain
3 1-3 Router
4 1-4 Agent
5 1-5 Agent Memory
6 1-6 Deployment
SUM Module Summary
HomeLangGraphModule 1 · Basic Introduction1-6 Deployment
📓 Notebook 📖 Explained
LANGGRAPH MODULE 1 · LESSON 6

Deployment: From local to cloud
Full analysis of LangGraph deployment system

Five core components, SDK call chain, local development process, and how to use a unified interface to seamlessly switch between local and cloud.

1What problem is this lecture going to solve?

In the previous lectures, we built Simple Graph, Chain, Router, and Agent, all of which were passed in Jupyter Notebookgraph.invoke()Synchronous call. This is no problem in the learning stage, but you will encounter several serious problems in the production environment:

questionLimitations of invoke()LangGraph deployment system solution
blocking invoke()It is synchronous. When the Agent runs for several minutes, the caller will wait LangGraph API provides an asynchronous task queue, the caller returns immediately, and the results are pushed through streaming
persistence Requires manual configurationMemorySaver, and is only valid within a single process LangGraph API has a built-in persistence layer that maintains Thread State across processes and restarts.
accessibility Can only be called from Python within the same process HTTP API + SDK, can be called in any language and anywhere
Observability Operation process is opaque LangSmith monitors and tracks input and output at every step
The core of this lecture

Understand the LangGraph deployment systemfive components, andThree core concepts of SDK(Assistant/Thread/Run). Mastering these, you can move the locally debugged Agent to the cloud with one click while maintaining the same calling code.

2Five component hierarchy

The LangGraph deployment system consists of five components, and their hierarchical relationship is as follows: from the lowest Python/JS library, to the API server, to three different access/hosting methods.

LangGraph deployment architecture diagram

📦
LangGraph (library) Python / JavaScript library · Define graph structure, nodes, edges · All the business logic you write is here
Package graph code and expose it as a service
LangGraph API (server) Package the graph into HTTP API · Provide asynchronous task queue · Built-in Thread persistence · Support Streaming
Three ways to use the API
🛠️
LangGraph SDK
Python client library
Programmatic call graph
🎨
LangSmith Studio
Visual IDE
Debug image in browser
☁️
LangSmith Deployment
Cloud hosting services
Deploy from GitHub

Layer-by-layer analysis

componentsessencewhat do you use it for
LangGraph (library) pip install langgraph
Python/JS library
Define StateGraph, add nodes and edges, this is where you write business logic
LangGraph API HTTP server
Can run locally/on the cloud
Wrap your graph into a service that can be called remotely, providing persistence and queues
LangSmith Studio
(formerly LangGraph Studio)
Browser IDE Visually view the structure of the graph, manually test the input, and observe the state changes at each step.
LangSmith Deployment
(formerly LangGraph Cloud)
Managed cloud services Deploy with one click on the LangSmith platform, get a unique URL, and host the LangGraph API
LangGraph SDK pip install langgraph-sdk
Python client
Call the graph programmatically in code (create Thread, initiate Run, obtain Stream)
Tips for naming changes

The LangGraph ecosystem is being deeply integrated with LangSmith. Originally calledLangGraph CloudThe cloud service is now calledLangSmith Deployment; originally calledLangGraph StudioThe IDE is now calledLangSmith Studio. The functions are essentially the same, but the branding is unified.

3Why do you need LangGraph API?

This is a key issue in understanding the entire deployment system. Use directlyinvoke()Isn't it simpler? Let's compare the two ways:

Problem with invoke(): synchronous blocking

# 直接 invoke —— 简单,但在生产环境有严重问题
result = graph.invoke({"messages": [HumanMessage("帮我研究量子计算的最新进展")]})
# ^ 这里会阻塞 5~10 分钟,直到 Agent 完成所有工具调用
# Web 服务器的请求会超时,用户体验极差

Three major capabilities of LangGraph API

Capability 1: Asynchronous task queue

The client returns run_id immediately after initiating the request without blocking. The API executes the graph asynchronously in the background, and the results are pushed to the listener through streaming. Suitable for long-running Agents.

Capability 2: Built-in persistence (Persistence)

API automatically providesThreadMaintain snapshots of state across interactions. No manual configuration requiredMemorySaver, restarting the service will not lose the conversation history. This is the underlying foundation of Memory in Module 2.

Capability 3: Unified HTTP interface

Regardless of whether the graph is run locally (langgraph dev) or the cloud (LangSmith Deployment), all exposed through the same HTTP API. The SDK encapsulates these HTTP calls and allows you to access them elegantly with Python.

# 通过 API 的异步方式 —— 立即返回,streaming 获取结果
async for chunk in client.runs.stream(thread_id, "agent", input=input):
    # 每个图步骤完成后立即收到更新,不阻塞
    print(chunk.data)

4Local development process: langgraph dev

Before deploying the Agent to the cloud, you need to start the LangGraph API server locally so that you can use Studio for visual debugging and use the SDK for integration testing.

studio/ directory structure

Each module has astudio/subdirectory, which is the root directory of the LangGraph API server. The structure is as follows:

module-1/studio/ ├── langgraph.json ← Configuration files: Tell the API server where the graph is ├── agent.py ← Your graph definition code (StateGraph object) ├── router.py ← Another picture (one studio/ can have multiple pictures) ├── requirements.txt ← Dependency declaration └── .env ← Environment variables (OPENAI_API_KEY, etc., don’t commit!)

langgraph.json is the core configuration

// module-1/studio/langgraph.json
{
  "dependencies": ["."],           // 依赖当前目录(读取 requirements.txt)
  "graphs": {
    "agent": "./agent.py:graph",   // 注册图:graph_id → 文件:变量名
    "router": "./router.py:graph"  // 可以注册多个图
  },
  "env": ".env"                   // 环境变量文件路径
}
Key: graph_id

langgraph.jsonofgraphsIn the field, the key name (such as"agent") isgraph_id. SDK callruns.stream()The second parameter passed in is this id. When registering multiple graphs, each has its own id.

Start local server

# 在 studio/ 目录下运行
$ langgraph dev

# 成功启动后输出:
🚀 API: http://127.0.0.1:2024
🎨 Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
How Studio UI works

Note that the Studio URL has parameters?baseUrl=http://127.0.0.1:2024. This means that Studio is a front-end application that runs on the LangSmith server, using thebaseUrlconnect youlocal machineAPI. Your graph code never leaves local - Studio is just a visual frontend.

What can Studio do?

5SDK: Programmatic way to access graphs

LangGraph SDK(pip install langgraph-sdk) is a Python client library that lets you interact with the LangGraph API from code. The core entrance isget_client()

from langgraph_sdk import get_client

# 连接本地开发服务器
URL = "http://127.0.0.1:2024"
client = get_client(url=URL)

# 连接云端部署(切换一行代码即可)
# URL = "https://your-deployment-xxxx.us.langgraph.app"
# client = get_client(url=URL, api_key="lsv2_...")

clientIt is the operation entrance of the entire SDK, through which all resources are accessed:

client
client
Assistant management
client.assistants
Thread management
client.threads
Operation management
client.runs

Complete SDK call example

from langgraph_sdk import get_client
from langchain_core.messages import HumanMessage

# 1. 建立连接
URL = "http://127.0.0.1:2024"
client = get_client(url=URL)

# 2. 查看已注册的图(对应 langgraph.json 里的 graphs)
assistants = await client.assistants.search()
print(assistants)
# [{'assistant_id': '...', 'graph_id': 'agent', ...},
#  {'assistant_id': '...', 'graph_id': 'router', ...}]

# 3. 创建一个对话线程(对应一个持久化的 State 容器)
thread = await client.threads.create()
print(thread['thread_id'])   # 类似 UUID 的字符串

# 4. 在这个线程上发起流式运行
input = {"messages": [HumanMessage(content="Multiply 3 by 2.")]}

async for chunk in client.runs.stream(
    thread['thread_id'],   # 线程 ID
    "agent",              # graph_id(对应 langgraph.json 中的键)
    input=input,
    stream_mode="values",  # 每步后返回完整 State
):
    if chunk.data and chunk.event != "metadata":
        print(chunk.data['messages'][-1])

6Three core concepts: Assistant/Thread/Run

Understanding these three concepts is the basis for making good use of the SDK. They are the resource model of LangGraph API, similar to the three tables in the database.

Assistant

Corresponds to oneRegistered pictures(graph_id). It can be understood as a "configuration instance" of the graph, which can have different versions or different system prompt words, but the underlying structure shares the same graph structure.

every timelanggraph devAfter starting,langgraph.jsonEach picture in it will automatically generate an Assistant.

Thread

Corresponds to onePersistent conversation sessions. There is only onethread_id, sharing the same State across multiple Runs.

Analogy: Thread is like a chat window in WeChat - every message (Run) is accumulated in the same context.

Run

CorrespondA specific graph run. On a Thread, calling an Assistant with specific input generates a Run.

Run can stream (streaming) or wait (wait for completion). The results of each Run are automatically written back to the Thread's State.

The relationship between the three

conceptanalogyKey attributeslife cycle
Assistant A configured Agent service assistant_idgraph_id Exists with the service and is valid for a long time
Thread A conversation session/chat window thread_id, State snapshot Manually created, can span multiple Runs
Run A "send message" action run_id, status, output chunks Single execution, ends after completion
Points of confusion

There can be multiple Runs in a Thread, and the State after each Run ends will be persisted. The next time Run starts, it will continue from the last ended State (this is the implementation principle of Memory). If you want to start a completely new conversation, you need to create a new Thread, not a new Run.

7Streaming operation: detailed explanation of stream_mode

client.runs.stream()Returns an asynchronous iterator, each iteration gets achunkobject.chunkThere are two key fields:chunk.eventandchunk.data

type of chunk.event

Metadata at the start of streaming.chunk.datacontainsrun_id. Usually skipped (chunk.event != "metadata")。
values
After each step of the graph is executed, the current complete State is pushed.chunk.dataIt is the complete State dictionary, such as{"messages": [...]}
end
Signaling the end of the graph run.chunk.datais empty. You can stop monitoring after receiving it.

stream_mode parameter comparison

stream_modeContent pushed each timeApplicable scenarios
"values" After each step is executed, pushComplete current State(includes all fields) Need to display the complete conversation history and monitor the overall status
"updates" After each step is executed, only pushState changes in this step(delta) Reduce the amount of data transferred and only care about new content
"messages" When LLM generates tokenToken by tokenPush (typing effect similar to ChatGPT) Requires streaming display of LLM text output
"debug" Detailed debugging information, pushed for every internal event In-depth debugging and troubleshooting

chunk.data structure of stream_mode="values"

# chunk.event == "values" 时,chunk.data 就是完整 State:
chunk.data = {
    "messages": [
        HumanMessage(content="Multiply 3 by 2."),
        AIMessage(content="", tool_calls=[{
            "name": "multiply",
            "args": {"a": 3, "b": 2}
        }]),
        ToolMessage(content="6"),
        AIMessage(content="3 multiplied by 2 equals 6.")
    ]
}

# 每步执行后都会收到一次这样的 chunk,messages 列表逐步增长
# 所以用 chunk.data['messages'][-1] 只看最新的消息
Practical skills

use stream_mode="values", a complete State will be received at each step, and the message list will grow cumulatively. usechunk.data['messages'][-1]Get the latest news withchunk.event != "metadata"Filter out metadata frames, this is the most common processing mode.

8Local vs. Cloud: Unified Interface for SDK

The most important design concept of LangGraph SDK isLocal development and cloud production use the exact same API. The only difference is the URL and authentication key when connecting.

local development

from langgraph_sdk import get_client

# 本地:只需 URL
client = get_client(
    url="http://127.0.0.1:2024"
)

# 以下代码完全相同 ↓
thread = await client.threads.create()
async for chunk in client.runs.stream(
    thread['thread_id'],
    "agent",
    input=input,
    stream_mode="values",
):
    ...

Cloud production

from langgraph_sdk import get_client

# 云端:URL + API Key
client = get_client(
    url="https://xxx.us.langgraph.app",
    api_key="lsv2_pt_..."
)

# 以下代码完全相同 ↓
thread = await client.threads.create()
async for chunk in client.runs.stream(
    thread['thread_id'],
    "agent",
    input=input,
    stream_mode="values",
):
    ...
The value of unified interfaces

You can use it locallylanggraph devAfter development and debugging, after the code is written, you can switch to the cloud production environment by changing only one line of URL. All business logic code does not need to be modified. This is the essence of deployment system design.

On-Premise vs. Cloud: A Complete Comparison

DimensionsLocal (langgraph dev)Cloud (LangSmith Deployment)
URL format http://127.0.0.1:2024 https://xxx.us.langgraph.app
Certification No need (local development) needapi_key(LangSmith API Key)
Code source Local file system, modifications take effect immediately GitHub repository, trigger deployment after push
persistence Memory or local SQLite, will be lost on restart Cloud persistent storage, permanent storage
Studio access Requires local service to be running Accessible at any time, no local environment required
SDK calling code exactly the same(Only the URL and api_key are different)

9Cloud deployment process (LangSmith Deployment)

After your Agent passes the local test, you can deploy it to the LangSmith cloud to obtain a stable online service address.

1

Prepare GitHub repository

Push the project to GitHub. ensurestudio/Directory containslanggraph.json, graph definition file andrequirements.txtDon'tput.envFile commit goes in.

2

LangSmith → Deployments → New Deployment

Loginsmith.langchain.com, enter the Deployments page, click "New Deployment".

3

Select the warehouse and specify the configuration path

Connect to your GitHub account, select the warehouse, and specifylanggraph.jsonpath (such asmodule-1/studio/langgraph.json). The platform will automatically read the graph configuration.

4

Configure environment variables

Fill in the deployment interfaceOPENAI_API_KEYand other environment variables. This is equivalent to the cloud.envDocuments, securely stored on the LangSmith platform.

5

Wait for deployment to complete and get the URL

The platform automatically pulls code, builds the environment, and starts services. After completion, you will get a unique URL with a similar formathttps://xxx.us.langgraph.app. Replace the URL in the SDK with this URLhttp://127.0.0.1:2024That’s it.

NOTE: Unique URL for each deployment

Each Deployment has an independent and stable URL that will not change due to redeployment. LangSmith supports multiple parallel Deployments (such as staging, production), each environment has its own URL.

10Complete process series

Connect all the knowledge points together and take a look at a complete LangGraph development to deployment process:

Writing graph code (using the LangGraph library)

existstudio/agent.pyDefinitionStateGraph, add nodes and edges, and compile asgraphobject. This is the content of the first five lectures of Module 1.

Configure langgraph.json, register graph

Give the picture a name in the configuration filegraph_id(such as"agent"), pointing toagent.pyinsidegraphvariables.

langgraph dev starts local API + Studio

Visually debug graphs in the browser and use Studio to manually test various inputs to ensure the graph behaves as expected.

Integration testing with SDK

Write Python code, connect to the local API through the SDK, and test Thread creation, Run initiation, and streaming reception. Confirm that the code logic is correct.

Deploy to LangSmith and change the URL

Push the code to GitHub, create a Deployment in LangSmith, and obtain the cloud URL. Only the URL and api_key are changed in the SDK code, and the rest of the business logic remains completely unchanged.

Summary of core design ideas

The core design of LangGraph deployment system isLayered decoupling: You are only responsible for writing graph logic (LangGraph library), LangGraph API is responsible for turning it into an accessible service, SDK is responsible for providing a unified access interface, Studio is responsible for visual debugging, and LangSmith Deployment is responsible for cloud hosting. Each layer has clear responsibilities and can be replaced independently, which greatly improves the Agent development experience.

Knowledge point quick check card

Knowledge pointsWhat to remember
Start local servicelanggraph dev, run in the studio/ directory
Local API addresshttp://127.0.0.1:2024
Where to register pictureslanggraph.jsonofgraphsField, the key name is graph_id
SDK entrancefrom langgraph_sdk import get_client
Three major resourcesAssistants (graph instances) / Threads (dialog sessions) / Runs (single executions)
stream_mode recommended"values": Return the complete State after each step, use[-1]Get the latest news
Skip metadata framechunk.event != "metadata"andchunk.dataNot empty
Switch to the cloudOnly changeurlandapi_key, the business code remains unchanged