
1. 企业大模型网关到底解决什么问题1.1 从一个真实场景说起去年下半年我所在的团队接手了一个内部效率工具平台的改造项目。当时的情况是算法组用一套接口调模型后端组用另一套前端组干脆在本地写死了几个API Key直接请求。结果就是——账单没人说得清密钥散落在十几个仓库里某个同事离职后他名下的Key还在被调用安全审计根本过不了。这不是个例。任何一家公司只要同时有三个人以上在调大模型就一定会遇到这几个问题密钥管理混乱、调用成本不可控、模型切换成本高、审计日志缺失、限流和重试各写各的。企业大模型网关LLM Gateway就是在这个背景下被推到台前的。说白了网关就是所有大模型调用的统一入口。业务代码不再直接对接OpenAI、Anthropic或者国内各家厂商的接口而是统一打到网关由网关负责鉴权、路由、计费、限流、缓存、日志。这个思路和当年微服务架构里的API Gateway是一脉相承的只不过这次代理的对象从普通HTTP服务变成了大模型。1.2 网关的核心能力拆解我在选型和自研之间反复横跳过最后落地的方案里网关承担了这么几件事统一协议适配对外暴露一套OpenAI兼容的接口格式对内适配不同厂商。这样业务侧只需要会写一种调用方式换模型时改配置就行不用改代码。密钥托管与租户隔离真实的上游Key只存在网关的密钥管理模块里业务方拿到的是网关自己签发的虚拟Key可以按团队、按项目、按人分配。配额与限流按Token数、按请求数、按并发数三个维度做限制。这个后面会详细讲因为并发控制是坑最多的地方。可观测性每一次调用的输入输出、耗时、Token消耗、命中的模型、返回状态全部落库这是后面做成本分摊和问题排查的基础。缓存与降级相同请求命中缓存直接返回上游故障时自动切换到备用模型。提示网关不是越重越好。我见过有团队一上来就想把RAG、Agent编排、Prompt管理全塞进网关结果网关变成了一个巨型单体任何改动都要全量回归。网关的边界应该清晰——它只管调用这件事编排逻辑放到上层。1.3 为什么自研而不是直接用开源市面上开源的网关方案不少比如One API、LiteLLM这类。我们评估过最后选择在开源基础上做二次开发核心原因是企业内部的鉴权体系和配额策略是高度定制化的。开源方案的用户体系和我们内部的SSO对不上配额维度也不够细。如果你的团队规模不大直接用成熟开源方案完全够用没必要重复造轮子。判断标准很简单当开源方案的扩展点无法满足你的核心诉求且这个诉求是刚需时才考虑自研。2. 网关落地的关键技术细节2.1 协议兼容层怎么设计对外统一成OpenAI的Chat Completions格式这是目前事实上的行业标准。原因很实际几乎所有主流SDK、几乎所有Agent框架、几乎所有CLI工具默认都支持OpenAI格式。你只要兼容了这一套生态里的工具就能直接接进来。协议转换层要处理几个容易忽略的点流式响应的格式差异不同厂商的SSEServer-Sent Events事件结构不一样有的用data:前缀有的带心跳包有的结束标记是[DONE]有的不是。转换层必须把这些归一化否则前端解析会出各种诡异问题。Function Calling/Tool Use的字段映射OpenAI叫tools有的厂商叫functions参数结构也有细微差别。这块要做双向映射且要处理模型不支持工具调用时的降级。多模态输入图片、音频的传参格式各家差异更大建议在网关层做一层抽象用统一的content数组结构。# 一个简化的协议转换示意 def normalize_request(raw_request, target_provider): normalized { model: raw_request.get(model), messages: convert_messages(raw_request[messages]), stream: raw_request.get(stream, False), } if target_provider provider_a: normalized[tools] convert_tools(raw_request.get(tools)) return normalized2.2 并发控制AI Agent场景下的真正难点热搜词里有个ai agent 怎么扛并发这个问题我在实际项目里踩了不少坑。传统Web服务的并发控制思路在这里会失效原因是大模型请求的耗时极长且方差极大。一个普通接口可能50ms返回但一次大模型调用可能3秒也可能因为生成长文本跑到60秒。如果用传统的线程池模型几百个并发请求就能把连接池打满后面的请求全部排队超时。我的做法是异步非阻塞架构网关本身用异步框架比如FastAPI httpx异步客户端一个进程能挂起大量等待中的请求不占用线程。信号量控制上游并发对每个上游厂商维护一个信号量控制同时打到上游的请求数。这个数值要根据厂商的限流策略来定宁小勿大。队列与超时分级普通请求和Agent请求走不同的队列。Agent请求往往链路长、可容忍的延迟高可以给更长的超时和更低的优先级。背压机制当队列深度超过阈值时直接快速失败返回429而不是让请求堆积到雪崩。控制维度传统接口大模型网关单请求耗时毫秒级秒级到分钟级并发模型线程池异步信号量超时策略统一短超时分级超时失败处理快速重试谨慎重试降级注意重试策略要特别小心。大模型调用重试成本很高一次重试就是一次真金白银的Token消耗。我的经验是只对网络错误和5xx重试且最多重试一次对4xx和内容审核类错误绝不重试。2.3 成本核算与配额分配成本这块网关要能精确到每一次调用。核心是记录prompt_tokens和completion_tokens然后乘以对应模型的单价。这里有个坑不同厂商的Token计数方式不一样有的按字符估算有的用自家分词器。网关最好统一用一套分词器比如tiktoken做预估同时以厂商返回的实际用量为准做对账。配额分配我建议做成三层组织级总额、团队级配额、个人级配额。任何一层超限就拒绝。配额周期用滚动窗口比自然月更合理避免月初月末的用量尖峰。3. 自动化编程与CLI工具链实践3.1 为什么CLI在Agent时代重新火了起来热搜里codex cli、zcode cli、gitlab cli、trae cli这些词扎堆出现说明一个趋势CLI正在成为AI Agent最重要的交互形态之一。原因不难理解——Agent需要能执行命令、读写文件、调用工具而CLI天然就是干这个的。相比图形界面CLI更容易被程序化调用更容易嵌入到自动化流程里。我自己的日常开发里CLI工具已经承担了相当一部分重复劳动批量改代码、生成提交信息、跑测试并分析失败原因、根据Issue自动生成修复草稿。这些场景的共同点是输入输出都是文本且需要串联多个步骤正好是Agent擅长的。3.2 Codex CLI的安装与常见报错处理热搜里有个很具体的问题missing optional dependency openai/codex-win32-x64. reinstall codex: npm in。这是典型的平台相关依赖缺失问题。Codex CLI这类工具通常会针对不同操作系统打包不同的原生依赖npm在安装时如果没能正确识别平台就会漏装。处理思路是这样的# 先清理可能损坏的安装 npm uninstall -g openai/codex npm cache clean --force # 重新安装注意指定平台参数 npm install -g openai/codex # 如果还是报平台依赖缺失手动安装对应包 npm install -g openai/codex-win32-x64如果手动装平台包还不行检查两件事一是Node版本是否满足要求很多CLI工具要求Node 18以上二是npm的optionalDependencies是否被某些配置禁用了。有些公司的npm镜像会裁剪optional依赖这也是常见原因。提示遇到无法发送消息、显示更新agent沙盒这类报错八成是网络请求被拦截或者认证失效。先确认API Key是否有效再检查是否有代理配置冲突。CLI工具对网络环境比普通应用敏感得多。3.3 Codex CLI的常用命令Codex CLI里几个高频命令值得记一下/compact压缩当前会话上下文。Agent跑久了上下文会爆这个命令能把历史对话做摘要压缩腾出Token空间。/model切换当前使用的模型。不同任务用不同模型简单任务用便宜的复杂推理用强的。/resume恢复之前的会话。中断了不用从头再来。这几个命令背后其实对应了Agent的三个核心问题上下文管理、模型路由、状态持久化。理解了这三点用任何Agent工具都能快速上手。3.4 从CLI到自动化流水线单个CLI命令只是起点真正的价值在于把CLI串成流水线。举个我实际在用的例子每次提交代码前自动跑一个脚本它会调用CLI工具做三件事——检查代码风格、生成变更摘要、根据diff推测可能受影响的测试用例。整个过程不需要我手动干预。#!/bin/bash # pre-commit自动化脚本示意 codex-cli review --diff HEAD~1 /tmp/review.txt codex-cli summarize --input /tmp/review.txt codex-cli test-suggest --diff HEAD~1 | xargs -I {} run-test {}这种流水线的关键是把每个CLI调用做成幂等且可组合的。每个命令只干一件事输出结构化文本下一个命令消费上一个的输出。这样任何一个环节出问题都好定位。4. Agent开发的核心概念与架构选型4.1 Agent到底是什么和普通程序有什么区别热搜里agent是什么、harness和agent区别这两个问题问到了点子上。我的理解是普通程序是确定性的给定输入必然得到确定的输出路径Agent是不确定性的它自己决定下一步做什么。Agent的核心循环是感知-决策-行动观察当前状态决定调用哪个工具执行工具观察结果再决定下一步。这个循环直到任务完成或达到终止条件。那harness和agent的区别呢Harness更像是Agent的运行容器和约束框架。它负责给Agent提供工具、管理上下文、执行安全策略、记录轨迹。Agent是大脑Harness是身体和规则。一个设计良好的Harness能让Agent更安全、更可控这也是为什么现在很多团队把精力放在Harness上而不是Agent本身。4.2 Agent架构的几种主流形态架构形态特点适用场景ReAct推理与行动交替通用任务工具调用Plan-and-Execute先规划再执行复杂多步任务Multi-Agent多个Agent协作需要分工的复杂流程Reflexion带自我反思需要迭代优化的任务我个人的经验是不要一上来就上Multi-Agent。大部分场景单Agent加好的工具集就够了。Multi-Agent的调试成本极高Agent之间的通信开销和错误传播会让问题排查变成噩梦。只有当任务确实可以清晰拆分成独立子任务时才考虑多Agent。4.3 Agent记忆系统的设计agent记忆是另一个高频问题。Agent的记忆分短期和长期短期记忆就是当前会话的上下文长期记忆需要外部存储。短期记忆的管理核心是上下文窗口的取舍。全量塞进去会爆Token全丢掉又丢失信息。我的做法是分层最近的对话保留原文较早的对话做摘要关键事实比如用户偏好、任务约束单独抽出来存成结构化数据。长期记忆我一般用向量库加结构化存储的组合。向量库存语义相关的历史片段结构化库存确定的事实。检索时两者结合既保证相关性又保证准确性。注意记忆系统最大的坑是记忆污染。如果Agent把错误的推理结果也存进长期记忆后续会不断被误导。所以写入长期记忆前一定要有校验机制宁可少存也不要存错。4.4 Agent安全不能事后补agent安全这个词最近被提得很多我觉得这是好事。Agent能执行命令、能读写文件、能调用外部API一旦被恶意输入操控后果比普通应用严重得多。几个必须做的防护工具权限最小化Agent能用的工具要严格限定能读的目录、能执行的命令都要白名单。输入输出过滤对进入Agent的用户输入做注入检测对Agent的输出做敏感信息扫描。沙盒执行所有代码执行、命令执行都在隔离环境里跑限制资源占用。人工确认关键操作删除文件、发送请求、修改配置这类操作必须有人工确认环节。我见过有团队为了演示效果给Agent开了完整的shell权限结果一个Prompt注入就让Agent把测试环境的数据库删了。这种教训一次就够了。5. 从零搭建一个最小可用Agent的实操5.1 环境准备与依赖安装先明确目标搭一个能读文件、能执行命令、能调用大模型的最小Agent。技术栈选Python因为生态最全。# 创建虚拟环境 python -m venv agent-env source agent-env/bin/activate # Windows用 agent-env\Scripts\activate # 安装核心依赖 pip install openai httpx pydanticAPI Key的获取和管理是第一步。不管用哪家的服务Key都不要硬编码在代码里用环境变量或者密钥管理服务。export OPENAI_API_KEYyour-key-here5.2 核心循环的实现Agent的核心就是一个循环我把它拆成最简形式import os from openai import OpenAI client OpenAI(api_keyos.environ[OPENAI_API_KEY]) def agent_loop(task, max_steps10): messages [{role: user, content: task}] for step in range(max_steps): response client.chat.completions.create( modelgpt-4o, messagesmessages, toolsTOOLS, ) msg response.choices[0].message messages.append(msg) if not msg.tool_calls: return msg.content for tool_call in msg.tool_calls: result execute_tool(tool_call) messages.append({ role: tool, tool_call_id: tool_call.id, content: result, }) return 达到最大步数限制这段代码虽然短但包含了Agent的所有核心要素循环、工具调用、结果回填、终止条件。max_steps这个限制非常重要没有它Agent可能陷入死循环无限消耗Token。5.3 工具的定义与安全边界工具定义要清晰参数要明确每个工具都要有输入校验TOOLS [ { type: function, function: { name: read_file, description: 读取指定路径的文件内容, parameters: { type: object, properties: { path: {type: string, description: 文件路径} }, required: [path], }, }, }, ] def execute_tool(tool_call): name tool_call.function.name args json.loads(tool_call.function.arguments) if name read_file: path args[path] # 安全校验限制在允许的目录内 if not is_path_allowed(path): return 错误路径不在允许范围内 with open(path, r) as f: return f.read()is_path_allowed这个校验是必须的。没有它Agent可以被诱导读取系统敏感文件。这就是前面说的工具权限最小化的具体落地。5.4 上下文管理与成本控制Agent跑起来后上下文会快速膨胀。我的做法是每轮循环后检查Token数超过阈值就触发压缩def maybe_compact(messages, threshold6000): total count_tokens(messages) if total threshold: # 保留系统提示和最近N轮中间部分做摘要 return compact_messages(messages) return messages成本控制上我给每个Agent任务设一个Token预算超了就强制终止。这个预算根据任务复杂度动态调整简单任务给少点复杂任务给多点。6. 常见问题排查与避坑经验6.1 高频报错速查报错信息可能原因处理方式missing optional dependency平台依赖未安装手动安装对应平台包internetopenurl failed网络请求失败检查网络和认证配置403错误权限或配额问题检查Key权限和配额agent execution terminated执行超时或异常查看日志定位具体步骤无法发送消息认证失效或沙盒异常重新认证重启沙盒6.2 我踩过的几个坑第一个坑以为并发越高越好。早期我给网关设了很高的并发上限结果上游厂商直接限流大量请求失败。后来改成保守的并发数加队列稳定性大幅提升。上游的限流策略永远比你想象的严格。第二个坑忽略流式响应的错误处理。流式响应中途出错时HTTP状态码可能已经是200了错误信息藏在SSE事件里。如果不解析事件内容前端会以为请求成功但拿到空数据。必须在流式解析里检查每个事件的错误字段。第三个坑Agent的工具描述写得太模糊。工具描述是给模型看的写得含糊模型就会乱调用。比如处理文件这种描述模型根本不知道是读还是写。描述要具体到读取指定路径的文本文件内容并返回。第四个坑没有做幂等。Agent重试时可能重复执行有副作用的操作比如重复发邮件、重复下单。所有有副作用的工具都要支持幂等用请求ID去重。6.3 性能优化的几个实用技巧连接复用网关到上游的HTTP连接要复用别每次请求都新建连接握手开销在长耗时场景下占比不小。批量请求如果业务允许把多个小请求合并成一个批量请求能显著降低单位成本。预热对延迟敏感的场景提前建立连接和加载模型避免冷启动。缓存分层精确匹配的缓存放内存语义相似的缓存放向量库两级配合。7. 一些个人体会这套网关加Agent的东西我从最初的想法到真正在生产环境跑稳前后折腾了大半年。最大的感受是技术选型上不要追求新要追求稳。热搜上每天都有新框架新工具但企业环境里一个能稳定运行、出问题能快速定位的方案比一个功能炫酷但三天两头出幺蛾子的方案有价值得多。另外就是Agent的能力边界很大程度上取决于你给它的工具和约束。工具设计得好Agent就聪明约束设得合理Agent就安全。把精力花在工具和Harness上比花在调Prompt上回报率高得多。最后分享一个小技巧给Agent加一个思考日志让它每步决策都输出简短的理由。这个日志平时看着啰嗦但出问题时是排查的救命稻草能让你快速知道Agent是在哪一步走偏的。