
1. 为什么要在隔离内网里折腾 AI Agent先把场景说清楚。所谓隔离内网就是那种物理上跟公网断开、或者只允许极少数白名单流量进出的网络环境。银行核心机房、制造业的工控网、政企的涉密办公区、医院的影像系统内网基本都是这个形态。这类环境里做 AI Agent 工程跟你在自己笔记本上跑个 demo 完全是两码事——外网 API 调不通、pip 装不了包、模型权重下不下来、连个像样的文档都搜不到。我前后在三个不同规模的内网环境里落地过 Agent 项目踩的坑足够写一本小册子。这篇就把整套方法论摊开讲从架构怎么设计、模型怎么进去、MCP 和 Skills 怎么在内网里跑起来、并发怎么扛、出问题怎么排查。目标读者是那些手里有内网资源、想把 AI Agent 真正用起来的工程师不管你是刚接触 Agent 的新手还是已经在外网玩得很溜想往内网迁移的老手都能从里面找到能直接抄的东西。核心矛盾其实就一句话AI Agent 的生态是建立在公网连通性之上的而内网的本质就是切断这种连通性。所有的工程决策本质上都是在解决这个矛盾。想明白这一点后面所有的取舍就都有依据了。2. 内网 AI Agent 的整体架构设计思路2.1 三种典型部署形态与选型依据内网环境千差万别不能一套方案打天下。我把它归成三类你对号入座。第一类是完全物理隔离网线都不通外网。这种环境里所有依赖必须提前准备好模型、依赖包、镜像、数据集全部靠移动介质摆渡进去。Agent 只能用本地推理不能有任何运行时对外请求。第二类是单向可控出口允许通过指定的跳板机或代理访问有限的几个地址。这种相对好办可以把模型服务放在出口可达的位置内网 Agent 通过内网地址调用。第三类是逻辑隔离但物理连通比如 VLAN 划分出来的开发网能访问公司内部的模型网关。这种最舒服基本可以复用外网的工程实践只是把公网地址换成内网地址。选型的时候有个判断口诀先看模型能不能就近部署再看依赖能不能离线满足最后看数据能不能出网。这三条决定了你的架构天花板。我见过太多人一上来就想着接某个云端大模型结果发现数据合规根本过不了返工重来。2.2 分层架构把能变的和不能变的分开内网 Agent 我一般拆成四层从下往上分别是模型层、能力层、编排层、接入层。模型层负责推理可以是本地部署的开源模型也可以是内网模型网关。这一层的关键是接口标准化不管你后面换什么模型上层都不用改。我习惯统一成 OpenAI 兼容格式因为绝大多数框架都认这个。能力层就是工具和 Skills 的集合包括 MCP Server、本地函数、数据库连接器等等。这一层的关键是隔离性每个能力独立进程、独立权限一个挂了不影响其他。编排层是 Agent 的大脑负责规划、调用、反思。这一层的关键是可观测每一步决策都要有日志不然内网里出了问题你连调试手段都没有。接入层是对外的接口可能是 Web、可能是 API、可能是某个业务系统嵌进去的对话框。这一层的关键是鉴权和限流内网不等于没有安全要求。这么分层的好处是模型换了、工具加了、编排逻辑改了各改各的互不干扰。内网环境迭代慢架构的稳定性比外网更重要。2.3 为什么优先选 MCP 而不是自己造轮子MCP 这两年火起来不是没道理的。它本质上是给模型调用外部能力这件事定了一套标准协议把工具的描述、调用、返回都规范化了。在内网环境里这个标准化的价值被放大了。自己造轮子的话你得定义工具 schema、写调用分发、处理错误、管理生命周期每个 Agent 项目都重复一遍。用 MCP 的话工具写一次任何支持 MCP 的客户端都能用。内网里工具复用率越高你的维护成本越低。更重要的是MCP 的传输层可以换成 stdio 或者内网 HTTP天然适配隔离环境。你不需要为了用某个工具去开外网端口工具进程就在本机跑通过标准输入输出通信安全边界清清楚楚。提示内网选 MCP 传输方式时stdio 适合单机单进程场景内网 SSE 或 Streamable HTTP 适合多客户端共享工具服务的场景。别一上来就上 HTTP多一个端口就多一份运维负担。3. 模型与依赖的离线落地实操3.1 模型权重的摆渡与校验模型进内网是第一个硬骨头。假设你要部署一个 7B 到 14B 级别的开源模型权重文件动辄十几 GB靠 U 盘拷要拷到天荒地老。我的做法是分卷压缩加校验。在外网机器上把权重目录打成多个固定大小的分卷比如每个 2GB同时生成一份 SHA256 清单。摆渡进去之后先校验完整性再合并解压。这一步千万别省我遇到过拷贝过程中某个分卷损坏模型加载时报了个莫名其妙的错排查了大半天才发现是文件坏了。校验命令大概长这样# 外网侧生成校验清单 find ./model_weights -type f -exec sha256sum {} \; checksums.txt # 内网侧校验 sha256sum -c checksums.txt如果内网有对象存储直接把分卷传上去用内网的下载工具拉比移动介质快得多。没有的话移动硬盘是最稳的别用 U 盘容量和稳定性都不够。3.2 Python 依赖的离线打包依赖这块最省事的方案是在跟内网同架构同系统的外网机器上用 pip download 把 wheel 全下下来。pip download -r requirements.txt -d ./offline_packages \ --platform manylinux2014_x86_64 \ --python-version 310 \ --only-binary:all:注意--platform和--python-version一定要跟内网目标环境一致不然下下来的 wheel 装不上。有些包没有预编译 wheel只有源码包那就得在内网里现场编译这时候要把编译工具链也准备好gcc、make、python-dev 这些一个都不能少。我一般会额外准备一个constraints.txt把所有依赖的版本钉死。内网环境没法随时升级版本漂移是灾难。3.3 容器镜像的离线导入如果内网用容器跑服务镜像的离线导入是绕不开的。流程是外网docker save成 tar摆渡进去docker load。# 外网 docker save my-agent:1.0 -o my-agent-1.0.tar # 内网 docker load -i my-agent-1.0.tar镜像体积大的话同样分卷。还有个技巧是用多层镜像把基础环境、依赖、应用代码分成不同的层这样更新应用代码时只需要摆渡最上面那一层省很多时间。注意内网的容器 registry 如果有优先推到 registry 再拉比 save/load 优雅得多。没有 registry 的话可以考虑在内网搭一个轻量的私有 registry一次性投入长期受益。4. MCP 与 Skills 在内网里的工程化落地4.1 MCP Server 的内网部署要点MCP Server 在内网部署核心是解决工具进程怎么被 Agent 发现和调用。stdio 模式下Agent 启动时把 MCP Server 作为子进程拉起来通过标准输入输出通信。这种方式最简单不需要网络配置适合工具跟 Agent 在同一台机器上的场景。配置大概是这样{ mcpServers: { local-tools: { command: python, args: [-m, my_mcp_server], env: { DB_HOST: 10.0.0.5, DB_PORT: 5432 } } } }内网 HTTP 模式下MCP Server 作为独立服务跑在某个内网地址上多个 Agent 共享。这种方式适合工具需要被多个 Agent 复用的场景但要注意鉴权和限流内网也不是法外之地。我踩过的一个坑是MCP Server 里如果调用了需要外网的能力比如某个在线翻译 API在内网里会直接超时挂掉。所以每个工具上线前都要过一遍它依赖什么外部资源的检查。4.2 Skills 的组织与版本管理Skills 可以理解成 Agent 的技能包把一组相关的工具、提示词、知识打包在一起。内网里管理 Skills我建议用目录加清单的方式。每个 Skill 一个目录里面放manifest.json描述元信息tools/放工具实现prompts/放提示词模板docs/放使用说明。清单文件记录所有 Skill 的版本和依赖关系。{ name: db-query-skill, version: 1.2.0, description: 内网数据库查询技能, tools: [query_table, list_tables, describe_table], dependencies: { python: 3.10, packages: [psycopg2-binary2.9.9] } }版本管理在内网里尤其重要因为你没法随时回滚到某个历史版本。我的做法是每次更新都保留旧版本目录用软链接指向当前生效的版本出问题一键切回去。4.3 工具权限的最小化原则内网 Agent 能碰的数据往往很敏感工具权限必须收到最紧。数据库工具只给只读账号写操作单独走审批流程。文件工具限制在指定目录用路径白名单。网络工具只允许访问内网白名单地址。这些限制要在工具实现层面做不能指望 Agent 自己懂事。我一般会给每个工具配一个权限声明Agent 调用前先检查TOOL_PERMISSIONS { query_table: {level: read, resources: [db:analytics]}, write_file: {level: write, resources: [fs:/data/agent_output]}, http_get: {level: network, resources: [http://10.0.0.0/8]} }这样即使 Agent 被提示词注入攻击也越不过权限边界。5. 并发扛压与性能调优实战5.1 内网 Agent 的并发瓶颈在哪很多人问 AI Agent 怎么扛并发其实瓶颈往往不在模型推理而在编排层的同步等待。一个典型的 Agent 请求要经历规划、工具调用、结果整合、再规划这么几轮。每一轮工具调用如果是同步的整个请求的延迟就是所有工具延迟之和。并发一上来线程池瞬间打满。我的做法是把工具调用异步化。编排层用异步框架工具调用返回 Future多个独立工具并行执行。这样一轮里如果有三个互不依赖的工具延迟就从三者之和变成三者最大值。import asyncio async def execute_tools(tool_calls): tasks [call_tool(tc) for tc in tool_calls] results await asyncio.gather(*tasks, return_exceptionsTrue) return results5.2 模型推理的批处理与队列本地模型推理的吞吐是有限的。如果并发请求直接打到模型上要么排队排到超时要么显存爆掉。我的方案是加一层请求队列模型服务从队列里批量取请求攒够一批或者等够一个时间窗口就一起推理。批处理能显著提升 GPU 利用率代价是单请求延迟略微增加。队列的深度和批大小要根据显存和延迟要求调。显存 24G 跑 7B 模型的话批大小 8 到 16 比较合适再大就容易 OOM。延迟敏感的场景批大小调小吞吐优先的场景调大。5.3 缓存策略把重复计算挡在前面Agent 场景里重复请求其实很多尤其是那些固定的查询类工具。加一层缓存能省掉大量计算。缓存分两级工具结果缓存和模型响应缓存。工具结果缓存按参数哈希模型响应缓存按提示词哈希。缓存用内网的 Redis 就行设置合理的过期时间。要注意的是涉及实时数据的工具不能缓存比如查当前库存。这类工具要在元信息里标记cacheable: false编排层跳过缓存。提示缓存键一定要包含工具版本和模型版本不然升级之后拿到旧缓存会出现明明改了代码结果没变的诡异现象。6. 常见问题与排查技巧实录6.1 内网 Agent 典型故障速查表现象可能原因排查方向Agent 启动即挂依赖缺失或版本不符检查离线包是否完整版本是否匹配工具调用超时工具依赖外网资源检查工具实现里的外部调用模型加载失败权重文件损坏或格式不对校验 SHA256确认模型格式并发上来后大量超时线程池或队列打满看队列深度、线程池配置响应内容异常缓存了旧版本结果检查缓存键是否含版本号MCP 连接失败传输方式或地址配置错确认 stdio/HTTP 配置一致6.2 没有外网怎么调试内网调试最大的痛点是没法上网搜。我的经验是提前把调试工具和文档准备好。调试工具方面日志系统是命根子。每个环节都要打结构化日志包含请求 ID、时间戳、耗时、输入输出摘要。出问题时按请求 ID 串起来看比什么都管用。文档方面把常用的排查命令、配置模板、错误码含义整理成一份内网 wiki放在内网可访问的地方。新人进来照着查能省很多事。还有个技巧是在内网搭一个最小复现环境把外网遇到的问题在内网复现出来这样调试就有方向了。6.3 我踩过的几个印象深刻的坑第一个坑是时区问题。内网服务器时区设置不一致日志时间对不上排查问题时被误导了好几次。后来统一用 UTC 时间戳问题消失。第二个坑是文件编码。内网里有些老系统的配置文件是 GBK 编码Agent 读进来乱码工具直接报错。后来所有文件读取都显式指定编码或者用 chardet 探测。第三个坑是长连接被中间设备掐断。内网里有些防火墙会掐掉长时间空闲的连接MCP 的 HTTP 长连接经常莫名其妙断掉。解决办法是加心跳定期发个空请求保活。第四个坑是磁盘写满。Agent 的日志和缓存如果不清理很快就把磁盘写满然后整个服务挂掉。后来加了日志轮转和缓存过期策略才算稳住。7. 内网 Agent 工程的一些个人体会在内网做 Agent 工程跟外网最大的区别是你没法依赖随时能修这个前提。外网出问题改个配置重启一下几分钟的事。内网出问题可能要走审批、要摆渡文件、要等窗口期一个简单修复拖成一天。所以内网的工程实践要往稳字上靠。依赖版本钉死配置显式声明日志详尽权限收紧能提前准备的绝不临时抱佛脚。宁可上线慢一点也别上线后天天救火。另外一点体会是内网 Agent 的价值往往不在智能而在自动化。外网用户对 Agent 的期待是它能理解复杂意图、能创造性地解决问题。内网用户更关心的是这件事能不能自动做完别让我手动点。所以内网 Agent 的设计重点应该放在流程打通和稳定性上花哨的推理能力反而是次要的。最后分享一个实用的小技巧内网 Agent 上线前一定要做一轮断网演练。把外网出口彻底断掉看 Agent 还能不能正常跑。能跑通说明你的离线方案是扎实的跑不通正好趁上线前把漏网的依赖补上。这个演练我每次都做救过好几次命。