基于 Provider Runtime 契约构建
组合服务商身份、安全重试、熔断、能力证据、兼容端点与适配器验证。
Provider 的职责
Provider Adapter 有两项核心职责:实现具有无损规范 Stream 的 Model,以及实现带稳定
Provider Namespace 的 ProviderModel。它必须转换请求内容、响应生命周期、Tool Call、
Reasoning、用量、Warning、类型化错误、Deadline、取消与重试安全性。
它不应该重新实现 Agent 循环、Workflow 恢复、预算、Capability、Effect 或可观测性策略; 这些层保持服务商中立。
Runtime 组合
ProviderModelExt 提供带 Provider 身份的 Agent 构建、单 Route 弹性 Builder 与
ProviderRuntime。Runtime 在规范 Stream 外组合同 Route 重试与独立熔断器,同时仍然
实现 Model。
因此它可以被 OtelModel 观测、放进 ModelRouter、直接调用、交给 Agent,或在
AgentStep 中执行。
Adapter 自带的安全默认值
0.9 中,每个具体 Adapter 都通过 ProviderModel::runtime_profile 发布经过审查的
ProviderRuntimeProfile,普通 .runtime(model) 会自动应用。Delivery Mode、请求选项、
重试权限、熔断策略和 Capability 行为因此遵循真实协议,而不是门面层的统一猜测。
只有明确标记为可安全重试的错误才参与重试;未知、不安全、取消和已经 Commit 后的
Stream 失败不会重试。只有掌握部署证据时,才通过 runtime_with_profile 覆盖完整策略。
选择工作负载 Preset
use runifold::{BatchProfile, InteractiveProfile, ProviderModelExt};
use runifold_providers::openai::OpenAiClient;
let client = OpenAiClient::from_api_key(std::env::var("OPENAI_API_KEY")?)?;
let interactive = client
.clone()
.runtime_with_preset("gpt-5", InteractiveProfile)?;
let batch = client.runtime_with_preset("gpt-5", BatchProfile)?;
let audit = batch.capability_audit().await?;
for item in audit.review_required() {
println!("{}: {}", item.feature, item.recommendation);
}ProductionProfile 保持 Adapter 建议,InteractiveProfile 尽快 Commit 流事件,
BatchProfile 在 Router Commit 前验证完整响应。Capability Audit 是部署证据,
不会猜测未知模型已经支持某项能力。
兼容端点
协议兼容不等于能力等价。OpenAI-Compatible 端点可能接受相同 JSON,但在流式语义、 结构化输出、用量、Reasoning、错误 Body 或取消上存在差异。
使用经过验证的自定义 Endpoint 与稳定 Provider Identity;凭证留在服务端。部署配置应 记录精确 Model、Endpoint 家族、Feature Policy 与已经验证的行为。
适配器验收
只有确定性证据覆盖请求编码、分片 Stream、终止完成、Tool 参数、类型化错误、重试安全、 Timeout、取消、截断、凭证脱敏、并发隔离与 Runtime 兼容时,Provider 才适合生产。
runifold-provider-testkit 提供 Cassette、一致性与 Benchmark 边界。Live Test 补充协议
测试,不能替代故障注入和固定断言。
构造一次并共享 Runtime
use runifold::{ProductionProfile, ProviderModelExt};
use runifold_providers::openai::OpenAiClient;
let runtime = OpenAiClient::from_api_key(std::env::var("OPENAI_API_KEY")?)?
.runtime_with_preset("gpt-5", ProductionProfile)?;
let health = runtime.route_health();
println!("initial routes: {health:?}");
let agent = runtime
.agent("assistant")
.system("Answer precisely and expose uncertainty.")
.build()?;
let answer = agent.prompt_text("Why use a shared runtime?").await?;在 Service 启动时创建一次 ProviderRuntime,然后 Clone 给 Handler。Clone 共享 Retry
与 Circuit Breaker 状态;每个 Request 都调用 .runtime(...) 会创建独立 Health State,
破坏协同熔断。优先使用 Adapter 默认策略加标准 Preset;只有在明确评审过的覆盖边界
才使用 .runtime_with_profile(...)。