
1. 项目缘起与整体设计思路1.1 为什么要在隔离内网里折腾 AI Agent先说清楚这个项目的背景。我所在的团队负责一套内部业务系统的运维和迭代这套系统跑在完全隔离的内网环境里——没有外网出口没有公网依赖所有软件包、镜像、模型权重都得靠离线方式导入。过去两年团队一直想引入 AI Agent 来辅助日常的工单处理、日志分析和配置变更但每次一调研就卡在同一个问题上主流方案几乎都默认你能访问外部 API或者至少能拉取在线依赖。真正让我下决心动手的是去年底一次大规模故障复盘。当时一个配置项被误改导致下游三个服务连锁报错值班同学花了将近四十分钟才定位到根因。如果有一个能读懂内部文档、能调用内部工具链、能在审批通过后自动执行回滚的 Agent这个时间至少能压缩到五分钟以内。这个念头一旦冒出来就再也压不下去了。所以这个项目的核心目标很明确在完全隔离的内网环境中搭建一套可运行、可扩展、可审计的 AI Agent 工程体系让它能真正“下地干活”而不是停留在演示阶段。适合阅读这篇内容的是那些同样受限于内网环境、但又想落地 Agent 能力的运维工程师、平台开发者和技术负责人。如果你所在的环境能直连公网这篇内容里的很多取舍你可能用不上但关于审批机制和工具编排的思路依然有参考价值。1.2 整体架构的取舍逻辑隔离内网这个约束条件直接决定了架构的每一个关键选择。我先说结论再解释为什么。整体架构分四层模型推理层、Agent 编排层、工具接入层、审批与审计层。模型推理层跑的是本地部署的开源模型通过内部推理服务暴露接口Agent 编排层负责意图理解、任务拆解和工具调度工具接入层把内部系统的 API、脚本、数据库查询封装成标准化的工具描述审批与审计层则负责在敏感操作前拦截、记录、等待人工确认。为什么这么分因为隔离环境最大的痛点是不可控的外部依赖。你不能假设某个在线服务永远可用也不能假设模型能实时更新。把推理层独立出来意味着模型可以单独升级、单独扩容不会牵动上层逻辑。把工具接入层独立出来意味着新增一个内部系统接入时只需要写一个适配器不用改 Agent 的核心代码。这里有个关键决策Agent 编排层没有采用重量级的工作流引擎而是用了轻量的状态机加工具注册机制。原因很简单内网环境的调试成本极高每次改动都要走离线部署流程。工作流引擎虽然功能强大但配置复杂、排错困难一旦出问题光看日志就得花半天。轻量状态机的好处是逻辑透明每一步的状态流转都能在日志里看得清清楚楚出问题直接定位到具体环节。另一个决策是关于工具描述格式的。我参考了 MCP Tools 的设计思路但做了大幅简化。标准 MCP 协议功能很全但引入的依赖也多。在内网环境里每多一个依赖就多一份离线打包的负担。所以我只保留了最核心的部分工具名称、功能描述、参数 schema、调用方式。这样既能让模型理解工具用途又能把实现复杂度控制在可维护的范围内。1.3 和公网方案的差异对比很多人会问内网方案和公网方案到底差在哪。我整理了一个对比表把关键差异列清楚。维度公网方案隔离内网方案模型来源在线 API 或云端推理本地部署开源模型依赖管理包管理器在线拉取离线包导入版本锁定工具调用可直接访问外部服务仅限内部系统 API审批机制可选多为事后审计强制敏感操作前置拦截调试方式在线日志、实时追踪本地日志、离线回放更新频率跟随上游随时更新按需更新版本冻结这张表里最值得说的是审批机制。公网方案里审批往往是可选项因为很多操作本身风险可控。但在内网环境里Agent 能碰到的都是核心业务系统一次误操作可能就是生产事故。所以我把审批做成了强制环节任何涉及写操作、配置变更、服务重启的工具调用都必须经过人工确认才能执行。这不是不信任 Agent而是内网环境的容错空间太小必须用流程来兜底。还有一个差异是调试方式。公网方案可以实时看追踪、看指标内网方案只能靠本地日志。这就要求日志必须打得足够细每一步的输入输出、状态流转、耗时都要记录。我后来甚至加了一个离线回放功能把一次完整的 Agent 执行过程录下来可以在本地反复重放方便排查问题。2. 核心细节解析与实操要点2.1 模型推理层的本地化部署模型推理层是整个体系的地基。内网环境没法调外部 API所以必须本地部署。我选的是中等规模的开源模型参数量在可接受范围内推理延迟能控制在秒级。选型时主要考虑三个因素推理速度、中文理解能力、工具调用准确率。推理速度直接决定用户体验。如果每次工具调用都要等十几秒值班同学宁愿自己去查日志。我实测下来在单张推理卡上中等规模模型的首次响应能压到两秒以内后续对话因为上下文缓存能更快一些。这个速度虽然比不上公网 API但在内网场景里已经够用了。中文理解能力是刚需因为内部文档、工单描述、日志信息全是中文。有些开源模型英文很强但中文一塌糊涂工具描述稍微复杂一点就理解偏了。我试过好几个模型最后选了一个中文语料训练比较充分的版本。工具调用准确率是最容易被忽视的指标。模型不仅要理解用户意图还要能正确选择工具、正确填充参数。这里有个坑很多模型在对话场景下表现很好但一到结构化输出就拉胯参数格式经常出错。解决办法是在推理层加一层输出校验把模型返回的工具调用请求做一次 schema 校验不合法就重新生成。部署方式上我用的是容器化方案把模型权重、推理框架、依赖库全部打包进镜像。这样做的原因是内网环境的机器配置可能不一致容器能保证运行环境统一。镜像构建在外部完成然后通过离线方式导入内网。这里要注意镜像体积会很大导入前最好做一次压缩并且确认目标机器的存储空间足够。提示模型权重文件通常有几个 GB 到几十个 GB离线导入时建议分卷压缩避免单文件过大导致传输中断后需要重传。推理服务的接口设计也有讲究。我没有直接用模型原生的接口而是在外面包了一层统一网关。网关负责请求排队、超时控制、重试逻辑和结果缓存。为什么要加这层因为内网环境的推理资源有限多个 Agent 实例同时请求时如果没有排队机制很容易把推理服务打挂。网关的缓存也很有用相同的查询可以直接返回缓存结果减少推理压力。2.2 工具接入层的标准化封装工具接入层是 Agent 和内部系统之间的桥梁。这一层的核心任务是把各种异构的内部接口统一成 Agent 能理解的标准格式。我把它拆成三个部分工具注册、参数校验、调用执行。工具注册解决的是“Agent 知道有哪些工具可用”的问题。每个工具都要有清晰的名称、功能描述和参数说明。名称要短最好用动词开头比如query_log、restart_service、update_config。功能描述要准确不能有歧义因为模型就是靠这段描述来判断该不该用这个工具。参数说明要完整每个参数的类型、是否必填、取值范围都要写清楚。这里有个经验功能描述里要明确写出工具的适用场景和限制条件。比如restart_service这个工具描述里要写清楚“仅用于服务无响应且确认需要重启的场景重启会导致服务短暂不可用”。这样模型在决策时会更谨慎不会动不动就重启服务。参数校验是第二道防线。模型生成的参数不一定合法可能在类型上出错也可能超出取值范围。我在工具注册时定义了每个参数的 schema调用前先做一次校验。校验不通过就返回错误信息给模型让它重新生成。这个机制能挡掉大部分低级错误。调用执行是最后一步。这里的关键是超时控制和错误处理。内部系统的响应时间参差不齐有的接口几百毫秒就返回有的可能要几十秒。我给每个工具都设了独立的超时时间超时后直接返回失败不让 Agent 无限等待。错误处理也要细致把内部系统返回的错误码转换成模型能理解的描述方便它决定下一步动作。工具接入还有一个容易被忽视的点幂等性。有些工具调用可能会重复执行比如网络抖动导致的重试。如果工具本身不是幂等的重复执行就可能出问题。我的做法是在工具层加一个请求 ID相同的请求 ID 只执行一次后续请求直接返回之前的结果。这个机制对于写操作尤其重要。2.3 审批机制的设计与实现审批机制是内网 Agent 工程里最不能省的部分。我的设计原则是读操作放行写操作拦截敏感操作双重确认。读操作包括查询日志、读取配置、查看服务状态等这些操作不会改变系统状态风险可控所以直接放行。写操作包括修改配置、重启服务、执行脚本等这些操作可能影响生产环境必须经过人工确认。敏感操作则是在写操作的基础上再加一层比如涉及核心数据库的变更需要两个人分别确认。审批流程的实现方式是在 Agent 编排层加一个拦截器。当 Agent 决定调用某个工具时拦截器先检查这个工具的审批级别。如果是读操作直接放行如果是写操作拦截器会暂停执行生成一条审批请求推送给值班同学。值班同学在内部审批系统里看到请求后可以选择批准或拒绝。批准后拦截器继续执行工具调用拒绝则返回拒绝信息给 Agent让它调整策略。审批请求的内容要足够详细让审批人能在不查额外信息的情况下做出判断。我设计的审批请求包含这几个字段请求 ID、发起时间、Agent 实例标识、工具名称、参数详情、预期影响、回滚方案。其中“预期影响”和“回滚方案”是重点审批人最关心的就是这两个。注意审批请求里的参数详情要脱敏不能把敏感信息直接展示出来。我的做法是对参数值做掩码处理只展示结构不展示具体内容。审批超时也要处理。如果审批请求发出去后值班同学一直没响应不能无限等待。我设了一个默认超时时间超时后自动拒绝并通知 Agent 重新规划。这样能避免 Agent 卡死在等待状态。审批日志要完整记录包括谁审批的、什么时候审批的、审批结果是什么。这些日志不仅是审计需要也是后续优化的依据。比如某个工具的审批拒绝率特别高就说明要么工具描述有问题要么模型决策有问题需要针对性调整。2.4 编排层的状态管理与上下文控制编排层是 Agent 的大脑负责意图理解、任务拆解和工具调度。内网环境对编排层的要求是逻辑透明、状态可查、异常可恢复。我用的是状态机模型把 Agent 的执行过程拆成几个明确的状态接收请求、理解意图、规划任务、执行工具、等待审批、生成回复、结束。每个状态之间的流转都有明确的触发条件状态变更时记录日志。这样做的最大好处是排错方便出问题时直接看状态流转日志就能知道卡在哪一步。上下文控制是另一个重点。内网环境的模型上下文窗口有限不能把整个对话历史都塞进去。我的做法是分层管理上下文系统提示词、工具描述、当前任务上下文、历史对话摘要。系统提示词和工具描述是固定的每次请求都带上当前任务上下文是动态的只保留和当前任务相关的信息历史对话则做摘要处理只保留关键结论。任务拆解的策略也值得一说。复杂任务不能一步到位要拆成多个子任务逐个执行。比如“排查服务 A 的响应变慢问题”可以拆成查询服务 A 的当前状态、查询最近的日志、查询依赖服务的状态、分析可能的瓶颈、给出建议。每个子任务对应一个或多个工具调用执行完一个再执行下一个。这里有个坑子任务之间的依赖关系要处理好。有些子任务可以并行有些必须串行。如果依赖关系搞错了可能导致工具调用顺序错误拿到无效结果。我的做法是在任务规划阶段就明确依赖关系生成一个任务图然后按拓扑顺序执行。异常恢复也是编排层要考虑的。如果某个工具调用失败Agent 不能直接崩溃要有重试和降级策略。我的做法是失败后先重试一次如果还失败就尝试用替代工具如果替代工具也没有就返回失败信息并给出建议。整个过程的状态变更都要记录方便后续分析。3. 实操过程与核心环节实现3.1 离线环境的依赖打包与导入离线环境的依赖管理是个体力活但必须做扎实。我的流程是在外部环境构建、打包、校验然后导入内网、解压、部署。构建阶段我会把所有依赖列一个清单包括模型权重、推理框架、Python 库、系统工具。清单要精确到版本号不能有模糊范围。然后用容器化方式构建一个完整的运行环境镜像。镜像构建完成后做一次完整性校验确保所有依赖都能正常工作。打包阶段把镜像导出成 tar 文件然后分卷压缩。分卷大小根据传输介质的限制来定一般控制在单个文件几百 MB 到 1 GB 之间。压缩完成后生成校验和文件导入内网后先校验再解压。导入阶段把分卷文件传到内网机器上合并、解压、加载镜像。加载完成后启动容器跑一次冒烟测试确认推理服务能正常响应。这里有个经验镜像里不要包含任何敏感信息比如密钥、证书、内部地址。这些信息应该通过配置文件或环境变量注入而不是硬编码在镜像里。这样镜像可以复用也避免了信息泄露风险。提示离线导入前先确认目标机器的磁盘空间和内存是否足够。模型推理对内存要求较高空间不足会导致加载失败。3.2 工具适配器的编写与注册工具适配器是连接 Agent 和内部系统的具体实现。我以“查询服务日志”这个工具为例说明完整的编写和注册过程。首先定义工具的元信息名称叫query_service_log功能描述是“查询指定服务在指定时间范围内的日志支持按关键字过滤”。参数有三个service_name服务名称必填、time_range时间范围必填、keyword关键字可选。然后写适配器的实现逻辑。内部系统的日志查询接口是一个 HTTP API需要传服务名、起始时间、结束时间和关键字。适配器负责把 Agent 传来的参数转换成 API 需要的格式调用 API然后把返回结果转换成 Agent 能理解的格式。参数转换时要注意时间格式。Agent 传来的时间可能是自然语言描述比如“最近一小时”适配器要把它转换成具体的时间戳。这个转换逻辑要健壮能处理各种常见的时间描述。结果转换时要注意截断。日志查询可能返回大量数据不能全部塞给模型。我的做法是只返回前 N 条并附上总条数让模型知道还有更多数据。N 的取值要平衡信息量和上下文长度我一般设成 20 到 50 条。注册时把工具的元信息和适配器实现一起注册到工具注册表里。注册表是一个中心化的管理组件Agent 通过它来发现和调用工具。注册时要做一次校验确保元信息完整、适配器可调用。3.3 审批流程的完整走通审批流程的走通需要三个组件配合Agent 编排层、审批服务、通知渠道。Agent 编排层在决定调用写操作工具时生成审批请求发送给审批服务。审批请求包含前面提到的那些字段。审批服务收到请求后生成一个审批任务推送到通知渠道。通知渠道我用的是内部即时通讯工具。审批任务以卡片形式展示包含请求详情和批准/拒绝按钮。值班同学点击按钮后审批服务收到结果更新审批任务状态并通知 Agent 编排层。Agent 编排层收到审批结果后如果批准继续执行工具调用如果拒绝返回拒绝信息给模型让它重新规划。整个过程的每一步都记录日志。这里有个细节审批请求的推送要保证可达。如果值班同学没看到通知审批就会卡住。我的做法是加一个提醒机制审批请求发出后如果 N 分钟内没响应再推送一次。同时审批服务提供一个查询接口值班同学可以主动查看待审批任务。审批结果的处理也要考虑并发。多个 Agent 实例可能同时发起审批请求审批服务要能正确处理并发避免状态混乱。我用的是队列加锁的方式保证每个审批任务的状态变更都是原子的。3.4 一次完整的 Agent 执行实录我以“服务 A 响应变慢”这个工单为例完整走一遍 Agent 的执行过程。工单内容是“服务 A 从今天上午十点开始响应变慢请排查原因。”Agent 收到工单后进入理解意图状态。模型分析后认为这是一个排查类任务需要查询服务状态、查询日志、分析依赖。进入规划任务状态Agent 把任务拆成四个子任务查询服务 A 的当前状态、查询服务 A 最近一小时的日志、查询服务 A 的依赖服务状态、综合分析给出结论。进入执行工具状态第一个子任务调用query_service_status工具返回服务 A 的 CPU、内存、响应时间等指标。发现响应时间确实偏高但 CPU 和内存正常。第二个子任务调用query_service_log工具查询最近一小时的日志。日志里发现大量数据库连接超时的错误。第三个子任务调用query_service_status工具查询依赖的数据库服务状态。发现数据库连接数接近上限。进入综合分析状态模型结合三个子任务的结果得出结论服务 A 响应变慢是因为数据库连接数接近上限导致连接超时。建议增加数据库连接池大小或者排查是否有连接泄漏。整个执行过程耗时约十五秒其中工具调用占了大部分时间。如果涉及写操作比如调整连接池大小就会触发审批流程等待值班同学确认。这个实录说明了一个关键点Agent 的价值在于快速聚合信息、给出方向性结论而不是替代人工做最终决策。排查类任务可以全自动但变更类任务必须有人把关。4. 常见问题与排查技巧实录4.1 模型输出格式错误的排查模型输出格式错误是最常见的问题。表现是模型返回的工具调用请求不符合 schema比如参数类型错误、缺少必填参数、参数值超出范围。排查思路是先看模型原始输出确认是模型理解问题还是格式问题。如果是理解问题说明工具描述不够清晰需要优化描述。如果是格式问题说明模型的输出约束不够强需要在提示词里加强格式要求。我的解决办法是在推理层加一个输出解析器把模型输出解析成结构化数据。解析失败时把错误信息返回给模型让它重新生成。同时记录失败案例定期分析针对性优化提示词。注意不要指望模型一次就能输出正确格式要有重试机制。我一般设三次重试三次都失败就返回错误。4.2 工具调用超时与重试策略工具调用超时在内网环境很常见因为内部系统的响应时间不稳定。超时后的处理策略直接影响用户体验。我的策略是首次超时后重试一次重试还超时就返回失败。重试时要判断工具是否幂等非幂等工具不能盲目重试。对于查询类工具重试是安全的对于写操作工具重试可能导致重复执行要谨慎。超时时间要根据工具类型设置。查询类工具可以设短一点比如五秒写操作工具可以设长一点比如三十秒。超时时间不是越长越好太长会拖慢整体响应。重试失败后Agent 要能降级处理。比如查询日志超时可以尝试查询摘要信息查询状态超时可以尝试查询缓存数据。降级策略要在工具注册时定义好。4.3 审批卡住与通知丢失的处理审批卡住是运维同学最头疼的问题。表现是 Agent 发起了审批请求但值班同学没收到通知或者收到了但没处理。排查思路是先确认审批服务是否正常再看通知渠道是否可达最后看审批任务的状态。如果审批服务正常、通知渠道可达但任务状态一直是待审批说明值班同学没看到或没处理。我的解决办法是加一个超时自动拒绝机制。审批请求发出后如果 N 分钟内没响应自动拒绝并通知 Agent。同时审批服务提供一个待办列表值班同学可以主动查看。通知渠道也要做冗余不能只依赖一个渠道。还有一个细节审批请求的推送要带上下文。值班同学可能同时处理多个工单审批请求里要写清楚是哪个工单、哪个 Agent 发起的、涉及什么操作。这样值班同学能快速判断。4.4 常见问题速查表我把实际运维中遇到的问题整理成一张速查表方便快速定位。问题现象可能原因排查方法解决办法模型无响应推理服务挂了检查推理服务日志重启推理服务工具调用失败内部系统不可达检查网络和接口状态重试或降级审批卡住通知未送达检查通知渠道手动推送或超时拒绝输出格式错误提示词不够强查看模型原始输出优化提示词加重试上下文超限历史对话太长查看上下文长度做摘要截断历史执行速度慢工具调用耗时查看各步骤耗时优化工具或并行调用这张表是我踩了无数坑之后总结出来的基本上覆盖了八成以上的常见问题。遇到新问题时先对照这张表排查能省不少时间。4.5 几个血泪教训最后分享几个我踩过的坑都是真金白银换来的。第一个坑不要相信模型的自我评估。模型有时候会说自己“已经完成了任务”但实际上工具调用失败了。我的做法是加一层结果校验工具调用成功与否以实际返回为准不以模型的描述为准。第二个坑审批机制不能太复杂。我一开始设计了多级审批结果值班同学嫌麻烦经常直接拒绝。后来简化成一级审批通过率反而高了。审批的目的是兜底不是增加负担。第三个坑日志要打全但不要打太多。日志太少排不了错日志太多看不过来。我的做法是分级打日志关键步骤打 INFO详细数据打 DEBUG默认只输出 INFO。排查问题时再开 DEBUG。第四个坑工具描述要定期 review。内部系统会迭代工具的行为可能变化但描述没更新导致模型决策错误。我后来加了一个机制每次内部系统变更后同步 review 相关工具的描述。第五个坑不要忽视冷启动。推理服务刚启动时第一次请求会特别慢因为要加载模型。我的做法是启动后先跑一次预热请求把模型加载到内存里这样正式请求就快了。这些经验在官方文档里基本找不到都是实际运维中一点点积累的。内网环境的 Agent 工程技术选型只是一部分更多的是流程设计和细节打磨。把审批做扎实把日志打清楚把异常处理到位系统才能稳定跑起来。