API 客户端、内部代理和上游服务会独立升级。同一个团队可能同时运行桌面自动更新版、固定 CLI、CI 容器和内部兼容实现;一句“我们已经升级”无法说明哪些组合真的通过验证。只手动发送一条短请求,也覆盖不了子路径、工具调用、流式中断和错误转换。长期治理需要一张版本契约矩阵:记录每个可部署组合的不可变版本、协议行为、固定测试和最近结果,未验证组合不能默认进入生产。本文给出矩阵字段、用例结构和灰度更新流程。
版本矩阵记录实际构建
至少包含:
| 字段 | 说明 |
|---|---|
| 客户端类型 | 桌面、CLI、CI 或内部实现 |
| 客户端版本 | 完整版本与安装来源 |
| 客户端摘要 | 二进制哈希或镜像摘要 |
| 代理版本 | 提交标识或不可变镜像摘要 |
| 协议模式 | 当前实际使用的端点与功能路径 |
| 测试身份 | 不含密钥的凭据标识 |
| 测试模型或资源 | 请求和实际映射标识 |
| 契约集版本 | 固定用例集合版本 |
| 最近验证 | 时间、结果和负责人 |
| 允许环境 | 开发、测试或生产 |
不要写 latest,也不要只记录可移动标签。无法还原构建就无法复现兼容问题。
先定义不可变的契约用例
契约测试至少覆盖:
基础非流式请求
流式响应正常结束
流式连接中断后的客户端行为
结构化输出解析
单个与多个工具调用
长会话整理后的继续执行
认证失败和权限不足
不存在的端点或资源
限流和服务端错误的保真
重试是否遵守幂等边界
每个用例定义输入、前置条件和可观察断言,不依赖模型文字完全一致。
一个可复用的用例结构
case_id: long-session-continue-01
contract_version: "v3"
preconditions:
client_version: "<actual-version>"
proxy_version: "<commit-or-digest>"
test_identity: "<non-secret-id>"
steps:
- "建立包含固定目标与三条约束的测试会话"
- "触发客户端当前版本的上下文整理行为"
- "发送下一次普通请求"
assertions:
- "下一次请求命中声明的端点"
- "目标与三条约束仍可由响应确认"
- "已完成的工具动作不被重复执行"
- "请求资源与实际资源映射可观察"
- "代理状态与上游原始状态均被记录"
占位符由测试运行器注入。用例文件不保存真实 Key、用户会话或生产正文。
错误契约检查语义而非固定文本
客户端看到的错误可能经过代理转换。测试应同时断言:
upstream_status
upstream_error_category
proxy_status
proxy_error_category
client_visible_category
retry_count
actual_route
例如认证失败不应被重试成服务不可用;权限不足不应被包装成不存在而失去调查线索。具体状态映射要依据接口合同,不使用一张通用表强加给所有服务。
长会话测试验证状态而非“还能回答”
长会话整理后,需要检查:
- 原始任务目标是否保留;
- 禁止动作和目录边界是否仍有效;
- 已完成步骤是否被重复;
- 工具结果是否保持正确角色和顺序;
- 未完成的验收标准是否仍可见;
- 下一请求实际使用的端点和资源是否符合矩阵声明。
测试材料使用无敏感信息的固定场景。不要用真实用户长会话触发兼容测试。
对资源回退做显式契约
如果代理允许回退,测试必须同时记录 requested_resource 和 effective_resource,并断言调用方能够观察变化。不同动作分开定义:
同资源切换健康上游
切换到已验收的等价部署
切换到不同资源或能力
停止并向调用方返回失败
切换到不同资源不能藏在请求规范化中。它需要独立策略、审批和结果验收。
更新矩阵的灰度流程
每次客户端或代理升级:
- 创建新的矩阵行,不覆盖旧结果;
- 在隔离测试身份下运行完整契约集;
- 对失败用例保存入站、规范化和上游结构摘要;
- 通过后只开放给明确的测试人群或项目;
- 观察契约外的实际错误类别和人工反馈;
- 达到退出条件后扩大范围;
- 保留旧组合直到回滚演练通过。
灰度必须写明范围、负责人、观察指标、停止条件和恢复版本。仅让少量用户“先试试”不构成可审计灰度。
用凭据和环境隔离测试
开发、契约测试和生产使用不同凭据。测试身份只开放用例需要的资源和权限,并设置可控的调用范围。矩阵保存凭据标识,不保存秘密值。
同一测试必须固定身份和路由。动态账号池会让结果同时混入权限差异,破坏版本对比。
客户端与代理分别记录元数据
客户端适合记录版本、会话散列、功能触发状态和本地错误类别;代理适合记录请求标识、路由、请求资源、实际资源、上游状态和重试。两侧通过非敏感关联标识连接。
默认不记录完整提示词、工具结果、文件正文、Cookie 和认证信息。记录更多内容前先说明用途、访问范围和删除责任。
复盘保留证据等级
故障报告将信息分为:
已确认事实:由请求、日志或契约测试直接证明
外部线索:来自 issue、文档或其他环境的观察
工程假设:等待单变量实验验证
最终结论:能够由本环境复现和反向验证
升级后恢复只说明版本变化与结果相关,不自动证明某个 Header 或字段是唯一根因。
定期清理未验证组合
当客户端停止支持、代理版本过期或测试身份失效时,矩阵行标为退役并从允许环境中移除。保留历史结果用于事故追踪,但不能让旧“曾经通过”继续代表当前上游行为。
模型、工具 Schema、认证方式或上游接口发生变化时,找到受影响契约并重新运行,而不是等待用户报告错误。
结论与限制
协议兼容性不是一个版本号,而是客户端、代理、上游资源和测试合同的组合。维护不可变版本矩阵,用固定契约覆盖基础请求、长会话、工具调用和错误保真,再通过隔离身份灰度更新,才能知道哪些组合真正可部署。
本文提供通用治理结构,不规定任何客户端的具体压缩方式、端点或错误码映射。实际契约必须依据所用版本的官方接口和本地实现编写,并在生产数据之外执行。