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:27 阅读更多 →
SpringBoot数据库操作方案对比与实战优化

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

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

2026/7/22 14:50:27 阅读更多 →
算力的隐形代价:当AI的“水足迹”成为下一个技术瓶颈

算力的隐形代价:当AI的“水足迹”成为下一个技术瓶颈

算力的隐形代价:当AI的“水足迹”成为下一个技术瓶颈 最近,一条关于“2030年AI耗水量够13亿人用一年”的消息冲上了热搜榜。乍一看,这个数字似乎有些耸人听闻,甚至让人觉得又是哪个环保组织的夸张宣传。但作为身处技术一线的开发者…

2026/7/23 19:57:28 阅读更多 →

最新新闻

13 Windsurf vs Cursor vs Copilot:2026年AI IDE横评

13 Windsurf vs Cursor vs Copilot:2026年AI IDE横评

摘要:本文对比了 2026 年三大主流 AI 编程工具——Cursor、Windsurf 和 GitHub Copilot 的核心能力。通过三轮比拼(代码补全、内联编辑、项目级理解)和按场景推荐,文章指出:Copilot 在代码补全上仍是标杆;C…

2026/7/23 23:30:04 阅读更多 →
彻底搞懂OpenSSH!SSH原理+免密登录+安全加固+故障排查

彻底搞懂OpenSSH!SSH原理+免密登录+安全加固+故障排查

彻底搞懂OpenSSH!SSH原理免密登录安全加固故障排查(万字干货) 🔥 置顶:Linux运维必学核心干货,面试高频考点生产实战全覆盖,零基础也能看懂,收藏不亏! 前言&#xff1a…

2026/7/23 23:30:04 阅读更多 →
长期可持续的交付价值:与AI共同进化

长期可持续的交付价值:与AI共同进化

长期可持续的交付价值:与AI共同进化30天写完了,SKILL会写了,Agent能跑了,团队也开始用了。但有一个问题始终悬在头上:这些东西能跑多久?你今天花两周打磨的SKILL,同事拿过去也能跑——差距在哪&…

2026/7/23 23:30:04 阅读更多 →
走进科学灵异事件:一台惠普z620工作站FreeBSD系统,我一插入鼠标,它就重启了。而且重启后还报CPU出错.....

走进科学灵异事件:一台惠普z620工作站FreeBSD系统,我一插入鼠标,它就重启了。而且重启后还报CPU出错.....

问题一台惠普z620工作站FreeBSD系统,我一插入鼠标,它就重启了。而且重启后还报CPU出错.....文心的回答:在惠普Z620工作站的FreeBSD系统中,插入鼠标就触发系统重启并报CPU错误,这是硬件兼容性与USB驱动配置冲突导致的典…

2026/7/23 23:30:04 阅读更多 →
HuProt™ 人类蛋白组芯片用于天然产物靶点发现技术研究

HuProt™ 人类蛋白组芯片用于天然产物靶点发现技术研究

天然产物因其复杂的化学组成和多样化的生物活性,在药物开发和生命科学研究领域持续受到关注。随着研究需求不断提升,仅了解天然产物是否具有功能作用已经难以满足科研要求,进一步明确其直接结合蛋白和作用机制成为研究重点。因此,…

2026/7/23 23:30:04 阅读更多 →
CVE_2020_26259 任意文件删除

CVE_2020_26259 任意文件删除

CVE-2020-26259 任意文件删除漏洞深度剖析 漏洞概述CVE-2020-26259 是一个影响 xstream 库(Java 中用于序列化 XML 数据的流行库)的严重安全漏洞。该漏洞允许攻击者通过构造恶意的 XML 输入,实现任意文件删除。xstream 在 1.4.14 版本之前存…

2026/7/23 23:29:04 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/7/23 17:49:47 阅读更多 →

月新闻