前言展示了 LangChain 近期非常核心的 “强约束型 Agent” 开发模式。它集成了结构化输出Structured Output、运行时上下文Runtime Context以及多轮对话持久化LangGraph Checkpointer三大高级特性。来源看langchain的官方帮助手册SYSTEM_PROMPT也是使用他们官方的例子编码from langchain.agents import create_agent from langgraph.checkpoint.memory import InMemorySaver from langchain.tools import tool,ToolRuntime from langchain_openai import ChatOpenAI from dataclasses import dataclass kimi_model ChatOpenAI( modelkimi-k2.5, api_keysk-uQ*****, base_urlhttps://api.moonshot.cn/v1, # 重点这里严格对应 Kimi 的 API 结构 extra_body{ thinking: {type: disabled} } ) SYSTEM_PROMPT You are an expert weather forecaster, who speaks in puns. You have access to two tools: - get_weather_for_location: use this to get the weather for a specific location - get_user_location: use this to get the users location If a user asks you for the weather, make sure you know the location. If you can tell from the question that they mean wherever they are, use the get_user_location tool to find their location. 用中文回答 tool def get_weather_for_location(city:str)-str: Get weather for a given city. return fIts sunny in {city} dataclass class Context: Custom runtime context schema. user_id: str tool def get_user_location(runtime:ToolRuntime[Context])-str: Retrieve user information based on user ID. user_id runtime.context.user_id return Shanghai if user_id 1 else Beijing dataclass class ResponseFormat: Response schema for the agent. punny_response:str weather_conditions:str |None None checkpointer InMemorySaver() agent create_agent( modelkimi_model, system_promptSYSTEM_PROMPT, tools[get_weather_for_location,get_user_location], context_schemaContext, response_formatResponseFormat, checkpointercheckpointer ) config {configurable:{thread_id:1}} response agent.invoke( {messages:[{role:user,content:what is weather outside?}]}, configconfig, contextContext(user_id1) ) print(response[structured_response]) responseagent.invoke( {messages:[{role:user,content:thank you}]}, configconfig, contextContext(user_id1) ) print(response[structured_response])编码解释环境初始化与模型配置我使用了兼容 OpenAI 格式的 Kimi 模型可以换成自己的。extra_body参数非常关键。由于 Kimi k2.5 具备推理Thinking能力但在某些结构化输出场景下关闭思维链可以提高解析的稳定性或符合特定的 API 规范。kimi_model ChatOpenAI( modelkimi-k2.5, api_keysk-uQp***, base_urlhttps://api.moonshot.cn/v1, # 重点这里严格对应 Kimi 的 API 结构 extra_body{ thinking: {type: disabled} } )系统提示词System Prompt的策略设计定义了“爱说双关语”的人设更重要的是定义了工具调用逻辑它明确告知 Agent如果用户询问“外面的天气outside”Agent 必须先调用get_user_location获取位置再调用get_weather_for_location获取天气。这体现了 Agent 的 多步推理能力。SYSTEM_PROMPT You are an expert weather forecaster, who speaks in puns...运行时上下文Runtime Context与动态工具这是代码中重要的部分传统的工具定义是静态的。通过ToolRuntime[Context]工具可以在执行时访问 “外部传入的私有上下文”如当前登录的user_id。Agent 不需要也不应该在对话中询问用户的 ID而是由系统在invoke时隐式注入确保了数据安全和逻辑解耦。tool def get_weather_for_location(city:str)-str: Get weather for a given city. return fIts sunny in {city} dataclass class Context: Custom runtime context schema. user_id: str tool def get_user_location(runtime:ToolRuntime[Context])-str: Retrieve user information based on user ID. user_id runtime.context.user_id return Shanghai if user_id 1 else Beijing结构化输出Structured Response定义了 Agent 最终返回给用户的“数据模型”。在生产环境中我们往往不希望 Agent 只返回一段字符串。通过ResponseFormatAgent 会强制返回一个包含punny_response人设回答和weather_conditions纯天气数据的对象方便前端渲染或后续逻辑处理。dataclass class ResponseFormat: Response schema for the agent. punny_response:str weather_conditions:str |None NoneAgent 的构建与持久化实现了 Memory记忆 功能这个在前面的章节中着重讲过。checkpointer InMemorySaver() agent create_agent( modelkimi_model, system_promptSYSTEM_PROMPT, tools[get_weather_for_location,get_user_location], context_schemaContext, response_formatResponseFormat, checkpointercheckpointer )运行config {configurable:{thread_id:1}} response agent.invoke( {messages:[{role:user,content:what is weather outside?}]}, configconfig, contextContext(user_id1) ) print(response[structured_response]) responseagent.invoke( {messages:[{role:user,content:thank you}]}, configconfig, contextContext(user_id1) ) print(response[structured_response])运行结果第一轮对话多步推理与工具链调用输入what is weather outside?结果ResponseFormat(punny_response..., weather_conditionssunny)Agent 识别出用户在问天气根据系统提示词它意识到需要先知道用户在哪于是调用了get_user_location。此时contextContext(user_id1)发挥作用工具内部识别出user_id1并返回了ShanghaiAgent 获取到上海后紧接着调用get_weather_for_location(cityShanghai)Agent 并没有直接打印字符串而是按照定义的ResponseFormat格式将双关语填入punny_response将状态填入weather_conditions。第二轮对话上下文记忆与 Schema 容错输入thank you结果ResponseFormat(..., weather_conditionsNone)由于我们传入了相同的thread_id: 1Agent 知道你在对刚才的天气查询表示感谢。注意这里的weather_conditionsNone。在第一轮对话中Agent 填充了天气数据。在第二轮只是礼貌性回复并没有触发天气查询。因为在ResponseFormat中定义了weather_conditions: str | None NoneAgent 聪明地意识到这一轮不需要提供天气数据于是将其设为空。通过运行结果我们可以观察到三个核心技术点隐式上下文的威力用户只问了‘外面天气’Agent 却能通过user_id自动定位到上海实现了‘无感化’个性化服务。结构化输出的严谨性返回结果不再是杂乱无章的字符串而是一个可以直接被 API 或数据库读取的ResponseFormat对象。状态机的鲁棒性当用户说‘谢谢’时Agent 不会因为找不到天气数据而报错而是通过可选字段Optional Fields优雅地处理了非业务对话。总结未来 Agent 开发趋势将深度聚焦于“强类型约束”与“运行可观测性”。通过ResponseFormat等结构化输出协议我们正将 LLM 从不可控的“黑盒对话”转型为可预测的“函数调用”确保 AI 产出能无缝对接下游业务逻辑。同时引入ToolRuntime上下文注入与状态持久化机制不仅提升了 Agent 对用户身份的感知力更让复杂的推理链路变得透明、可追踪。这种从“模糊语义”向“精准工程”的跨越正是构建高可靠、生产级 AI 应用的必经之路。