[利用LangGraph SDK调用部署的Agent-01] 以dev模式部署一个简单的Agent Server
不论我们采用那种形式的开发方式(LangChain、LangGraph和Deep Agents),最终创建的Agent都体现为一个CompiledStateGraph对象,CompiledStateGraph派生于Pregel类型。我们最终需要利用LangSmith对它进行部署,它提供Agent在生产环境中大规模可靠运行所需的托管基础架构,支持从本地开发到部署的完整生命周期。LangSmith不仅仅限于针对自家开发框架的支持,它可以用来部署LangGraph和其他框架构建的Agent。所谓针对Agent部署,本质上就是创建一个Web Server,并对外暴露一系列RESTful API使我们可以通过HTTP请求与Agent进行交互。
这个系列旨在通过一系列具体的实例演示介绍客户端如何以Web的形式与部署的Agent Server进行交互,但在这之前,我们得有一个可供调用的Agent Server。为了让读者朋友们如何与Agent Server之间的交互有一个总体的认识,我们会先部署一个简单的Agent Server,然后演示利用LangGraph SDK来调用Agent Server暴露出来的RESTful API。
1. 定义和部署Graph
为了我们构建了一个极简的Agent服务器,根目录下只有如下所示的几个必要的文件:
root/ ├── .env # 存放环境变量 ├── langgraph.json # 配置Graph ├── agent.py # 定义Graph └── pyproject.toml # 项目配置文件从部署的角度来说,我们之前所谓的Agent在这里被统一称为Graph,虽然它是StateGraph编译后的产物,自身是一个Actor模型。但是我们依然习惯称之为Graph,毕竟从图的角度去理解Agent的执行流程比从Actor模型的角度更为直观。
我们在agent.py中定义了一个Graph用来提供指定城市实时的天气信息,并在此基础上提供着装建议。我们调用的是“和风天气”提供的API,相应的URL和API Key等信息我们都放在了.env文件中,该文件中也存放了与模型和LangSmith相关的环境变量。agent.py文件的内容如下所示:利用create_agent函数创建了一个Agent注册了两个工具,get_weather根据指定的位置编码查询实时天气信息,指定城市的地理位置编码则由look_up_location工具查询获得。
fromtypingimportCallable,Anyfromlangchain.agentsimportcreate_agentfromlangchain.toolsimporttoolfromlangchain_openaiimportChatOpenAIfromrequestsimportResponseimportrequests,osdefinvoke(url:str,params:dict,extract_result:Callable[[Response],Any])->Any:response=requests.get(headers={"X-QW-Api-Key":os.getenv("QW_API_KEY")},url=url,params=params)ifresponse.status_code==200:returnextract_result(response)else:raiseException(f"请求失败,状态码:{response.status_code}")@tooldeflook_up_location(city:str)->str:"""查询指定城市的地理位置 Args: city (str): 城市名称,例如 "北京" 或 "beijing" """returninvoke(url=os.getenv("QW_LOCATION_LOOKUP_URL",""),params={"location":city},extract_result=lambdaresponse:response.json()["location"][0]["id"])@tooldefget_weather(location:str)->dict:"""获取指定位置的实时天气信息 Args: location (str): 工具look_up_location返回的指定城市的地理位置 """returninvoke(url=os.getenv("QW_WEATHER_URL",""),params={"location":location},extract_result=lambdaresponse:response.json()["now"])graph=create_agent(model=ChatOpenAI(model="gpt-5.2-chat"),tools=[look_up_location,get_weather],system_prompt=("作为一个出行Assistant,提供指定程序实时天气和着装建议"),)上面定义的这个Graph以如下的形式配置在langgraph.json文件中,Graph ID被命名为test_agent:
{"dependencies":["."],"graphs":{"test_agent":"./agent.py:graph"},"env":".env"}我们执行命令行langgraph dev以dev模式部署我们定义的Agent,并启动作为宿主的Web服务器。
Langgraph Server启动成功后会输出相关的访问信息,包括API的URL、Studio UI的URL以及API文档的URL等:
- 🚀 API: http://127.0.0.1:2024
- 🎨 Studio UI: https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:2024
- 📚 API Docs: http://127.0.0.1:2024/docs
2. 利用Studio UI测试
我们也可以直接访问Studio UI来测试我们部署的Agent,Studio UI提供了一个可视化的界面来与Agent进行交互,非常适合我们在开发阶段进行调试和测试。Studio UI提供了Graph和Chat两种模式,前者以图形化的方式展示Agent的执行流程,后者则以对话的形式展示Agent的输入输出和工具调用等信息。我们可以根据自己的需求选择不同的模式来观察Agent的行为。为了测试我们部署的Agent是否能够正常工作,我们可以在Studio UI中输入如下的测试指令:
3. 编写客户端程序测试
我们也可以利用LangGraph SDK编写客户端程序来测试我们部署的Graph。下面是一个简单的客户端程序示例:我们将LangGraph服务器的URL作为参数调用get_client函数来创建一个LangGraphClient对象,然后调用runs.wait方法调用部署的Agent。虽然LangGraphClient.runs.wait方法返回的数据结构与CompiledStateGraph.ainvoke方法返回的数据结构基本一致。但是返回的消息是一个单纯的字典,而不是BaseMessage对象。所以我们需要定义一个辅助函数as_message来将字典转换为BaseMessage对象,以便我们能够利用BaseMessage提供的pretty_print方法来更友好地展示消息内容。
fromtypingimportAnyfromlanggraph_sdkimportget_clientfromlangchain_core.messagesimportHumanMessage,AIMessage,ToolMessageimportasyncio client=get_client(url="http://localhost:2024")defas_message(message:dict[str,Any])->HumanMessage|AIMessage|ToolMessage:type=message.get("type")cls=HumanMessageiftype=="human"elseAIMessageiftype=="ai"elseToolMessagereturncls(**message)asyncdefmain():result=awaitclient.runs.wait(thread_id=None,assistant_id="test_agent",input={"messages":[{"role":"user","content":"苏州目前天气如何?我该穿什么?"}]})formessageinresult["messages"]:# type: ignoreas_message(message).pretty_print()asyncio.run(main())上面的演示程序将整个流程生成的消息都打印了出来,我们可以清晰地看到Agent的执行流程,包括工具调用和工具返回的结果等信息。
================================ Human Message ================================= 苏州目前天气如何?我该穿什么? ================================== Ai Message ================================== Tool Calls: look_up_location (call_kHtMWKQVws3zkPEnXREn0sOb) Call ID: call_kHtMWKQVws3zkPEnXREn0sOb Args: city: 苏州 ================================= Tool Message ================================= Name: look_up_location 101190401 ================================== Ai Message ================================== Tool Calls: get_weather (call_8MFOH4LlTsFTHCi56bbpMwLF) Call ID: call_8MFOH4LlTsFTHCi56bbpMwLF Args: location: 101190401 ================================= Tool Message ================================= Name: get_weather {"obsTime": "2026-04-25T19:40+08:00", "temp": "19", "feelsLike": "16", "icon": "150", "text": "晴", "wind360": "91", "windDir": "东风", "windScale": "3", "windSpeed": "19", "humidity": "54", "precip": "0.0", "pressure": "1014", "vis": "29", "cloud": "91", "dew": "8"} ================================== Ai Message ================================== 苏州**目前实时天气**(更新时间:4月25日 19:40)如下: 🌤 **天气状况**:晴 🌡 **气温**:19℃ 🤔 **体感温度**:16℃ 💨 **风**:东风 3级,风速约19 km/h 💧 **湿度**:54% ☔ **降水**:无 👀 **能见度**:29 km --- ### 👕 穿衣建议 现在是**傍晚偏凉**,而且有风,建议: - ✅ **上身**:长袖衬衫 / 薄卫衣 / 薄针织衫 - ✅ **外搭**:轻薄外套或风衣(防风很重要) - ✅ **下身**:长裤(牛仔裤、休闲裤都合适) - ✅ **鞋子**:运动鞋或休闲鞋 👉 **怕冷的人**:可以选择稍厚一点的外套 👉 **夜间外出**:温度还可能再降1–2℃,不建议穿短袖 如果你是**通勤、旅游还是夜跑**,我也可以帮你更具体地搭配 😊