LangGraph SDK 全量技术手册:分布式 Agent 集群的远程调用与编排引擎
1. 技术概论
LangGraph SDK 是与 LangGraph Server / LangGraph Cloud 进行交互的官方客户端库(提供 Python 与 JavaScript 版本)。其核心价值在于实现 Agent 逻辑的前后端分离与分布式部署。通过该 SDK,开发者无需在业务服务中直接运行沉重的图计算逻辑,而是通过统一的 REST/WebSocket API 远程管理助手(Assistants)、线程(Threads)、运行实例(Runs)以及跨会话存储(Store),是构建高并发、可扩展企业级 AI 智能体服务的标准调用协议。
2. 全量 API 指南与组件字典(强类型版)
本节覆盖 langgraph_sdk 中的核心模块及全量 API 操作,主要基于异步客户端 AsyncLangGraphClient(同步客户端方法签名一致)。
2.1 客户端初始化与全局配置
| API 原型 | 参数说明 | 输入/输出 | 功能简述 |
|---|---|---|---|
get_client(url: str, *, headers: dict = None) -> AsyncLangGraphClient |
url: Server 地址 headers: 认证头(如 API Key) |
出: 异步客户端实例 | 初始化异步客户端,与 LangGraph 部署环境建立连接。 |
get_sync_client(url: str, *, headers: dict = None) -> LangGraphClient |
同上 | 出: 同步客户端实例 | 初始化同步客户端,适用于传统的阻塞式后台任务。 |
2.2 助手管理 API (client.assistants)
助手(Assistant)是基于特定图逻辑(Graph)和配置初始化的代理实例。
| API 原型 | 主要参数说明 | 输入/输出 | 功能简述 |
|---|---|---|---|
create |
graph_id: 部署的图名称, config: 模型/提示词等配置 |
出 : 助手实例 (Assistant) |
实例化助手。基于一个通用的逻辑图,创建一个带有特定"个性"或"参数"的独立助手。 |
get |
assistant_id: 助手唯一 ID |
出 : 助手详情 (Assistant) |
获取详情。查询特定助手的基本信息、关联图 ID 及其默认配置参数。 |
search |
graph_id: 按图过滤, metadata: 按标签搜索 |
出 : 助手列表 (List[Assistant]) |
资产盘点。在系统中分页查找符合条件的助手实例。 |
update |
config: 新的模型配置, metadata: 新标签 |
出: 更新后的实例 | 配置变更。在不改变图逻辑的前提下,动态调整助手的底层模型、参数或元数据。 |
delete |
assistant_id: 助手唯一 ID |
出 : 无 (None) |
实例销毁。下线并删除指定的助手配置实例。 |
get_graph |
assistant_id: 助手唯一 ID |
出 : 序列化图拓扑 (dict) |
结构可视化 。获取图的节点和连线数据,常用于前端生成流程图或 Mermaid 代码。 |
get_schemas |
assistant_id: 助手唯一 ID |
出: JSON Schema 字典 | 协议定义。获取该助手运行所需的输入/输出数据结构,方便前端进行表单校验。 |
2.3 线程与记忆管理 API (client.threads)
线程(Thread)是维护多轮对话和 Agent 长时记忆的独立上下文容器。
| API 原型 | 主要参数说明 | 输入/输出 | 功能简述 |
|---|---|---|---|
create |
metadata: 业务标签, thread_id: 可选 ID |
出 : 线程实例 (Thread) |
创建隔离上下文。为新的用户对话或任务建立独立的"记忆沙箱"。 |
get |
thread_id: 唯一标识 |
出 : 线程实例 (Thread) |
查询元数据。获取线程的创建时间、配置和业务标签信息。 |
search |
status: "idle"/"busy", limit: 数量限制 |
出 : 线程列表 (List[Thread]) |
批量检索。根据运行状态或自定义元数据筛选系统中的线程。 |
update |
metadata: 要覆盖或新增的标签 |
出: 更新后的实例 | 属性维护。修改线程的外部描述信息,不干预内部业务逻辑。 |
delete |
thread_id: 线程标识 |
出 : 无 (None) |
彻底销毁。删除线程及其所有的状态快照、运行记录和物理存储。 |
get_state |
thread_id: 线程标识 |
出 : 状态快照 (StateSnapshot) |
获取实时快照。查看当前程序运行到了哪个节点,以及当前的全局变量值。 |
update_state |
values: 注入的数据, as_node: 触发节点名 |
出 : 更新响应 (dict) |
外部干预。手动修改线程状态,常用于**人工审核(Human-in-the-loop)**场景。 |
get_history |
before: 起始快照, limit: 历史深度 |
出 : 快照列表 (List[Snapshot]) |
回溯历史 。获取状态演进的时间轴,是实现"版本回滚 "或"时间旅行"的基础。 |
2.4 执行引擎 API (client.runs)
运行(Run)是在特定线程上触发助手执行的单次动作。
| API 原型 | 主要参数说明 | 输入/输出 | 功能简述 |
|---|---|---|---|
stream |
stream_mode: "values"(状态), "messages"(消息), "events"(事件) |
出 : 异步事件流生成器 (AsyncIterator) |
触发图执行,并建立长连接实时接收图状态变更或 LLM Token 流。 |
wait |
thread_id, assistant_id, input |
出 : 最终状态字典 (dict) |
阻塞式触发执行,直至图运行结束(达到 END 或被中断)并返回最终结果。 |
create |
input: 初始数据, webhook: 回调 URL |
出 : 运行实例 (Run) |
异步提交后台任务,立即返回任务句柄,可通过 Webhook 接收完成通知。 |
batch |
thread_ids: 线程列表, inputs: 输入列表 |
出 : 运行实例列表 (List[Run]) |
并发向多个线程提交批量执行任务,适用于大规模离线数据处理。 |
join |
thread_id: 线程 ID, run_id: 任务 ID |
出 : 最终状态字典 (dict) |
阻塞等待 之前由 create 提交的后台任务,直到其执行完毕并获取结果。 |
cancel |
run_id: 执行任务标识, wait: 是否同步等待 |
出 : 无 (None) |
强制终止正在执行的任务,用于手动干预或释放计算资源。 |
list |
limit: 分页大小, offset: 偏移量 |
出 : 任务历史列表 (List[Run]) |
查询并获取指定线程下所有运行过的任务记录及其状态。 |
2.5 跨会话存储与定时任务 (Store & Crons)
| API 原型 | 参数说明 | 输入/输出 | 功能简述 |
|---|---|---|---|
client.store.put_item(namespace: Tuple[str], key: str, value: dict) -> None |
namespace: 层级命名空间 key: 键名 value: 存储载荷 |
出 : None |
在全局 Store 中持久化与特定用户或组织相关联的记忆数据,跨 Thread 共享。 |
client.store.search_items(namespace_prefix: Tuple[str], limit: int) -> List[Item] |
namespace_prefix: 命名空间前缀 |
出: 存储项列表 | 依据命名空间前缀搜索全局记忆/配置数据。 |
client.crons.create(thread_id: str, assistant_id: str, schedule: str, input: dict) -> Cron |
schedule: Cron 表达式 (如 0 8 * * *) |
出: Cron 实例 | 创建一个定时任务,按照设定的频率自动在指定线程中触发 Agent 执行。 |
3. 应用场景与典型案例
3.1 场景一:构建实时流式对话后端 (Streaming)
前端需要打字机效果,后端通过 SDK 桥接 LangGraph Server 并通过 Server-Sent Events (SSE) 转发。
python
from langgraph_sdk import get_client
async def chat_stream(thread_id: str, user_message: str):
client = get_client("http://localhost:8123")
input_data = {"messages": [{"role": "user", "content": user_message}]}
# 监听 messages 流模式,仅获取大模型的生成 token
async for chunk in client.runs.stream(
thread_id,
assistant_id="my_assistant",
input=input_data,
stream_mode="messages"
):
if chunk.event == "messages/partial":
yield chunk.data[0]["content"]
3.2 场景二:人在回路的人工干预注入 (Human-in-the-loop)
当获取到线程状态为"挂起"时,管理员调用 SDK 更新状态并唤醒图继续执行。
python
async def approve_action(thread_id: str, is_approved: bool):
client = get_client("http://localhost:8123")
# 将人工决策注入系统状态中
await client.threads.update_state(
thread_id,
values={"approval_status": "approved" if is_approved else "rejected"},
as_node="human_reviewer" # 伪装成挂起的审查节点产生的数据
)
# 恢复执行:传入 None 作为 input
await client.runs.wait(thread_id, assistant_id="my_assistant", input=None)
3.3 场景三:后台自动化与 Webhook 回调
触发长时间分析任务,避免阻塞主线程,依靠 Server 进行 Webhook 通知。
python
async def trigger_report_generation(thread_id: str, data_url: str):
client = get_client("http://localhost:8123")
run = await client.runs.create(
thread_id,
assistant_id="data_analyst",
input={"data_url": data_url},
webhook="https://my-backend.com/api/webhooks/langgraph"
)
return run.run_id
4. 常见问题与解决方案
- 异常现象: 运行
client.runs.wait()时长时间阻塞直至触发TimeoutError。- 核心原因: 远端 Agent 内部发生死循环(如由于 ReAct 路由逻辑缺陷导致的无限次工具调用),或者图代码执行极其耗时的操作。
- 修正建议: 在调用时指定超时控制配置:
client.runs.wait(..., config={"configurable": {"timeout_seconds": 60}})。
- 异常现象:
update_state后再次触发图运行,发现系统似乎忽略了更新的状态,又从头开始运行或报错。- 核心原因:
as_node参数错误或未提供。若图在节点A前挂起,此时手动更新状态应表现为节点A执行完毕,因此需要明确指定as_node="A"。 - 修正建议: 先通过
get_state获取挂起的next节点,然后在update_state中将其设为as_node。
- 核心原因:
- 异常现象: 使用同步客户端
get_sync_client在 FastAPI 或 Asyncio 循环中报错:RuntimeError: This event loop is already running。- 核心原因:
httpx同步客户端和异步环境冲突。 - 修正建议: 在任何基于
asyncio的框架(FastAPI, Sanic)中,严禁使用get_sync_client,必须全局使用get_client及await调用。
- 核心原因:
5. 零门槛全闭环实战项目:异步流式 Agent 中台网关
项目背景
构建一个企业级的中间层网关(基于 FastAPI)。该网关不对内承载任何 LLM 算力,而是使用 LangGraph SDK 连接独立的 LangGraph Server 集群。网关负责创建会话线程、触发分析任务,并将远端 Server 传回的状态流(State Values)转换为 SSE(Server-Sent Events)推送给前端应用。
环境搭建 (Conda)
bash
# 创建网关环境
conda create -n graph_gateway python=3.11 -y
conda activate graph_gateway
# 安装 FastAPI, Uvicorn, LangGraph SDK 及 SSE 支持
pip install fastapi uvicorn langgraph-sdk sse-starlette
前置说明:假设 LangGraph Server 已经运行在 http://localhost:8123 且注册了名为 agent 的 assistant。
架构可视化
HTTP POST
SDK: create_thread
SDK: stream_runs
Chunked State Events
SSE Streaming
Web/Mobile Client
FastAPI Gateway
LangGraph Server
LLM / Tools Execution
全量源码
gateway_app.py
python
import json
from typing import AsyncGenerator
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from sse_starlette.sse import EventSourceResponse
from langgraph_sdk import get_client, AsyncLangGraphClient
# 1. 声明数据模型
class ChatRequest(BaseModel):
message: str
class ThreadResponse(BaseModel):
thread_id: str
# 2. 初始化应用与 SDK 客户端
app = FastAPI(title="LangGraph Agent Gateway")
LANGGRAPH_URL = "http://localhost:8123"
ASSISTANT_ID = "agent" # 需在 Server 中预先配置的图标识
def get_lg_client() -> AsyncLangGraphClient:
"""获取 LangGraph SDK 异步客户端"""
return get_client(url=LANGGRAPH_URL)
# 3. 会话管理接口:创建新线程
@app.post("/api/threads", response_model=ThreadResponse)
async def create_new_thread():
client = get_lg_client()
try:
thread = await client.threads.create()
return ThreadResponse(thread_id=thread["thread_id"])
except Exception as e:
raise HTTPException(status_code=500, detail=f"无法连接到计算节点: {str(e)}")
# 4. 核心流式接口:触发 Agent 并转发状态流
@app.post("/api/threads/{thread_id}/chat_stream")
async def chat_with_agent_stream(thread_id: str, request: ChatRequest):
client = get_lg_client()
# 验证线程是否存在
try:
await client.threads.get(thread_id)
except Exception:
raise HTTPException(status_code=404, detail="会话不存在")
# 构建输入载荷 (符合 LangGraph State 定义)
payload = {"messages": [{"role": "user", "content": request.message}]}
async def sse_generator() -> AsyncGenerator[dict, None]:
try:
# 调用 SDK 建立流式连接 (使用 values 模式监听全量状态变更)
async for chunk in client.runs.stream(
thread_id=thread_id,
assistant_id=ASSISTANT_ID,
input=payload,
stream_mode="values"
):
# chunk.data 包含当前图的完整状态字典
# 将状态打包为 SSE 格式向前端推送
yield {
"event": chunk.event,
"data": json.dumps(chunk.data, ensure_ascii=False)
}
# 运行结束标志
yield {"event": "done", "data": "[DONE]"}
except Exception as e:
yield {"event": "error", "data": str(e)}
return EventSourceResponse(sse_generator())
# 5. 状态透视接口:获取会话当前记忆与挂起状态
@app.get("/api/threads/{thread_id}/state")
async def get_thread_state(thread_id: str):
client = get_lg_client()
try:
state_snapshot = await client.threads.get_state(thread_id)
return {
"values": state_snapshot["values"],
"next_nodes": state_snapshot["next"],
"created_at": state_snapshot["created_at"]
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# 6. 项目启动入口
if __name__ == "__main__":
import uvicorn
# 运行网关服务器
uvicorn.run(app, host="0.0.0.0", port=8000)
预期输出
模拟前端调用网关(需保持 LangGraph Server 开启):
- 创建会话:
bash
curl -X POST http://localhost:8000/api/threads
# 输出: {"thread_id":"11223344-5566-7788-9900-aabbccddeeff"}
- 发起流式聊天:
bash
curl -N -X POST http://localhost:8000/api/threads/11223344-5566-7788-9900-aabbccddeeff/chat_stream \
-H "Content-Type: application/json" \
-d '{"message": "你好,请查询今天的天气"}'
流式输出截取:
event: metadata
data: {"run_id": "...", "thread_id": "..."}
event: values
data: {"messages": [{"content": "你好,请查询今天的天气", "role": "user"}]}
event: values
data: {"messages": [{"content": "你好,请查询今天的天气", "role": "user"}, {"content": "", "tool_calls": [...], "role": "assistant"}]}
event: done
data: [DONE]
6. 核心总结
LangGraph SDK 将复杂的图计算状态机逻辑封装在 REST/WebSocket 通信层之下。其核心范式为:创建 Thread(沙箱) -> 使用 Assistant(逻辑模版) -> 触发 Run(计算实例) -> 监听 Stream / Wait(状态获取)。通过将图的执行部署在远端 Server 并通过 SDK 交互,开发团队可以轻松实现 AI 算力与业务网关的解耦,为高并发、高可用性的 Multi-Agent 系统奠定了工程基础。