添加提供方
衡量一个提供方(provider)集成,要看每一项 T3 功能在它上面是否如实工作,而不是只看回合(turn)能否跑完。本页列出新驱动(driver)需要做出的决定,以及需要拿出的证据。提供方约束和能力系统说明这些规则为何存在。
选择集成形态
- ACP 智能体从 ACP 注册表 条目开始。这些条目遵循 ACP 规范,没有按智能体单独处理的逻辑。只有当某个智能体需要规范未覆盖的行为时,才为它配备专用驱动;即便如此,它也只是共享 ACP 适配器上的一个小变体,例如 Grok 和 Antigravity。绝不要向通用注册表适配器(adapter)添加 agent-id 检查。
- 其他协议使用实现
ProviderAdapterV2的原生适配器,例如 Codex、Claude、Cursor、OpenCode、Pi 和 Muse。
提供方专有的行为留在适配器和驱动里。编排和客户端(client)读取的是能力,而不是驱动种类。
只报告提供方真正做的事
- **能力。**把
OrchestrationV2ProviderCapabilities中的每个标志都设成提供方(provider)真正具备的行为。关掉它所没有的分叉、回滚、转向或子智能体支持;编排随后会回退,例如分叉会改用可移植上下文交接。一项能力若保持开启、到运行时却失败,那就是缺陷。 - **权限模式。**只提供提供方会原生强制执行的模式,通过提供方展示中的
supportedRuntimeModes来给出(Grok 和 Pi 是例子)。不要在 T3 里代答批准,以此来仿造一个缺失的模式:T3 的检查弱于智能体自己的强制执行。已经存下、但这次没有提供的模式,服务器会按 Supervised 运行(RuntimePolicy.ts)。 - **批准与问题选项。**提供方自己的选项 ID 原样传递。每个请求都要有一种提供方会遵守的拒绝方式。
- **交互模式。**除非提供方的计划输出会变成 T3 的提议计划卡片,否则隐藏计划开关(
showInteractionModeToggle: false)。
进程、账户与安装边界
- **实例。**提供方会话(session)状态、目录和凭据属于提供方实例,而不属于驱动(driver)。去掉该实例并未配置的环境中既有凭据,这样两个实例就不会在无声无息中共用同一个账户或同一份账单。
- **状态检查。**后台的状态刷新和模型刷新,不得打开一个会启动 MCP 服务器、运行钩子或发起登录的提供方会话。更重的探测要留在显式刷新之后。
- **T3 MCP 工具。**注入该对话线程(thread)的 MCP 服务器,使智能体能够使用 T3 的工具;当这台服务器不可达时,回合(turn)也要能够继续。
- **更新。**只有能够证明自己拥有该二进制文件的安装程序,才可以用来执行更新;否则保持手动。参见
providerMaintenanceRunner.ts。
测试
用回放夹具证明适配器(adapter)行为:把一份提供方(provider)记录稿,经真实的编排器(orchestrator)、适配器和投影回放一遍。参见测试策略。
- 用
apps/server/scripts中的录制脚本(record-*-replay-fixture.ts)从真实提供方录制记录稿。新协议通常需要自己的录制器。 - 覆盖
testkit/fixtures下该提供方所支持的共享场景:simple、multi_turn、queued_turn、turn_interrupt、message_steering、provider_thread_resume,以及tool_call_*批准用例。共享场景覆盖不到的行为,再补充提供方自己的夹具。 - 单元测试用于纯逻辑,以及真实提供方无法按需产生的失败。用手工编写的帧去驱动适配器的测试,只是对协议的猜测;实机测试经常会发现这些猜测漏掉的地方。
- 针对真实二进制文件的门控实机测试可以有,但它不能代替回放,因为 CI 会跳过它。
多个提供方都踩过的陷阱
下面每一条都曾弄坏不止一个适配器。你的提供方(provider)能够产生的每一种情况,各备一个回放夹具,就能把它们抓住。
- **在提供方宣告这些设置之前就写入。**智能体常常在提供方会话(session)打开之后、在稍后的一次更新里,或者直到某个模型运行时,才列出配置选项(例如 effort 选项只存在于带 effort 的模型上)。在那之前,智能体可能接受这次写入,实际却什么也不改。要等该选项被宣告之后再写;实时会话没有提供的已存储选项,应当视为跳过,而不是失败。
- **“Default”是哨兵值,不是模型。**默认模型这一选择,必须在一个具名模型运行过之后把提供方会话切回去,恢复出来的会话也一样。绝不要把这个哨兵值发给提供方。
- **回合开始之前就发出了停止。**取消若在提供方登记该提示之前到达,可能被忽略,回合(turn)会一直跑到结束;也可能留下一个提供方从未保存的提供方会话。找到提供方自己的回合已开始信号,并测试刚刚发送就按下停止。
- **提供方自行启动的工作。**后台命令(command)、子智能体、工作流和目标,可能在 T3 的回合已经结算之后才结束,或才开始一个回合。通过
ProviderContinuationRequests提供续跑,让父级醒来,并报告hasPendingBackgroundWork,这样提供方会话就不会被当作空闲而释放。丢掉它,或者杀掉该会话,结果就会丢失。 - **子智能体比拉起它们的运行活得更久。**子级可能在父级回合结算之后才报告,也可能在后来的一次运行中恢复。按其所属子智能体路由这些更新,而不是按当前哪一次运行正在活跃。
- **失败或被停止的回合不留下未结束的事项。**结算该回合的工具调用、子智能体,以及仍待处理的批准和问题。每条终态路径都要有自己的回放:完成、停止、提供方失败,以及进程退出。
- **用量限制不是普通失败。**把配额错误和速率限制错误归类为
usage_limit,并在提供方给出重置时间时带上它,这样对话线程(thread)会显示 Limited,并且可以恢复。 - **路径与环境。**测试符号链接的工作区,例如 macOS 的
/tmp;比较规范路径的智能体,在那里每个回合都会失败。丢掉该实例并未配置的继承凭据。登录状态未知时,报告为未知,不要报告为已登录。
驱动接在哪里
提供方(provider)放在它自己的 packages/provider-<name> 包里,以 Pi 为参照。尚未迁出的驱动(driver)仍在 provider/Drivers 中。
- 包导出。
./settings存放实例设置模式,用 contracts 中的makeProviderSettingsSchema构建。./client导出一个ProviderClientDefinition(标签、设置模式、纯数据图标、徽章),并且必须对浏览器和 React Native 保持安全。./server导出ProviderDriver及其适配器驱动。./testing暴露服务器回放测试套件所驱动的内部实现;需要编排器(orchestrator)的测试套件留在服务器中。设置位于providerInstances;新提供方默认关闭。 - **包边界。**服务器代码只导入
@t3tools/provider-core/server/*、contracts 和 shared。它通过ProviderHost访问服务器(路径、设置、后台需求、附件、已存储的凭据),绝不通过apps/server。测试使用@t3tools/provider-testing。 - **服务器注册:**驱动在
builtInDrivers.ts中的条目。该驱动带有自己的适配器驱动。还要包括它在状态顺序中的位置、model-manifest.json中的兼容策略(递增updatedAt;参见模型清单),以及它在 contracts 中的默认模型。 - **客户端注册:**Web 与移动端提供方注册表中的客户端(client)定义,以及设置搜索词。客户端绘制包中的图标;不要为单个驱动再增加图标分支。
- **文档:**一篇符合产品口吻的
docs/user/providers-<name>.md指南、安装表中的一行,以及任何会改变权限模式页面的提供方差异。