使用服务商中立的模型协议
理解请求、有序内容、能力协商、规范流事件、响应、用量与服务商扩展。
Model 边界
runifold-model 可以脱离 Agent 独立使用。对象安全的 Model 契约打开规范事件流,并可
把它收集为非流式调用同样使用的 ModelResponse。ModelCallContext 只携带调用身份、
可选的所属 Run、Deadline 与取消。
凭证、端点、HTTP Client、重试与路由属于适配器或中间件配置,因此调用协议保持可组合、 可测试。
无损内容
Message 保存有序 Content Part,而不是一段扁平字符串。规范 Variant 保存文本、媒体、 Reasoning、Tool Call、Tool Result、拒绝、引用与用量。未知服务商数据进入带命名空间的 扩展,而不是被静默丢弃。
可见回答与 Reasoning 始终分开。需要完整响应时应读取 ModelResponse;只拼接文本
Delta 会丢掉 Tool、成本、诊断与安全所需的证据。
能力协商
ModelCapabilities 把支持等级表达为原生、模拟、不支持或未知。请求策略可以要求严格
支持、允许模拟或接受 Best Effort;所有降级必须成为 Warning。
能力发现只代表一个 Provider/Model 组合,不能当作普遍承诺。结构化输出、Reasoning、 Tool Calling、Embedding、媒体与用量细节,都要在实际上线的 Route 上验证。
规范流式语义
合法 Stream 只启动一次,按索引打开并完成 Content Block,可以产生用量快照与 Provider Event,并且只完成一次。没有终止事件、带未关闭 Block 完成,或完成后继续产生事件, 都是协议错误。
重试或 Fallback 只能发生在第一条规范事件提交 Stream 之前。可见输出开始后切换 Route, 可能重复内容或混合两个服务商响应。
直接调用模型
需要请求/响应控制但不需要 Agent 循环时,直接使用模型层:模型代理、适配器 Benchmark、 批量转换、自定义编排或 Provider 语义测试。
模型需要反复选择 Tool 或子 Agent 时使用 Agent;应用代码拥有确定性跳转时使用 Workflow。 这些层可以组合,没有哪一层必须包装所有其他层。
调用底层 Model API
use runifold::{
Message, Model, ModelCallContext, ModelRef, ModelRequest,
};
use runifold_providers::openai::OpenAiClient;
let client = OpenAiClient::from_api_key(std::env::var("OPENAI_API_KEY")?)?;
let request = ModelRequest::new(
ModelRef::new("openai", "gpt-5"),
Message::user("Explain lease fencing in one paragraph"),
);
let response = client.invoke(request, ModelCallContext::new()).await?;
for part in response.content {
if let Some(text) = part.as_text() {
println!("{text}");
}
}构建 Adapter,或明确不需要 Agent Loop 时使用这一层。检查规范 Content、Finish Reason、
Usage、Warning 与 Provider Extension,不要在应用代码里解析 Provider 原始 JSON。生产
环境还应在 ModelCallContext 中加入 Cancellation 与 Deadline。