先写业务接入契约
很多多模型项目的第一版都很轻松:传 provider、model 和 prompt,返回一段 text。真正接入不同供应商后,差异才冒出来。系统指令放哪、会话状态谁保存、工具调用怎么回传、流式错误长什么样、429 要等多久、模型名是不是还可用,这些细节不会因为大家都叫大模型就自动统一。开始编码前先定义业务真正需要的能力,例如文本、图片、结构化输出、工具调用、流式、状态延续和异步任务,每项标成 required、optional 或 unsupported。
密钥分开保存
每家供应商使用独立凭据、预算、告警和轮换记录。密钥只进入自己的服务端环境或密钥存储,前端表单可以提交一次,但页面、localStorage、日志和 API 响应都不能再次出现明文。保存时使用稳定的工作台主密钥派生加密密钥,随机 IV 加认证标签;读取列表只返回 enabled 与 last4。测试和生产凭据分开,轮换时先启用新密钥、健康检查通过,再撤销旧密钥。仓库和构建包还要做明文扫描。
能力矩阵不能靠猜
模型名不要永久硬编码。按官方列表和文档维护白名单,为每个模型记录输入模态、结构化输出、工具调用、流式、状态续接、上下文限制、价格版本与退役日期。别名和固定快照要分开:固定版本适合稳定回归,滚动别名适合获得更新,但行为可能变化。接口能列出模型,不代表账号一定有权限;健康检查要发一个最小请求,并把 401、403、404、429 和 5xx 分类显示。
适配请求与状态
业务层可以提供统一 generate(request),供应商适配器保留真实差异。统一请求包括 messages、system、attachments、tools、responseSchema、stream、stateRef、timeout 和 metadata。适配器负责角色、内容块、工具定义与会话字段转换。状态不能只留一个 history 字符串,有的接口由调用方传完整历史,有的支持服务端 conversation 或 previous response。改变 system 指令、图片 MIME、工具 call ID 时都要做跨供应商样例测试。
统一响应但保留差异
统一响应至少包含 text、structured、toolCalls、finishReason、usage、providerRequestId、rawStatus 和 warnings。保留受控的原始响应用于排障,但必须脱敏和过期。流式事件可归一为 start、textDelta、toolCall、usage、error、done,同时保留原始事件类型。客户端断开时取消上游;上游已经完成而浏览器没收到,结果写入任务记录供重新读取,不能默认再生成一次。工具结果按供应商 call ID 回传,不能按出现顺序猜。
成本和日志要按项目看
每次调用至少记录 projectId、runId、provider、model、开始时间、耗时、输入输出 token、缓存 token、工具调用数、状态、request ID 与 fallback。业务日志不保存完整提示和敏感正文,确实需要排障的原始响应应脱敏、限制权限并设置过期时间。预算按项目、Agent 和供应商三层汇总,达到软阈值先提醒,达到硬阈值暂停新任务并保留人工放行入口。只看整月账单很难定位是哪条循环、哪个 Skill 或哪个备用模型把费用推高。
模型升级和下线要能演练
供应商宣布模型退役时,先在测试环境把固定样例跑过候选模型,比较结构化字段、工具参数、拒答、中文质量、延迟与成本。通过后更新白名单,让少量非关键任务试运行,再逐步扩大;旧模型在观察期内保留快速回退。迁移不能只改一个字符串,因为默认温度、上下文、工具调用和状态字段都可能变化。正式切换记录版本、日期、负责人和结果差异,失败时能回到上一套适配器与模型组合。把退役当成正常运维,才不会在接口突然报错时临时换模型。
接入完成也要保留人工开关
每个供应商、模型和 Agent 都应有独立启停开关,配置错误时可以只停一条路径,不影响整个工作台。开关状态保存在服务端并进入审计日志,前端按钮只发请求,不能成为唯一权限。生产事故时先停有问题的模型和自动重试,再保留只读查询与人工任务;恢复后逐步放量。能局部隔离问题,比拥有很多备用接口更重要。
错误、限额与回归测试
认证与权限错误通常不重试,429 读取限额或 retry-after 并指数退避,5xx 与网络错误只做有限重试。fallback 必须记录原模型、新模型和原因,不能静默切换。准备固定测试包:短中文、长文本、JSON、图片、工具调用、两轮状态、流式中断、非法模型和限额错误。每次升级适配器或换模型都跑同一批样例,比较字段完整性与任务结果。多模型系统的可靠性来自差异被看见、记录和测试,不是接口名字看起来一样。
