Nodejs也能写Agent - 23.LangGraph篇 - 可靠性与容错
上一篇我们管住了上下文窗口该 trim 的 trim该摘要的摘要RAG 也不再一股脑乱塞。窗口干净了Agent 就稳了吗并没有。生产里 LLM 会超时、会 429、Ollama 会挂、ReAct 会空转烧光额度——喂对了内容照样可能直接崩给你看。本篇管「挂了怎么办」——重试、Fallback、防死循环让异常变成优雅降级而不是用户脸上的 stack trace。老规矩本文以官网最新文档核对过Fault tolerance、Prebuilt middleware、Agents。入口继续createAgent——别再抄createReactAgent。重试 / Fallback / 调用上限优先挂官方中间件别先上手写一整套invokeWithRetry。一、生产里 Agent 怎么死先认清「会死在哪」再谈怎么救。场景典型原因表现超时模型负载高、网络慢、prompt 过长挂起后 timeout429 限流API 配额用尽、并发过高Rate limit exceeded模型不可用Ollama 没起、模型没 pull、服务宕机ECONNREFUSED、model not found上下文超限messages RAG 超窗400 / context length exceeded失控循环模型一直吐tool_calls烧 token、拖超时最后 recursive 爆官网把错误按「谁来修」分得更清楚——不同错误不该用同一招错误类型谁来修策略官方手段瞬时故障网络、限流系统自动指数退避重试modelRetryMiddleware/toolRetryMiddlewareLLM 可恢复工具失败、解析翻车模型错误进ToolMessage让模型改主意工具返回错误串JS 尚无ToolErrorMiddleware用户可修复缺信息、指令不清人暂停等人interrupt/ HITL供应商宕机系统自动换备选模型modelFallbackMiddleware失控循环系统自动封顶调用次数modelCallLimitMiddleware/toolCallLimitMiddlewarerecursionLimit未知异常开发者往上抛别瞎 catch无中间件硬吞工具失败时把错误信息回给模型它往往能自己换招。官网 JS 侧ToolErrorMiddleware尚未提供——继续走「错误内容进 ToolMessage」即可别等一个还不存在的 API。瞬时供应商挂工具可恢复失控循环未知错误发生错误类型?Retry 退避Fallback 模型错误进 ToolMessageCallLimit / recursionLimit向上抛出二、瞬时故障重试网络抖一下、偶发 429立刻失败只会逼用户狂点刷新。策略上策略说明固定间隔每次等一样久简单但 429 时可能越重试越堵指数退避第 n 次等initialDelayMs * backoffFactor^n给服务喘息时间maxRetries一般 23 次封顶别无限重试Chat 模型自身也可能有maxRetries但挂在 Agent 上时官网主路径是中间件——模型调用和工具调用各管各的import{createAgent,modelRetryMiddleware,toolRetryMiddleware,}fromlangchain;import{ChatOllama}fromlangchain/ollama;import{tool}fromlangchain/core/tools;import*aszfromzod;constsearchWebtool(async({q}:{q:string})搜索结果${q},{name:search_web,description:搜索网页外部 API值得重试,schema:z.object({q:z.string()}),});constllmnewChatOllama({model:qwen2.5:7b,temperature:0});constagentcreateAgent({model:llm,tools:[searchWeb],systemPrompt:需要外部信息时调用 search_web。,middleware:[// 模型超时 / 限流 / 5xx 类瞬时错误modelRetryMiddleware({maxRetries:3,backoffFactor:2.0,initialDelayMs:1000,}),// 工具只重试会抖的外部调用本地 read 别无脑重试toolRetryMiddleware({maxRetries:2,tools:[search_web],backoffFactor:2.0,initialDelayMs:500,}),],});要点默认就是指数退避backoffFactor: 0才退回固定间隔。toolRetryMiddleware用tools: [...]收窄范围——官网原话文件系统read失败多半重试也没用网页搜索超时才值得再试。onFailure: continue时重试用尽可返回带错误说明的AIMessage让 Agent 有机会收尾而不是整段炸穿。手写forsleep也能懂原理生产别重复造轮子中间件已经把退避、jitter、失败策略打包好了。三、主模型挂了Fallback重试用尽、或者主模型整机不可用时换备选继续服务主模型 qwen2.5:7b 失败 → 备选 llama3.1:8b或其它已 pull 的模型import{createAgent,modelFallbackMiddleware}fromlangchain;import{ChatOllama}fromlangchain/ollama;constprimarynewChatOllama({model:qwen2.5:7b,temperature:0});constfallbacknewChatOllama({model:llama3.1:8b,temperature:0});constagentcreateAgent({model:primary,tools:[],middleware:[// 主模型失败后按顺序尝试备选可传多个modelFallbackMiddleware(fallback),],});注意备选能力可能不同——回答风格、工具遵从度都会变。日志或 UI 最好标一句「已切换备选模型」别假装什么都没发生。Fallback 解决的是「模型/供应商挂了」解决不了「问题本身无解」。盯 fallback 触发率太高说明主路径在持续抽风。四、防死循环recursionLimit Call LimitReAct 环里模型若一直返回tool_calls而不给最终答案就会空转import{GraphRecursionError}fromlangchain/langgraph;try{awaitagent.invoke({messages:[{role:user,content:帮我做一件超复杂的事}]},{recursionLimit:15}// 生产可配环境变量默认别太大);}catch(err){if(errinstanceofGraphRecursionError){// 别把 stack 甩给用户return任务步骤过多请简化问题后再试。;}throwerr;}但要分清两层闸门闸门数的是什么超限表现recursionLimitLangGraphsuper-step调度滴答不是「模型调用次数」抛GraphRecursionErrormodelCallLimitMiddleware/toolCallLimitMiddleware业务语义上的模型/工具调用次数可exitBehavior: end优雅收束挂了beforeModel/afterModel这类会编译成独立节点的中间件会多占 super-stepwrapModelCall包在原节点里一般不另计。所以recursionLimit要留余量真正「最多调几次模型」交给 Call Limit 更直观。import{createAgent,modelCallLimitMiddleware,toolCallLimitMiddleware,}fromlangchain;import{ChatOllama}fromlangchain/ollama;constagentcreateAgent({model:newChatOllama({model:qwen2.5:7b,temperature:0}),tools:[/* ... */],middleware:[modelCallLimitMiddleware({runLimit:15,// 单次 invoke 内最多 15 次模型调用exitBehavior:end,// 到顶优雅结束而不是甩异常}),toolCallLimitMiddleware({runLimit:30,// 单次 invoke 内工具调用封顶}),],});runLimit一次用户请求内计数下轮重置。threadLimit整条会话累计需要 Checkpointer。两道闸一起上Call Limit 管业务预算recursionLimit防图调度层面真失控。五、缓存与熔断轻量中间件解决「这次调用怎么扛」缓存和熔断解决「别把下游打爆 / 别重复烧钱」。精确缓存 vs 语义缓存类型命中条件MVP 思路精确缓存问题字符串完全一致可 hash内存Map TTL语义缓存embedding 相似度过阈值向量库本篇不展开typeCacheEntry{value:string;expiresAt:number};constexactCachenewMapstring,CacheEntry();constTTL_MS5*60*1000;functioncacheKey(question:string){returnquestion.trim().toLowerCase();}functiongetCached(question:string):string|undefined{consthitexactCache.get(cacheKey(question));if(!hit)returnundefined;if(Date.now()hit.expiresAt){exactCache.delete(cacheKey(question));returnundefined;}returnhit.value;}functionsetCached(question:string,value:string){exactCache.set(cacheKey(question),{value,expiresAt:Date.now()TTL_MS,});}// 「现在几点」「今天天气」——实时题别进缓存注意不同用户 / 不同thread_id是否共享缓存要想清楚带隐私或个性化的回答默认不要全局共享。Circuit Breaker 简述连续失败时与其每次都去撞已经挂掉的 Ollama不如短暂拒绝关闭 → 失败累积 → 打开直接拒→ 冷却后 → 半开放一枪试探→ 成功则关闭classSimpleBreaker{privatefailures0;privateopenUntil0;constructor(privatethreshold5,privatecoolDownMs30_000){}getisOpen(){returnDate.now()this.openUntil;}beforeCall(){if(this.isOpen){thrownewError(服务暂时不可用请稍后重试熔断开启);}}onSuccess(){this.failures0;this.openUntil0;}onFailure(){this.failures1;if(this.failuresthis.threshold){this.openUntilDate.now()this.coolDownMs;this.failures0;}}}constbreakernewSimpleBreaker();asyncfunctioninvokeWithBreaker(run:()Promiseunknown){breaker.beforeCall();try{constresultawaitrun();breaker.onSuccess();returnresult;}catch(e){breaker.onFailure();throwe;}}这是教学级 MVP。完整半开态、按依赖隔离可后续对标 resilience4j 一类库本篇目标是建立心智不是重造运维平台。六、组合生产最小可靠骨架把前面几招叠在一颗createAgent上import{createAgent,modelRetryMiddleware,toolRetryMiddleware,modelFallbackMiddleware,modelCallLimitMiddleware,toolCallLimitMiddleware,}fromlangchain;import{ChatOllama}fromlangchain/ollama;import{GraphRecursionError}fromlangchain/langgraph;import{tool}fromlangchain/core/tools;import*aszfromzod;constgetWeathertool(async({city}:{city:string})${city}晴25°C,{name:get_weather,description:查询城市天气,schema:z.object({city:z.string()}),});constprimarynewChatOllama({model:qwen2.5:7b,temperature:0});constfallbacknewChatOllama({model:llama3.1:8b,temperature:0});constagentcreateAgent({model:primary,tools:[getWeather],systemPrompt:需要天气时调用 get_weather。,middleware:[modelRetryMiddleware({maxRetries:2,backoffFactor:2.0,initialDelayMs:1000,}),toolRetryMiddleware({maxRetries:2,tools:[get_weather],}),modelFallbackMiddleware(fallback),modelCallLimitMiddleware({runLimit:15,exitBehavior:end}),toolCallLimitMiddleware({runLimit:30}),],});exportasyncfunctionsafeInvoke(userText:string){try{returnawaitagent.invoke({messages:[{role:user,content:userText}]},{recursionLimit:25}// 比 callLimit 留余量);}catch(err){if(errinstanceofGraphRecursionError){return{messages:[{role:assistant,content:任务步骤过多请简化问题后再试。,},],};}throwerr;}}retry / fallback / 触顶时你才能在 LangSmith 里看见「到底换过几次、卡在哪」。可靠性没有可观测就是盲修。常见坑无重试直接失败偶发抖动逼用户狂点至少模型侧maxRetries: 2。重试无退避429 时立刻重试只会更堵用指数退避。工具无脑全量重试本地/确定性失败不值得重试tools: [...]收窄。只有recursionLimit、没有 Call Limitsuper-step ≠ 业务调用次数两道闸一起上更稳。Fallback 不告知备选质量不同日志/UI 应标注。缓存误用天气、时间、用户私有回答不该进全局精确缓存。熔断阈值乱调太敏感则误杀太钝则雪崩。瞎 catch 未知异常官网建议处理不了的往上抛方便调试。

相关新闻

VMware与VirtualBox虚拟机与主机双向复制粘贴配置与排错指南

VMware与VirtualBox虚拟机与主机双向复制粘贴配置与排错指南

1. 从“隔阂”到“丝滑”:为什么虚拟机与主机的复制粘贴如此重要如果你和我一样,经常在Windows主机上跑一个Linux虚拟机(比如Ubuntu、CentOS)做开发、测试或者学习,那你一定遇到过这个让人抓狂的场景:在虚拟…

2026/7/22 14:50:32阅读更多 →
SpringBoot数据库操作方案对比与实战优化

SpringBoot数据库操作方案对比与实战优化

1. SpringBoot数据库操作的核心价值SpringBoot作为Java生态中最流行的应用框架之一,其数据库操作能力直接决定了企业级应用的开发效率。我在实际项目中发现,合理的数据库访问层设计能让后续维护成本降低40%以上。SpringBoot通过自动配置和starter机制&am…

2026/7/22 14:50:32阅读更多 →
Cortex-M4中断唤醒与Thumb-2指令集实战解析

Cortex-M4中断唤醒与Thumb-2指令集实战解析

1. 项目概述与核心价值在嵌入式开发的日常里,中断和指令集是绕不开的两个硬核话题。前者决定了你的系统如何“眼观六路,耳听八方”,后者则是你与处理器沟通的“语言”。今天,我想结合自己这些年调试Cortex-M4内核的经验&#xff0…

2026/7/22 14:48:32阅读更多 →
综述救星[特殊字符]再也不用写流水账!

综述救星[特殊字符]再也不用写流水账!

写论文最煎熬的板块,绝对是文献综述! 熬几天看几十篇文献,结果写出来全是:XX认为…XX研究了… 全篇流水账、杂乱无章、没有逻辑、缺乏前沿视角,导师一句:只有堆砌,没有综述,重写&a…

2026/7/22 15:52:47阅读更多 →
TM4C129 μDMA控制器深度解析:从架构到高级模式实战

TM4C129 μDMA控制器深度解析:从架构到高级模式实战

1. 项目概述与μDMA核心价值在嵌入式开发,尤其是基于ARM Cortex-M内核的项目里,性能优化是个绕不开的话题。当你的应用需要处理高速ADC采样、批量SPI/I2C通信或者实时音频流时,如果还让CPU吭哧吭哧地一个个字节搬运数据,那系统效率…

2026/7/22 15:52:47阅读更多 →
TMS320C6000 DSP循环优化实战:稀疏数据处理与内存墙突破

TMS320C6000 DSP循环优化实战:稀疏数据处理与内存墙突破

1. 项目概述在嵌入式DSP开发,尤其是基于TI TMS320C6000系列处理器的项目中,性能瓶颈往往藏在最不起眼的循环里。我们常常面对这样的场景:一段逻辑上清晰、功能上正确的代码,一旦跑在实时性要求苛刻的信号处理或图像算法上&#xf…

2026/7/22 15:52:47阅读更多 →
Android随笔-MMKV

Android随笔-MMKV

一、MMKV 是什么 MMKV 是微信团队开源的一款基于 mmap 内存映射的高性能 key-value 存储组件,底层序列化采用 Protobuf,支持加密、多进程共享、匿名内存等特性。它在微信内部从 2015 年使用至今,后移植到 Android、iOS、macOS、Windows、POSI…

2026/7/22 15:52:47阅读更多 →
DOM编程核心原理与性能优化实战指南

DOM编程核心原理与性能优化实战指南

1. DOM编程基础概念解析作为前端开发的核心技能之一,DOM操作是每个工程师必须掌握的看家本领。DOM(Document Object Model)本质上是浏览器将HTML文档解析成的树状结构,它让JavaScript能够动态访问和更新页面内容。在实际项目中&am…

2026/7/22 15:52:47阅读更多 →
TI MibSPI DMA接口深度解析:实现SPI高速数据传输的硬件加速方案

TI MibSPI DMA接口深度解析:实现SPI高速数据传输的硬件加速方案

1. 项目概述与核心价值在嵌入式系统开发中,尤其是涉及高速数据采集、实时通信或大容量存储的场景,SPI(串行外设接口)总线上的数据传输效率往往是系统性能的瓶颈。传统的SPI通信,无论是查询还是中断方式,都需…

2026/7/22 15:50:47阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →