
去年我接到一个活儿把一套AI Agent系统部署进一个完全隔离的内网环境里。说“完全隔离”可能有人没概念简单讲就是这台机器没有外网路由DNS只能解析内网域名想去公网拉个模型权重、装个pip包通通没门。而任务要求是在这种环境里跑起一个能真正“下地干活”的Agent——接业务、查数据、调内部接口而不是拿个ChatGPT套壳演示。这篇文章就写这次实战里沉淀下来的东西。我会把这个项目的设计思路、选型逻辑、离线部署过程、并发处理、工具调用的可靠性设计、常见问题排查方式一整套都拆开来讲。如果你也在做企业内的AI Infra、要在安全区或生产内网里部署智能体服务这篇文章的内容应该能让你少踩不少坑。1. 隔离内网里的AI Agent到底难在哪1.1 隔离环境究竟在隔离什么先理清楚一个概念隔离内网并不是“坏境”它只是组织为了保证数据安全和业务稳定采取的一种网络控制手段。它隔离的不是开发人员的热情而是外部的不可控访问以及由外网带来的一切不确定性。这带来的直接后果就是所有依赖公网能力的东西在这里全都失效。模型API都没法用你就得找开源的模型权重自己部署推理服务。pip install也不好使你得准备一个离线依赖包仓库或者干脆用Docker镜像把整个运行环境打包带进去。Embedding模型、向量库、OCR组件、语音识别这套AI周边能力也一样要全部走本地部署。至于外部工具比如网上搜索、天气查询、新闻抓取这类——基本想都别想Agent的工具集必须重新围绕内网能力来设计。所以隔离内网下的AI Agent工程核心不是“AI”部分而是“工程化交付”部分。模型推理、依赖管理、服务部署、并发承载、日志追踪这些原本可以靠云平台伸缩解决的环节现在全部要在地面层自己扛起来。1.2 这套系统最终交付出来的样子为了避免空谈架构我先明确一下这套系统交付的形态。它是一套部署在隔离网络内部的智能工单分发与处理助手用户通过内部Web界面提交工单AI Agent接管工单后会调用内部知识库做语义检索结合历史工单数据生成处理建议并根据业务规则决定是自动执行还是转人工审批。整个处理过程全部发生在内网内部不依赖任何外网服务。它到底能解决什么问题几个痛点一线运维人员被海量重复性工单淹没知识分散在多个文档库导致检索效率低工单分发依赖人工经验、没有沉淀标准。Agent介入后重复工单可以自动给出处理方式复杂工单则借助知识库生成建议由人工确认后执行全流程留痕可审计。这套东西适合的企业场景很典型——有内部数据敏感、网络受控、但业务流程又需要智能化提效的团队。如果你正准备在企业里搞类似的Agent项目我会在下面把每个环节的关键决策和取舍都讲清楚包括为什么选LangGraph、为什么自建模型网关、并发能力怎么估算、工具调用失败以后怎么办等等。2. 整体架构设计与关键选型2.1 系统分四层设计每一层都不越界这套系统的架构我拆成四层接入层、编排层、模型层、工具层。先说各层职责再说为什么这么拆。接入层用的是FastAPI负责接收前端请求、管理会话、处理用户上传的附件同时承担自治限流的任务。FastAPI基于ASGI异步非阻塞模型非常适合IO密集型的API接入场景。编排层用LangGraph它负责Agent的状态流、工具调度的顺序控制、人工确认节点。模型层比较特殊我没有直接让LangChain直连模型API而是在中间加了一层LLM网关服务上层应用对模型的具体型号完全无感知。工具层就是Agent能调用的各种内部操作比如检索内部知识库、查询工单系统、写入处理记录每个工具都被包装成统一的函数接口。分层的核心原因很简单隔离内网里的系统变更代价高。你不可能频繁替换大版本依赖更不可能每调整一次模型或加一个工具就停服半天。分层边界清晰以后模型层升级不影响编排层新增工具不影响接入层排查问题时候也能按层定位。2.2 为什么选LangGraph而不是裸写LangChain或纯自研技术选型环节我其实纠结过一阵子。最开始想直接用LangChain的AgentExecutor省事、资料多但很快发现它在处理复杂分支、循环、人工介入这类场景时表达力不足。又考虑过纯自研状态机觉得无外部依赖、可控性最强但迭代效率太低了。最终定LangGraph是因为它把图结构带进了Agent编排里——节点之间定义好转移关系状态在每个节点间显式传递天然支持条件分支、循环和用interrupt机制挂起等人工处理。这种设计特别适合隔离内网里的Agent因为这里的Agent往往不是一句“帮我查个东西”那么轻而是“一个多步骤、有状态、可能需要人在中间环节确认”的业务流程。LangGraph还是LangChain生态原生支持与向量存储集成、工具调用机制、Prompt模板都能兼容不用重新造一套轮子。开发阶段在普通网络环境里把图流程测好再把打包好的依赖镜像丢进内网就能跑起来。2.3 开工前必须定的三件事这个项目启动前我建议先回答三个问题不然做到一半会返工。第一模型用哪个、跑在哪。隔离内网没有在线模型所以必须提前选定开源模型、确认参数量级、评估GPU资源。如果只有几台T4或者A10那超过14B的模型就别想了输出延迟和显存开销会让你在生产环境里很难受。第二工具范围有哪些。内网Agent的工具集不是越多越好而是越受控越好。每个工具都意味着新的权限边界和新的故障隐患。我们初期只做了知识库检索、工单查询、工单状态更新三个工具跑通以后再慢慢加。第三人工介入做到什么程度。隔离环境下的业务系统通常有严格的审计要求不是所有操作都能让Agent自主完成。我建议把工具执行分两类只读类可自动执行写操作类全部挂人工确认节点。这个决策越早定后续LangGraph的状态图设计就越顺手。3. 离线安装与依赖打包是第一个大坑3.1 模型权重的离线部署方案对比模型是隔离内网里的大件行李。我当时对比了三种部署方式Ollama、vLLM、HuggingFace Transformers直接加载。三者的适用场景差异很大选错会非常痛苦。Ollama胜在部署简单一条命令就能把模型跑起来还自带了OpenAI兼容的API。缺点是并发能力一般内部实现优先保证易用性对高并发和连续批处理的优化远不如专门的服务化推理框架。我们把它用作开发和联调阶段的环境生产并发上来以后直接不够用。vLLM是真正扛生产并发的主力。它实现了PagedAttention、Continuous Batching能在高并发场景下显著提升吞吐。我们在内网用vLLM部署Qwen系列模型实测并发从个位数飙到几十路显存利用率也高很多。代价是部署相对复杂要处理模型格式转换、启动参数调优但这在工程化项目里完全值得。HuggingFace Transformers直接加载是最后备选方案适合深度定制推理逻辑、调试模型行为的场景但生产并发能力比较弱官方长期跑服务还是不如vLLM成熟。建议直接按这个思路走开发验证用Ollama生产推理上vLLM。模型权重文件提前在安全的外网开发机上拉好通过内部文件审查流程后再用存储介质拷贝进内网资损和时效都需要提前规划。3.2 Python依赖到底怎么离线装这是整个项目里最容易让人血压升高的一环。你写代码的时候引了几十个库扒开传递依赖一看实际有上百个包。在没有公共PyPI访问权限的内网里我试过两条路线一条是手工下载wheel包一条是用Docker镜像整体交付。手工下载wheel是在外网开发机上用pip download把整个依赖树拉下来再传到内网用pip install --no-index --find-links去安装。这个方法可行但是有一个坑依赖列表会被Python版本、操作系统架构影响比如Python3.9和3.11的wheel不通用Windows和Linux的包也不一样。所以pip download时一定要指定目标环境的解释器版本和平台标签。另一条路线是把整个应用用Docker构建成镜像再导出tar包带进内网。这个方法最稳镜像里已经包含了Python环境、依赖、业务代码内网机器只要装了Docker就能直接跑。我们的最终环境里就是镜像交付为主wheel包只给那些不适合容器化的小模块用。顺带提一句内网机器的Docker版本如果太旧要和开发机的构建版本保持兼容否则可能遇到运行时报错。3.3 自建LLM网关解决模型切换与用量审计很多人在内网部署Agent时容易漏掉一个环节模型接入没有做统一抽象。结果就是业务代码里到处写着“调用Ollama”“调用vLLM”一旦模型要切换或新加一个开源模型所有调用点都要改。我们的做法是加了一个轻量的LLM网关服务。它向上提供OpenAI兼容的接口下层可以路由到vLLM、Ollama或自研的模型服务。这样做的好处有三个一是业务层只需要知道网关地址不用关心背后模型是哪一家二是网关层面可以做统一的输入输出日志和审计这在隔离内网里几乎等同于合规要求三是可以做模型灰度比如新来的模型先切20%流量跑一段时间观察结果稳定再全量切换。网关本身不需要造得很复杂几十行代理代码配合一个模型路由配置就行。但这一步强烈建议做否则后期每换一次模型都要跟着改一轮业务代码和测试用例。4. FastAPI LangGraph 的工程落地细节4.1 会话与持久化别再靠内存Session了内网Agent系统的会话管理和外网SaaS完全不是一个路子。外网环境可以用Redis分布式缓存做Session内网环境要看基础设施支持程度。有些隔离内网里根本没有Redis或者有但不允许你随便建这时候怎么办我们的方案是数据库会话。每轮Agent运行前把用户提问、上下文、工具执行记录都落到本地PostgreSQL里Agent状态也通过LangGraph的持久化机制存库。好处很明显服务重启不丢会话后续排查问题可以翻历史记录也方便做数据分析和效果评估。坏处是每次请求要多几次数据库IO但这在内网低并发的场景里完全可以接受。需要强调的是LangGraph提供了checkpointer机制它能在图执行的每个节点保存状态快照这是把Agent流程做成“可恢复”的关键。比如工具调用到一半挂掉了我们可以通过checkpoint恢复流程而不是让用户从头再提交一次。4.2 并发能力FastAPI异步 线程池 vLLM批处理热词里有条“AI Agent怎么扛并发”这确实是生产落地的核心问题。Agent和普通HTTP接口不一样一次请求可能跑几秒钟甚至几分钟中间要多次调用模型推理和工具执行。如果用的是普通的同步写法FastAPI的worker很快就被占满请求全部排队。我采用的方案是三层配合。第一层FastAPI接口声明为async所有IO操作都用异步方式做不阻塞事件循环。第二层LangGraph图执行本身是CPU密集、有阻塞操作的所以放进线程池运行避免阻塞在事件循环里。这里用的是run_in_executor或手动维护的线程池并设置上限。第三层模型推理的并发由vLLM的continuous batching吃掉并发请求到模型层后由vLLM统一调度。并发量化的经验公式大概是Agent实例数×线程池大小×模型推理吞吐。比如部署两个LangGraph worker副本每个线程池8个线程vLLM单机吞吐每秒20个请求那么整体并发能力至少要按实际请求时长来估算而不是看瞬时TPS。4.3 工具调用的可靠性是Agent落地的生死线隔离内网里的Agent工具调用远比读个网页要复杂。Agent向模型发出“帮我查询工单状态”的请求模型返回一段JSON格式的工具调用参数服务端解析后执行工具再把结果回填进上下文。听起来顺滑实际执行中最大的问题是LLM输出的不稳定性。哪怕是Qwen这类中文表现不错的模型在无人值守的离线环境里也经常出现工具调用格式不规范、参数类型错误、甚至幻觉出根本不存在的工具名。我们这里有一个硬性的设计原则工具调用必须经过Schema强校验校验失败自动让Agent重试一次并带上错误信息让模型自行修正多次失败则转为人工处理。如果你的Agent场景涉及写操作我更建议不管模型“感觉多可靠”一律在写操作前挂一个人工审批节点。LangGraph里用interrupt把图挂起等审批结果回来以后再从挂起点恢复执行。这套机制跑生产以后我的体会是它的价值不只是审计合规更在于让业务方对Agent建立信任——知道Agent不会擅自改动数据业务方才会真敢用。4.4 可观测性自建Trace体系别指望外部平台开发阶段用LangSmith做追踪特别舒服但隔离内网里这些外部平台全连不上。你只能自建一套轻量的可观测体系。我的做法是在应用层统一生成trace_id贯穿每一次Agent运行的整个调用链。每次工具调用都记录输入输出、耗时、模型名称。所有日志写到本地文件同时汇入内部日志平台。跑一段时间以后会发现Agent应用和普通Web应用的追踪差异很大普通Web追链路是一次HTTP请求而Agent的链路是一张图有分支有循环所以要额外记录节点转移信息否则排错会非常吃力。排查Agent问题最大的敌人是“不知道它当时在想什么”。只要日志里妥善记录了每轮模型输出、每个工具结果、每次状态跳转那么绝大多数问题都能事后还原不用让业务方帮忙复现。5. 参考业务流程智能工单分发与处理有了前面这些能力接下来用一个具体案例把它们串起来。5.1 这块要解决的业务诉求我们落地的第一个场景是智能工单分发与处理。企业内部每天有大量运维类工单进来比如“某系统服务不可用请排查”“账号登录失败需要重置密码”“磁盘空间不足请清理”。过去这些工单需要人工阅读、判断类型、分配处理人重复性极高。Agent介入以后流程变成这样用户提交工单描述系统调用内部知识库检索相似问题的历史解决方案Agent结合工单原文和检索结果生成处理建议如果建议的处理动作是只读查询直接执行如果需要变更系统配置或重置数据则推送人工审批审批通过后执行。5.2 LangGraph状态机怎么设计我把这个流程画成了一张有向图。图里有五个节点收集工单信息、语义检索、生成处理建议、执行只读操作、等待人工审批并执行写操作。状态在节点之间按条件转移。具体到LangGraph实现每个节点是一个Python异步函数接收全局状态字典返回更新后的状态。全局状态里包含原始工单文本、检索到的参考资料、Agent生成的处理建议、审批结果等字段。模型调用被设计成节点内部的动作但只通过LLM网关发出请求不让模型直接调度业务流程。这里有个设计细节值得展开生成处理建议时我要求模型只能输出“系统当前现象分析”和“下一步建议动作”不输出具体执行代码。具体的执行逻辑由后端工具模板来渲染。这样即使模型输出了一些不着边际的分析最终执行的仍是受控的、预定义好的操作安全隐患会大幅降低。5.3 人工审批这个点必须接扎实人工审批是Agent流程里最容易出bug的地方。很多初学LangGraph的人以为interrupt只是暂停恢复时把图继续跑就行。实际工程里审批动作往往发生在另一个Web界面里审批结果通过接口回传而图实例可能已经被服务重启过状态早就丢了。解决方式是把checkpointer落库。LangGraph支持把状态快照保存到数据库服务重启后仍然可以从某个节点恢复。每次审批动作都是对图的一个信号带上有审批结果的输入让图从挂起点往下继续走。我在做完这部分以后才意识到Agent在业务系统里真正值钱的地方恰恰不是它有多“聪明”而是它和人的协作有多平滑。模型负责提供建议和初步执行人负责最终决策和兜底这套协作机制跑顺畅了业务价值就出来了。6. 常见问题与排查心得6.1 高频问题速查表隔离内网环境里跑Agent有些问题出现频率极高我整理了一张表方便你直接对照排查。问题现象可能原因处理建议模型输出解析失败小模型生成JSON不稳定缺少few-shot约束强制Schema校验、错误重试、提供输出示例工具参数类型不对模型未理解工具定义工具描述写得不清晰精简工具数量、明确参数约束、增加调用的few-shotAgent运行到一半卡住某节点异常但未设置超时或者checkpointer没落库给每个工具调用加超时确保状态可恢复并发上来后响应变慢线程池太小或模型推理成为瓶颈调大线程池上限用vLLM替换简单推理服务语音/向量检索质量差Embedding模型与LLM模型能力不匹配统一模型家族调小top_k增加相似度阈值过滤内网没有LangSmith可观测外部追踪服务不可用自建结构化日志用trace_id贯穿链路Docker镜像带进来跑不起来构建环境与运行环境架构/GLIBC版本不一致使用多阶段构建并在目标机器上提前验证数据库连接池耗尽Agent每次请求占用连接时间太长连接池调大、及时释放、读写分离这张表里最容易被忽略的是最后一条。Agent运行期间会反复调用工具每个工具都服务内部业务系统读写如果业务系统数据库连接池很小Agent一跑并发连接就全被占满了。这个在开发和联调阶段通常暴露不出来因为并发量小生产一压就出事。6.2 一次典型的排查过程实录我在联调阶段遇到过这样一个问题Agent在执行知识库检索后返回的处理建议带有明显误导性。工单明明描述“磁盘空间不足”Agent给出的建议却是“检查服务配置”。当时第一反应是模型能力不行。但排查日志以后发现知识库检索返回的参考资料本身就是旧的、不相关的运维文档切片模型只是基于垃圾的上下文做了合理推测。问题根源不在模型而在检索链路——内网知识库文档没有做版本管理长期迭代以后老文档没有归档才导致检索命中了过期内容。所以排查Agent问题一定要坚持一个原则先查上下文再问模型。模型输出只是结果真正决定输出质量的是喂给它的参考资料和Prompt结构。很多团队一看到Agent答错就归咎于模型太笨其实是数据侧的问题没解决。6.3 两个沉淀下来的工程经验第一个经验内网Agent项目一定要先跑通一个最小闭环再扩展。不是一开始就把所有业务场景、所有工具都堆进去那样只会让排查问题的复杂度爆炸。先选一个高频、低风险的场景把模型离线部署、依赖打包、FastAPI接入、LangGraph编排、人工审批、日志追踪这一整条链跑通后面再复制到其他场景效率反而高得多。第二个经验模型输出质量要用“工程手段”来兜底而不是指望换个更大的模型解决问题。比如工具调用可以约束模型只输出固定格式的意图表达后端再解析执行。知识库问答可以给检索结果加相关性分数阈值低于阈值的直接不给Agent组装上下文。这些手段的稳定性和可控性远超“换一个大模型试试”这种思路。7. 最后说点实在的这次隔离内网AI Agent项目做完以后我最大的感受是技术选型不是最难的最难的是在受控环境里把整套系统的可靠性拉起来。外网开发的时候有各种现成服务和工具链兜底到了隔离环境里每一块砖都得自己铺。所以如果你正打算做类似的事我的建议是先花时间想清楚三个前提模型资源有多少、业务工具边界在哪、人工审批环节怎么接。这三件事定好了项目方向就稳了八成。另外一个很实际的技巧是在内网环境里做Agent开发时尽量把验证和开发阶段的模型与生产模型分开。开发阶段用小模型跑流程生产阶段用大模型做效果然后在流程稳定后再切换到生产模型做一轮完整回归。这样开发效率高试错的成本也低。这套系统后面如果要继续扩展我会倾向于把会话和记忆做得更深让Agent能结合用户历史行为做个性化处理同时把更多只读类业务操作接入工具集合。当然每加一个工具都要重新评估一次权限边界和数据安全这是隔离内网项目里永远不能放松的弦。