pub trait Provider: Send + Sync {
// Required methods
fn api_schema(&self) -> &str;
fn complete<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 ConversationRequest,
) -> Pin<Box<dyn Future<Output = Result<Completion, ProviderError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
// Provided method
fn stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
request: &'life1 ConversationRequest,
on_delta: &'life2 mut (dyn FnMut(CompletionDelta) + Send),
) -> Pin<Box<dyn Future<Output = Result<Completion, ProviderError>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
}Expand description
A model-sampling wire: builds a request, calls the model, normalizes the response.
One impl per wire schema — not per gateway. A Provider identifies a
request/response protocol shape (Anthropic Messages, OpenAI Chat, OpenAI
Responses, or the mock double); a gateway/endpoint (OpenRouter, Bedrock, a
proxy, a local model) is configuration (base_url + auth + headers) pointed at
one of these schemas, never a separate impl. This is Grok Build’s split
(ApiBackend schema vs an un-enumerated base_url/auth) and what ADR-0007’s
per-model { base_url, api_backend, extra_headers } record encodes.
Required Methods§
Sourcefn api_schema(&self) -> &str
fn api_schema(&self) -> &str
The wire-schema id this provider speaks — e.g. "anthropic", "mock".
This is the protocol shape, not a gateway. Stamped into the report’s
provider field.
Sourcefn complete<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 ConversationRequest,
) -> Pin<Box<dyn Future<Output = Result<Completion, ProviderError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn complete<'life0, 'life1, 'async_trait>(
&'life0 self,
request: &'life1 ConversationRequest,
) -> Pin<Box<dyn Future<Output = Result<Completion, ProviderError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Sample one completion for request.
§Errors
Returns ProviderError; use ProviderError::retryable to classify
retry-vs-terminal. The transport-tier backoff lives in the wire; the
bounded loop-level resample lives in the engine.
Provided Methods§
Sourcefn stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
request: &'life1 ConversationRequest,
on_delta: &'life2 mut (dyn FnMut(CompletionDelta) + Send),
) -> Pin<Box<dyn Future<Output = Result<Completion, ProviderError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn stream<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
request: &'life1 ConversationRequest,
on_delta: &'life2 mut (dyn FnMut(CompletionDelta) + Send),
) -> Pin<Box<dyn Future<Output = Result<Completion, ProviderError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Sample one completion, emitting CompletionDeltas to on_delta as they
arrive, and returning the same final Completion as Self::complete
(ADR-0021). Deltas are a display-only side channel; the returned
Completion is what the engine appends and dispatches from.
Default (this impl): non-streaming wires call Self::complete and emit one
synthetic text delta, so the seam works for every provider (mock, and any
wire that hasn’t implemented SSE). SSE wires override this to stream live.
§Errors
Returns ProviderError, same taxonomy as Self::complete.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".