[{"data":1,"prerenderedAt":1402},["ShallowReactive",2],{"note:\u002Frag\u002F05_智能体工具与中间件":3},{"id":4,"title":5,"body":6,"date":1382,"description":1383,"draft":1384,"extension":1385,"featured":1384,"kind":1386,"lastmod":1382,"meta":1387,"navigation":157,"path":1391,"planned":1392,"section":1393,"seo":1394,"source":1395,"stem":1396,"tags":1397,"toc":157,"weight":862,"__hash__":1401},"notes\u002Frag\u002F05_智能体工具与中间件.md","Tools、create_agent 与 Middleware",{"type":7,"value":8,"toc":1360},"minimark",[9,21,26,108,118,122,127,130,137,221,224,237,244,250,344,348,352,361,364,417,428,432,435,464,467,501,505,616,622,626,630,633,637,732,736,739,756,959,963,970,1258,1260,1283,1287,1351,1356],[10,11,12],"blockquote",{},[13,14,15,16,20],"p",{},"一句话总结：Tools 是智能体可以调用的外部能力，",[17,18,19],"code",{},"create_agent"," 是 LangChain v1.0 创建智能体的标准 API，Middleware 则是在智能体执行过程中插入业务逻辑的可插拔钩子系统。",[22,23,25],"h2",{"id":24},"_1-组件总览","1. 组件总览",[27,28,29,45],"table",{},[30,31,32],"thead",{},[33,34,35,39,42],"tr",{},[36,37,38],"th",{},"组件",[36,40,41],{},"定位",[36,43,44],{},"核心内容",[46,47,48,67,89],"tbody",{},[33,49,50,54,57],{},[51,52,53],"td",{},"Tools",[51,55,56],{},"智能体可以调用的外部能力",[51,58,59,62,63,66],{},[17,60,61],{},"@tool"," 装饰器、",[17,64,65],{},"BaseTool"," 基类",[33,68,69,71,74],{},[51,70,19],{},[51,72,73],{},"v1.0 创建智能体的标准 API",[51,75,76,79,80,79,83,79,86],{},[17,77,78],{},"model","、",[17,81,82],{},"tools",[17,84,85],{},"prompt",[17,87,88],{},"middleware",[33,90,91,94,97],{},[51,92,93],{},"Middleware",[51,95,96],{},"智能体执行过程中的可插拔钩子系统",[51,98,99,79,102,79,105],{},[17,100,101],{},"PIIMiddleware",[17,103,104],{},"SummarizationMiddleware",[17,106,107],{},"HumanInTheLoopMiddleware",[109,110,116],"pre",{"className":111,"code":113,"language":114,"meta":115},[112],"language-text","用户消息\n    │\n    ▼\ncreate_agent 基础循环\n（模型调用 → 工具执行 → 再次调用模型 → 结束）\n    │\n    ▼\nMiddleware 钩子\nbefore_agent → before_model → wrap_model_call\n→ wrap_tool_call → after_model → after_agent\n    │\n    ▼\n最终回复\n","text","",[17,117,113],{"__ignoreMap":115},[22,119,121],{"id":120},"_2-tools工具","2. Tools（工具）",[123,124,126],"h3",{"id":125},"_21-定位","2.1 定位",[13,128,129],{},"Tools 是智能体可以调用的外部能力，例如查天气、查数据库、发邮件、调用 API。模型本身不会执行工具，它只会决定“调用哪个工具、传什么参数”，真正的执行由 Tools 完成。",[123,131,133,134,136],{"id":132},"_22-使用-tool-装饰器定义工具推荐","2.2 使用 ",[17,135,61],{}," 装饰器定义工具（推荐）",[109,138,142],{"className":139,"code":140,"language":141,"meta":115,"style":115},"language-python shiki shiki-themes github-light github-dark","from langchain.tools import tool\n\n\n@tool\ndef get_weather(city: str) -> str:\n    \"\"\"获取指定城市的天气信息。\"\"\"\n    return f\"{city} 今天晴天，气温 28 摄氏度。\"\n\n\n@tool\ndef send_email(to: str, content: str) -> str:\n    \"\"\"向指定邮箱发送邮件。\"\"\"\n    return f\"邮件已发送至 {to}\"\n","python",[17,143,144,152,159,164,170,176,182,188,193,198,203,209,215],{"__ignoreMap":115},[145,146,149],"span",{"class":147,"line":148},"line",1,[145,150,151],{},"from langchain.tools import tool\n",[145,153,155],{"class":147,"line":154},2,[145,156,158],{"emptyLinePlaceholder":157},true,"\n",[145,160,162],{"class":147,"line":161},3,[145,163,158],{"emptyLinePlaceholder":157},[145,165,167],{"class":147,"line":166},4,[145,168,169],{},"@tool\n",[145,171,173],{"class":147,"line":172},5,[145,174,175],{},"def get_weather(city: str) -> str:\n",[145,177,179],{"class":147,"line":178},6,[145,180,181],{},"    \"\"\"获取指定城市的天气信息。\"\"\"\n",[145,183,185],{"class":147,"line":184},7,[145,186,187],{},"    return f\"{city} 今天晴天，气温 28 摄氏度。\"\n",[145,189,191],{"class":147,"line":190},8,[145,192,158],{"emptyLinePlaceholder":157},[145,194,196],{"class":147,"line":195},9,[145,197,158],{"emptyLinePlaceholder":157},[145,199,201],{"class":147,"line":200},10,[145,202,169],{},[145,204,206],{"class":147,"line":205},11,[145,207,208],{},"def send_email(to: str, content: str) -> str:\n",[145,210,212],{"class":147,"line":211},12,[145,213,214],{},"    \"\"\"向指定邮箱发送邮件。\"\"\"\n",[145,216,218],{"class":147,"line":217},13,[145,219,220],{},"    return f\"邮件已发送至 {to}\"\n",[13,222,223],{},"说明：",[225,226,227,231,234],"ul",{},[228,229,230],"li",{},"函数名会作为工具名。",[228,232,233],{},"函数 docstring 会作为工具描述，供模型判断何时调用。",[228,235,236],{},"函数参数和类型注解会转换为工具的输入结构。",[123,238,240,241,243],{"id":239},"_23-使用-basetool-基类定义工具","2.3 使用 ",[17,242,65],{}," 基类定义工具",[13,245,246,247,249],{},"当工具逻辑复杂，或需要自定义参数校验、异步实现时，可以继承 ",[17,248,65],{},"：",[109,251,253],{"className":139,"code":252,"language":141,"meta":115,"style":115},"from langchain.tools import BaseTool\nfrom pydantic import BaseModel, Field\n\n\nclass WeatherInput(BaseModel):\n    city: str = Field(description=\"要查询天气的城市名称\")\n\n\nclass WeatherTool(BaseTool):\n    name: str = \"get_weather\"\n    description: str = \"获取指定城市的天气信息\"\n    args_schema: type[BaseModel] = WeatherInput\n\n    def _run(self, city: str) -> str:\n        return f\"{city} 今天晴天，气温 28 摄氏度。\"\n\n    async def _arun(self, city: str) -> str:\n        return self._run(city)\n",[17,254,255,260,265,269,273,278,283,287,291,296,301,306,311,315,321,327,332,338],{"__ignoreMap":115},[145,256,257],{"class":147,"line":148},[145,258,259],{},"from langchain.tools import BaseTool\n",[145,261,262],{"class":147,"line":154},[145,263,264],{},"from pydantic import BaseModel, Field\n",[145,266,267],{"class":147,"line":161},[145,268,158],{"emptyLinePlaceholder":157},[145,270,271],{"class":147,"line":166},[145,272,158],{"emptyLinePlaceholder":157},[145,274,275],{"class":147,"line":172},[145,276,277],{},"class WeatherInput(BaseModel):\n",[145,279,280],{"class":147,"line":178},[145,281,282],{},"    city: str = Field(description=\"要查询天气的城市名称\")\n",[145,284,285],{"class":147,"line":184},[145,286,158],{"emptyLinePlaceholder":157},[145,288,289],{"class":147,"line":190},[145,290,158],{"emptyLinePlaceholder":157},[145,292,293],{"class":147,"line":195},[145,294,295],{},"class WeatherTool(BaseTool):\n",[145,297,298],{"class":147,"line":200},[145,299,300],{},"    name: str = \"get_weather\"\n",[145,302,303],{"class":147,"line":205},[145,304,305],{},"    description: str = \"获取指定城市的天气信息\"\n",[145,307,308],{"class":147,"line":211},[145,309,310],{},"    args_schema: type[BaseModel] = WeatherInput\n",[145,312,313],{"class":147,"line":217},[145,314,158],{"emptyLinePlaceholder":157},[145,316,318],{"class":147,"line":317},14,[145,319,320],{},"    def _run(self, city: str) -> str:\n",[145,322,324],{"class":147,"line":323},15,[145,325,326],{},"        return f\"{city} 今天晴天，气温 28 摄氏度。\"\n",[145,328,330],{"class":147,"line":329},16,[145,331,158],{"emptyLinePlaceholder":157},[145,333,335],{"class":147,"line":334},17,[145,336,337],{},"    async def _arun(self, city: str) -> str:\n",[145,339,341],{"class":147,"line":340},18,[145,342,343],{},"        return self._run(city)\n",[22,345,347],{"id":346},"_3-create_agent智能体创建器","3. create_agent（智能体创建器）",[123,349,351],{"id":350},"_31-定位","3.1 定位",[13,353,354,356,357,360],{},[17,355,19],{}," 是 LangChain v1.0 中创建智能体的标准 API，替代旧版的 ",[17,358,359],{},"AgentExecutor + create_react_agent"," 组合。它内置了“模型调用 -> 工具执行 -> 模型再次调用”的基础循环，同时支持通过 Middleware 深度定制。",[13,362,363],{},"核心参数：",[27,365,366,376],{},[30,367,368],{},[33,369,370,373],{},[36,371,372],{},"参数",[36,374,375],{},"作用",[46,377,378,387,396,408],{},[33,379,380,384],{},[51,381,382],{},[17,383,78],{},[51,385,386],{},"智能体使用的大模型",[33,388,389,393],{},[51,390,391],{},[17,392,82],{},[51,394,395],{},"智能体可以调用的工具列表",[33,397,398,402],{},[51,399,400],{},[17,401,85],{},[51,403,404,405],{},"系统提示词，v1.0 标准写法为 ",[17,406,407],{},"system_prompt",[33,409,410,414],{},[51,411,412],{},[17,413,88],{},[51,415,416],{},"智能体执行过程中插入的中间件列表",[10,418,419],{},[13,420,421,422,424,425,427],{},"注意：讲义里写的 ",[17,423,85],{},"，在 v1.0 标准 API 中通常写作 ",[17,426,407],{},"。",[123,429,431],{"id":430},"_32-新老写法对比","3.2 新老写法对比",[13,433,434],{},"旧版：",[109,436,438],{"className":139,"code":437,"language":141,"meta":115,"style":115},"from langchain.agents import AgentExecutor\nfrom langgraph.prebuilt import create_react_agent\n\nagent = create_react_agent(model=model, tools=tools)\nexecutor = AgentExecutor(agent=agent, tools=tools)\n",[17,439,440,445,450,454,459],{"__ignoreMap":115},[145,441,442],{"class":147,"line":148},[145,443,444],{},"from langchain.agents import AgentExecutor\n",[145,446,447],{"class":147,"line":154},[145,448,449],{},"from langgraph.prebuilt import create_react_agent\n",[145,451,452],{"class":147,"line":161},[145,453,158],{"emptyLinePlaceholder":157},[145,455,456],{"class":147,"line":166},[145,457,458],{},"agent = create_react_agent(model=model, tools=tools)\n",[145,460,461],{"class":147,"line":172},[145,462,463],{},"executor = AgentExecutor(agent=agent, tools=tools)\n",[13,465,466],{},"v1.0：",[109,468,470],{"className":139,"code":469,"language":141,"meta":115,"style":115},"from langchain.agents import create_agent\n\nagent = create_agent(\n    model=model,\n    tools=tools,\n)\n",[17,471,472,477,481,486,491,496],{"__ignoreMap":115},[145,473,474],{"class":147,"line":148},[145,475,476],{},"from langchain.agents import create_agent\n",[145,478,479],{"class":147,"line":154},[145,480,158],{"emptyLinePlaceholder":157},[145,482,483],{"class":147,"line":161},[145,484,485],{},"agent = create_agent(\n",[145,487,488],{"class":147,"line":166},[145,489,490],{},"    model=model,\n",[145,492,493],{"class":147,"line":172},[145,494,495],{},"    tools=tools,\n",[145,497,498],{"class":147,"line":178},[145,499,500],{},")\n",[123,502,504],{"id":503},"_33-create_agent-使用示例","3.3 create_agent 使用示例",[109,506,508],{"className":139,"code":507,"language":141,"meta":115,"style":115},"from langchain.agents import create_agent\nfrom langchain.tools import tool\n\n\n@tool\ndef get_weather(city: str) -> str:\n    \"\"\"获取指定城市的天气信息。\"\"\"\n    return f\"{city} 今天晴天，气温 28 摄氏度。\"\n\n\nagent = create_agent(\n    model=\"openai:gpt-4o-mini\",\n    tools=[get_weather],\n    system_prompt=\"你是一个天气助手，需要使用工具回答天气问题。\",\n)\n\nresult = agent.invoke({\n    \"messages\": [\n        {\"role\": \"user\", \"content\": \"上海今天天气怎么样？\"},\n    ],\n})\n\nprint(result[\"messages\"][-1].content)\n",[17,509,510,514,518,522,526,530,534,538,542,546,550,554,559,564,569,573,577,582,587,593,599,605,610],{"__ignoreMap":115},[145,511,512],{"class":147,"line":148},[145,513,476],{},[145,515,516],{"class":147,"line":154},[145,517,151],{},[145,519,520],{"class":147,"line":161},[145,521,158],{"emptyLinePlaceholder":157},[145,523,524],{"class":147,"line":166},[145,525,158],{"emptyLinePlaceholder":157},[145,527,528],{"class":147,"line":172},[145,529,169],{},[145,531,532],{"class":147,"line":178},[145,533,175],{},[145,535,536],{"class":147,"line":184},[145,537,181],{},[145,539,540],{"class":147,"line":190},[145,541,187],{},[145,543,544],{"class":147,"line":195},[145,545,158],{"emptyLinePlaceholder":157},[145,547,548],{"class":147,"line":200},[145,549,158],{"emptyLinePlaceholder":157},[145,551,552],{"class":147,"line":205},[145,553,485],{},[145,555,556],{"class":147,"line":211},[145,557,558],{},"    model=\"openai:gpt-4o-mini\",\n",[145,560,561],{"class":147,"line":217},[145,562,563],{},"    tools=[get_weather],\n",[145,565,566],{"class":147,"line":317},[145,567,568],{},"    system_prompt=\"你是一个天气助手，需要使用工具回答天气问题。\",\n",[145,570,571],{"class":147,"line":323},[145,572,500],{},[145,574,575],{"class":147,"line":329},[145,576,158],{"emptyLinePlaceholder":157},[145,578,579],{"class":147,"line":334},[145,580,581],{},"result = agent.invoke({\n",[145,583,584],{"class":147,"line":340},[145,585,586],{},"    \"messages\": [\n",[145,588,590],{"class":147,"line":589},19,[145,591,592],{},"        {\"role\": \"user\", \"content\": \"上海今天天气怎么样？\"},\n",[145,594,596],{"class":147,"line":595},20,[145,597,598],{},"    ],\n",[145,600,602],{"class":147,"line":601},21,[145,603,604],{},"})\n",[145,606,608],{"class":147,"line":607},22,[145,609,158],{"emptyLinePlaceholder":157},[145,611,613],{"class":147,"line":612},23,[145,614,615],{},"print(result[\"messages\"][-1].content)\n",[13,617,618,619,621],{},"因为 ",[17,620,19],{}," 基于 LangGraph 构建，还自动支持持久化、流式输出、人工审批和时间回溯等能力。",[22,623,625],{"id":624},"_4-middleware中间件","4. Middleware（中间件）",[123,627,629],{"id":628},"_41-定位","4.1 定位",[13,631,632],{},"Middleware 是智能体执行过程中的可插拔钩子系统，可以在模型调用前、模型调用后、工具调用时等节点插入自定义逻辑，例如脱敏、日志、限流、人工审批和上下文管理。",[123,634,636],{"id":635},"_42-核心钩子","4.2 核心钩子",[27,638,639,652],{},[30,640,641],{},[33,642,643,646,649],{},[36,644,645],{},"钩子",[36,647,648],{},"触发时机",[36,650,651],{},"典型用途",[46,653,654,667,680,693,706,719],{},[33,655,656,661,664],{},[51,657,658],{},[17,659,660],{},"before_agent",[51,662,663],{},"Agent 开始执行前",[51,665,666],{},"加载记忆、校验输入",[33,668,669,674,677],{},[51,670,671],{},[17,672,673],{},"before_model",[51,675,676],{},"每次模型调用前",[51,678,679],{},"动态修改提示词、裁剪消息",[33,681,682,687,690],{},[51,683,684],{},[17,685,686],{},"wrap_model_call",[51,688,689],{},"包裹每次模型调用",[51,691,692],{},"重试、缓存、模型切换",[33,694,695,700,703],{},[51,696,697],{},[17,698,699],{},"wrap_tool_call",[51,701,702],{},"包裹每次工具调用",[51,704,705],{},"工具监控、工具结果处理",[33,707,708,713,716],{},[51,709,710],{},[17,711,712],{},"after_model",[51,714,715],{},"每次模型响应后",[51,717,718],{},"输出校验、护栏",[33,720,721,726,729],{},[51,722,723],{},[17,724,725],{},"after_agent",[51,727,728],{},"Agent 执行结束后",[51,730,731],{},"保存结果、清理资源",[123,733,735],{"id":734},"_43-预置中间件","4.3 预置中间件",[13,737,738],{},"LangChain 提供了一些预置中间件：",[225,740,741,746,751],{},[228,742,743,745],{},[17,744,101],{},"：在发给模型前对敏感信息脱敏或拦截。",[228,747,748,750],{},[17,749,104],{},"：对话历史过长时自动摘要。",[228,752,753,755],{},[17,754,107],{},"：敏感工具调用前要求人工审批。",[109,757,759],{"className":139,"code":758,"language":141,"meta":115,"style":115},"from langchain.agents import create_agent\nfrom langchain.agents.middleware import (\n    HumanInTheLoopMiddleware,\n    PIIMiddleware,\n    SummarizationMiddleware,\n)\nfrom langchain.tools import tool\n\n\n@tool\ndef read_email() -> str:\n    \"\"\"读取最新邮件。\"\"\"\n    return \"最新邮件：系统将于今晚 22:00 维护。\"\n\n\n@tool\ndef send_email(to: str, content: str) -> str:\n    \"\"\"向指定邮箱发送邮件。\"\"\"\n    return f\"邮件已发送至 {to}\"\n\n\nagent = create_agent(\n    model=\"openai:gpt-4o-mini\",\n    tools=[read_email, send_email],\n    system_prompt=\"你是一位邮件助手\",\n    middleware=[\n        PIIMiddleware(\"email\", strategy=\"redact\", apply_to_input=True),\n        SummarizationMiddleware(\n            model=\"openai:gpt-4o-mini\",\n            trigger={\"tokens\": 500},\n        ),\n        HumanInTheLoopMiddleware(\n            interrupt_on={\n                \"send_email\": {\n                    \"allowed_decisions\": [\"approve\", \"edit\", \"reject\"],\n                },\n            },\n        ),\n    ],\n)\n",[17,760,761,765,770,775,780,785,789,793,797,801,805,810,815,820,824,828,832,836,840,844,848,852,856,860,866,872,878,884,890,896,902,908,914,920,926,932,938,944,949,954],{"__ignoreMap":115},[145,762,763],{"class":147,"line":148},[145,764,476],{},[145,766,767],{"class":147,"line":154},[145,768,769],{},"from langchain.agents.middleware import (\n",[145,771,772],{"class":147,"line":161},[145,773,774],{},"    HumanInTheLoopMiddleware,\n",[145,776,777],{"class":147,"line":166},[145,778,779],{},"    PIIMiddleware,\n",[145,781,782],{"class":147,"line":172},[145,783,784],{},"    SummarizationMiddleware,\n",[145,786,787],{"class":147,"line":178},[145,788,500],{},[145,790,791],{"class":147,"line":184},[145,792,151],{},[145,794,795],{"class":147,"line":190},[145,796,158],{"emptyLinePlaceholder":157},[145,798,799],{"class":147,"line":195},[145,800,158],{"emptyLinePlaceholder":157},[145,802,803],{"class":147,"line":200},[145,804,169],{},[145,806,807],{"class":147,"line":205},[145,808,809],{},"def read_email() -> str:\n",[145,811,812],{"class":147,"line":211},[145,813,814],{},"    \"\"\"读取最新邮件。\"\"\"\n",[145,816,817],{"class":147,"line":217},[145,818,819],{},"    return \"最新邮件：系统将于今晚 22:00 维护。\"\n",[145,821,822],{"class":147,"line":317},[145,823,158],{"emptyLinePlaceholder":157},[145,825,826],{"class":147,"line":323},[145,827,158],{"emptyLinePlaceholder":157},[145,829,830],{"class":147,"line":329},[145,831,169],{},[145,833,834],{"class":147,"line":334},[145,835,208],{},[145,837,838],{"class":147,"line":340},[145,839,214],{},[145,841,842],{"class":147,"line":589},[145,843,220],{},[145,845,846],{"class":147,"line":595},[145,847,158],{"emptyLinePlaceholder":157},[145,849,850],{"class":147,"line":601},[145,851,158],{"emptyLinePlaceholder":157},[145,853,854],{"class":147,"line":607},[145,855,485],{},[145,857,858],{"class":147,"line":612},[145,859,558],{},[145,861,863],{"class":147,"line":862},24,[145,864,865],{},"    tools=[read_email, send_email],\n",[145,867,869],{"class":147,"line":868},25,[145,870,871],{},"    system_prompt=\"你是一位邮件助手\",\n",[145,873,875],{"class":147,"line":874},26,[145,876,877],{},"    middleware=[\n",[145,879,881],{"class":147,"line":880},27,[145,882,883],{},"        PIIMiddleware(\"email\", strategy=\"redact\", apply_to_input=True),\n",[145,885,887],{"class":147,"line":886},28,[145,888,889],{},"        SummarizationMiddleware(\n",[145,891,893],{"class":147,"line":892},29,[145,894,895],{},"            model=\"openai:gpt-4o-mini\",\n",[145,897,899],{"class":147,"line":898},30,[145,900,901],{},"            trigger={\"tokens\": 500},\n",[145,903,905],{"class":147,"line":904},31,[145,906,907],{},"        ),\n",[145,909,911],{"class":147,"line":910},32,[145,912,913],{},"        HumanInTheLoopMiddleware(\n",[145,915,917],{"class":147,"line":916},33,[145,918,919],{},"            interrupt_on={\n",[145,921,923],{"class":147,"line":922},34,[145,924,925],{},"                \"send_email\": {\n",[145,927,929],{"class":147,"line":928},35,[145,930,931],{},"                    \"allowed_decisions\": [\"approve\", \"edit\", \"reject\"],\n",[145,933,935],{"class":147,"line":934},36,[145,936,937],{},"                },\n",[145,939,941],{"class":147,"line":940},37,[145,942,943],{},"            },\n",[145,945,947],{"class":147,"line":946},38,[145,948,907],{},[145,950,952],{"class":147,"line":951},39,[145,953,598],{},[145,955,957],{"class":147,"line":956},40,[145,958,500],{},[123,960,962],{"id":961},"_44-自定义中间件","4.4 自定义中间件",[13,964,965,966,969],{},"继承 ",[17,967,968],{},"AgentMiddleware","，实现需要的钩子方法：",[109,971,973],{"className":139,"code":972,"language":141,"meta":115,"style":115},"from typing import Any, Callable\n\nfrom langchain.agents import create_agent\nfrom langchain.agents.middleware import AgentMiddleware, AgentState\nfrom langchain.messages import ToolMessage\nfrom langchain.tools import tool\nfrom langchain.tools.tool_node import ToolCallRequest\nfrom langgraph.runtime import Runtime\nfrom langgraph.types import Command\n\n\n@tool\ndef get_weather(city: str) -> str:\n    \"\"\"获取指定城市的天气信息。\"\"\"\n    return f\"{city} 今天晴天，气温 28 摄氏度。\"\n\n\nclass LoggingMiddleware(AgentMiddleware):\n    def before_agent(\n        self,\n        state: AgentState,\n        runtime: Runtime,\n    ) -> dict[str, Any] | None:\n        print(\"Agent 开始执行\")\n        return None\n\n    def before_model(\n        self,\n        state: AgentState,\n        runtime: Runtime,\n    ) -> dict[str, Any] | None:\n        print(f\"调用模型前，消息数量：{len(state['messages'])}\")\n        return None\n\n    def wrap_tool_call(\n        self,\n        request: ToolCallRequest,\n        handler: Callable[[ToolCallRequest], ToolMessage | Command[Any]],\n    ) -> ToolMessage | Command[Any]:\n        print(f\"调用工具：{request.tool_call['name']}\")\n        result = handler(request)\n        print(f\"工具返回：{result}\")\n        return result\n\n    def after_agent(\n        self,\n        state: AgentState,\n        runtime: Runtime,\n    ) -> dict[str, Any] | None:\n        print(\"Agent 执行结束\")\n        return None\n\n\nagent = create_agent(\n    model=\"openai:gpt-4o-mini\",\n    tools=[get_weather],\n    system_prompt=\"你是一个天气助手\",\n    middleware=[LoggingMiddleware()],\n)\n",[17,974,975,980,984,988,993,998,1002,1007,1012,1017,1021,1025,1029,1033,1037,1041,1045,1049,1054,1059,1064,1069,1074,1079,1084,1089,1093,1098,1102,1106,1110,1114,1119,1123,1127,1132,1136,1141,1146,1151,1156,1162,1168,1174,1179,1185,1190,1195,1200,1205,1211,1216,1221,1226,1231,1236,1241,1247,1253],{"__ignoreMap":115},[145,976,977],{"class":147,"line":148},[145,978,979],{},"from typing import Any, Callable\n",[145,981,982],{"class":147,"line":154},[145,983,158],{"emptyLinePlaceholder":157},[145,985,986],{"class":147,"line":161},[145,987,476],{},[145,989,990],{"class":147,"line":166},[145,991,992],{},"from langchain.agents.middleware import AgentMiddleware, AgentState\n",[145,994,995],{"class":147,"line":172},[145,996,997],{},"from langchain.messages import ToolMessage\n",[145,999,1000],{"class":147,"line":178},[145,1001,151],{},[145,1003,1004],{"class":147,"line":184},[145,1005,1006],{},"from langchain.tools.tool_node import ToolCallRequest\n",[145,1008,1009],{"class":147,"line":190},[145,1010,1011],{},"from langgraph.runtime import Runtime\n",[145,1013,1014],{"class":147,"line":195},[145,1015,1016],{},"from langgraph.types import Command\n",[145,1018,1019],{"class":147,"line":200},[145,1020,158],{"emptyLinePlaceholder":157},[145,1022,1023],{"class":147,"line":205},[145,1024,158],{"emptyLinePlaceholder":157},[145,1026,1027],{"class":147,"line":211},[145,1028,169],{},[145,1030,1031],{"class":147,"line":217},[145,1032,175],{},[145,1034,1035],{"class":147,"line":317},[145,1036,181],{},[145,1038,1039],{"class":147,"line":323},[145,1040,187],{},[145,1042,1043],{"class":147,"line":329},[145,1044,158],{"emptyLinePlaceholder":157},[145,1046,1047],{"class":147,"line":334},[145,1048,158],{"emptyLinePlaceholder":157},[145,1050,1051],{"class":147,"line":340},[145,1052,1053],{},"class LoggingMiddleware(AgentMiddleware):\n",[145,1055,1056],{"class":147,"line":589},[145,1057,1058],{},"    def before_agent(\n",[145,1060,1061],{"class":147,"line":595},[145,1062,1063],{},"        self,\n",[145,1065,1066],{"class":147,"line":601},[145,1067,1068],{},"        state: AgentState,\n",[145,1070,1071],{"class":147,"line":607},[145,1072,1073],{},"        runtime: Runtime,\n",[145,1075,1076],{"class":147,"line":612},[145,1077,1078],{},"    ) -> dict[str, Any] | None:\n",[145,1080,1081],{"class":147,"line":862},[145,1082,1083],{},"        print(\"Agent 开始执行\")\n",[145,1085,1086],{"class":147,"line":868},[145,1087,1088],{},"        return None\n",[145,1090,1091],{"class":147,"line":874},[145,1092,158],{"emptyLinePlaceholder":157},[145,1094,1095],{"class":147,"line":880},[145,1096,1097],{},"    def before_model(\n",[145,1099,1100],{"class":147,"line":886},[145,1101,1063],{},[145,1103,1104],{"class":147,"line":892},[145,1105,1068],{},[145,1107,1108],{"class":147,"line":898},[145,1109,1073],{},[145,1111,1112],{"class":147,"line":904},[145,1113,1078],{},[145,1115,1116],{"class":147,"line":910},[145,1117,1118],{},"        print(f\"调用模型前，消息数量：{len(state['messages'])}\")\n",[145,1120,1121],{"class":147,"line":916},[145,1122,1088],{},[145,1124,1125],{"class":147,"line":922},[145,1126,158],{"emptyLinePlaceholder":157},[145,1128,1129],{"class":147,"line":928},[145,1130,1131],{},"    def wrap_tool_call(\n",[145,1133,1134],{"class":147,"line":934},[145,1135,1063],{},[145,1137,1138],{"class":147,"line":940},[145,1139,1140],{},"        request: ToolCallRequest,\n",[145,1142,1143],{"class":147,"line":946},[145,1144,1145],{},"        handler: Callable[[ToolCallRequest], ToolMessage | Command[Any]],\n",[145,1147,1148],{"class":147,"line":951},[145,1149,1150],{},"    ) -> ToolMessage | Command[Any]:\n",[145,1152,1153],{"class":147,"line":956},[145,1154,1155],{},"        print(f\"调用工具：{request.tool_call['name']}\")\n",[145,1157,1159],{"class":147,"line":1158},41,[145,1160,1161],{},"        result = handler(request)\n",[145,1163,1165],{"class":147,"line":1164},42,[145,1166,1167],{},"        print(f\"工具返回：{result}\")\n",[145,1169,1171],{"class":147,"line":1170},43,[145,1172,1173],{},"        return result\n",[145,1175,1177],{"class":147,"line":1176},44,[145,1178,158],{"emptyLinePlaceholder":157},[145,1180,1182],{"class":147,"line":1181},45,[145,1183,1184],{},"    def after_agent(\n",[145,1186,1188],{"class":147,"line":1187},46,[145,1189,1063],{},[145,1191,1193],{"class":147,"line":1192},47,[145,1194,1068],{},[145,1196,1198],{"class":147,"line":1197},48,[145,1199,1073],{},[145,1201,1203],{"class":147,"line":1202},49,[145,1204,1078],{},[145,1206,1208],{"class":147,"line":1207},50,[145,1209,1210],{},"        print(\"Agent 执行结束\")\n",[145,1212,1214],{"class":147,"line":1213},51,[145,1215,1088],{},[145,1217,1219],{"class":147,"line":1218},52,[145,1220,158],{"emptyLinePlaceholder":157},[145,1222,1224],{"class":147,"line":1223},53,[145,1225,158],{"emptyLinePlaceholder":157},[145,1227,1229],{"class":147,"line":1228},54,[145,1230,485],{},[145,1232,1234],{"class":147,"line":1233},55,[145,1235,558],{},[145,1237,1239],{"class":147,"line":1238},56,[145,1240,563],{},[145,1242,1244],{"class":147,"line":1243},57,[145,1245,1246],{},"    system_prompt=\"你是一个天气助手\",\n",[145,1248,1250],{"class":147,"line":1249},58,[145,1251,1252],{},"    middleware=[LoggingMiddleware()],\n",[145,1254,1256],{"class":147,"line":1255},59,[145,1257,500],{},[13,1259,223],{},[225,1261,1262,1268,1274,1280],{},[228,1263,1264,1267],{},[17,1265,1266],{},"before_*"," 钩子按中间件列表顺序执行。",[228,1269,1270,1273],{},[17,1271,1272],{},"after_*"," 钩子按逆序执行。",[228,1275,1276,1279],{},[17,1277,1278],{},"wrap_*"," 钩子采用嵌套方式包裹执行。",[228,1281,1282],{},"钩子返回的字典会合并进 Agent 状态，可用于跨阶段传值。",[22,1284,1286],{"id":1285},"_5-小结","5. 小结",[27,1288,1289,1301],{},[30,1290,1291],{},[33,1292,1293,1295,1298],{},[36,1294,38],{},[36,1296,1297],{},"核心任务",[36,1299,1300],{},"核心写法 \u002F 类型",[46,1302,1303,1316,1333],{},[33,1304,1305,1307,1310],{},[51,1306,53],{},[51,1308,1309],{},"提供智能体可调用的外部能力",[51,1311,1312,62,1314,66],{},[17,1313,61],{},[17,1315,65],{},[33,1317,1318,1320,1323],{},[51,1319,19],{},[51,1321,1322],{},"创建并运行智能体",[51,1324,1325,79,1327,79,1329,79,1331],{},[17,1326,78],{},[17,1328,82],{},[17,1330,407],{},[17,1332,88],{},[33,1334,1335,1337,1340],{},[51,1336,93],{},[51,1338,1339],{},"在执行流程中插入可插拔逻辑",[51,1341,1342,79,1344,79,1346,1348,1349],{},[17,1343,101],{},[17,1345,104],{},[17,1347,107],{},"、自定义 ",[17,1350,968],{},[13,1352,1353,1355],{},[17,1354,19],{}," 简化了智能体创建流程，Middleware 则提供了生产级智能体需要的控制力，两者配合是 LangChain v1.0 构建智能体的核心方式。",[1357,1358,1359],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":115,"searchDepth":154,"depth":154,"links":1361},[1362,1363,1370,1375,1381],{"id":24,"depth":154,"text":25},{"id":120,"depth":154,"text":121,"children":1364},[1365,1366,1368],{"id":125,"depth":161,"text":126},{"id":132,"depth":161,"text":1367},"2.2 使用 @tool 装饰器定义工具（推荐）",{"id":239,"depth":161,"text":1369},"2.3 使用 BaseTool 基类定义工具",{"id":346,"depth":154,"text":347,"children":1371},[1372,1373,1374],{"id":350,"depth":161,"text":351},{"id":430,"depth":161,"text":431},{"id":503,"depth":161,"text":504},{"id":624,"depth":154,"text":625,"children":1376},[1377,1378,1379,1380],{"id":628,"depth":161,"text":629},{"id":635,"depth":161,"text":636},{"id":734,"depth":161,"text":735},{"id":961,"depth":161,"text":962},{"id":1285,"depth":154,"text":1286},"2026-05-05","介绍 LangChain v1.0 的工具定义、create_agent 创建流程与 Middleware 扩展机制。",false,"md","article",{"migration":1388},{"generator":1389,"sourceSha256":1390},"nuxt-site\u002Fscripts\u002Fmigrate-content.mjs","ebf600801bb2f984955dcd8cd0b965100a394d278ec01c1283f7e32830182b58","\u002Frag\u002F05_智能体工具与中间件",null,"rag",{"title":5,"description":1383},"content\u002Frag\u002F05_智能体工具与中间件.md","rag\u002F05_智能体工具与中间件",[1398,1399,1400],"LangChain","Agent","工具调用","OdUAl1QEC_RO-NVU0ZvwFqqVKRO3xymZ-SKt7-wCyzY",1791279145540]