OpenAI
The OpenAI provider (rig::providers::openai) covers OpenAI’s completion, embedding, transcription, image and speech models. Its client, OpenAI, is also the client for every OpenAI-compatible vendor Rig supports (DeepSeek, Groq, OpenRouter, Together, …), each configured from its own module.
Capabilities
Section titled “Capabilities”| Capability | Support | How |
|---|---|---|
| Completion | Yes | client.completion(id) (Responses API), client.chat(id) (Chat Completions) |
| Streaming | Yes | agent.prompt(p).stream(), or model.stream(request) |
| Tools | Yes | Any Rig tool |
| Structured output | Yes | Native JSON-schema output, used by extractors and output_schema |
| Image input | Yes | Vision-capable models |
| Reasoning | Yes | GenerationOptions::reasoning; summaries through OpenAiOptions |
| Embeddings | Yes | client.embedding(id, None) |
| Transcription | Yes | client.transcription(openai::WHISPER_1) |
| Image generation | image feature | client.image_generation(openai::GPT_IMAGE_1) |
| Speech | audio feature | client.audio_generation(openai::TTS_1) |
| Websocket sessions | websocket feature | model.responses_websocket().connect() |
Basic usage
Section titled “Basic usage”use rig::prelude::*;use rig::providers::openai::{self, OpenAI};
// Reads OPENAI_API_KEY (and OPENAI_BASE_URL, if set).let client = OpenAI::from_env()?;
let agent = AgentBuilder::new(client.completion(openai::GPT_5_5)) .preamble("You are a helpful assistant.") .build();
let answer = agent.prompt("Hello!").await?.output();println!("{answer}");Configuring the client
Section titled “Configuring the client”use rig::providers::openai::{OpenAI, OpenAIConfig};
// From OPENAI_API_KEY and the optional OPENAI_BASE_URL.let client = OpenAI::from_env()?;
// From an explicit key.let client = OpenAI::new("your-api-key");
// From a configuration, for anything beyond the key.let client = OpenAIConfig::new("your-api-key") .with_base_url("https://your-gateway.example.com/v1") .client();OpenAIConfig is plain, serializable data (the key is never serialized), so you can store it with the rest of your settings and turn it into a client with .client(), or .connect(http) for your own HTTP client. For another OpenAI-shaped vendor, use its module: deepseek::from_env()?, openrouter::from_env()?, and so on. See Model Providers for the list.
Responses vs Chat Completions
Section titled “Responses vs Chat Completions”OpenAI serves two completion APIs, and Rig has a model for each:
client.completion(id)builds the provider’s primary endpoint. For OpenAI that is the Responses API (POST /responses).client.responses(id)always builds the Responses model.client.chat(id)always builds the Chat Completions model (POST /chat/completions).
use rig::providers::openai::{self, OpenAI};
let client = OpenAI::from_env()?;
let responses = client.completion(openai::GPT_5_5); // Responses APIlet chat = client.chat(openai::GPT_5_5); // Chat CompletionsBoth work with agents, extractors, tools and streaming. Use Chat Completions when a gateway or proxy only speaks that API, or when you need a Chat-only field such as logit_bias or prediction. To make completion pick Chat Completions for a whole configuration, set the route once:
use rig::providers::openai::{self, OpenAIConfig, Route};
let model = OpenAIConfig::from_env()? .with_route(Route::Chat) .client() .completion(openai::GPT_5_5);On the Responses API, Rig sends the agent’s preamble as top-level instructions. For a compatible backend that ignores or rejects that field, OpenAIConfig::with_system_instructions_as_messages() sends it as system messages in the input instead.
Models
Section titled “Models”The module exports constants for OpenAI’s models, such as openai::GPT_5_6, openai::GPT_5_5, openai::GPT_5_4_MINI, openai::GPT_5_MINI and openai::O4_MINI. Any id string works too:
use rig::providers::openai::OpenAI;
let model = OpenAI::from_env()?.completion("gpt-5-mini");client.list_models().await? returns the models your key can use, and client.verify().await? checks the key without spending tokens.
Generation options
Section titled “Generation options”Reasoning effort, prompt-cache retention, service tier and verbosity are typed, provider-neutral options. Set them on the agent builder, on a single CompletionRequest, or build a reusable GenerationOptions and pass it to .options(..):
use rig::completion::{CacheRetention, Effort, ServiceTier, Verbosity};use rig::prelude::*;use rig::providers::openai::{self, OpenAI};
let agent = AgentBuilder::new(OpenAI::from_env()?.completion(openai::GPT_5_5)) .reasoning(Effort::High) // reasoning.effort / reasoning_effort .cache(CacheRetention::Long) // extended prompt-cache retention .service_tier(ServiceTier::Flex) // service_tier .verbosity(Verbosity::Low) // text.verbosity / verbosity .build();Each option is checked against the model before the request is sent. OpenAI caches prompts automatically; CacheRetention chooses how long the cache is kept on models that offer a choice. An option the model can’t take (say an effort level it doesn’t offer) fails with ProviderError::UnsupportedOption rather than being dropped silently. Call .on_unsupported(OnUnsupported::Ignore) to skip such options with a warning instead.
OpenAI-only options
Section titled “OpenAI-only options”Fields only OpenAI has are typed in openai::extension. OpenAiOptions has three sections: shared fields both APIs take (store, metadata, prompt_cache_key, safety_identifier), Responses-only fields (reasoning_summary, include, conversation, truncation, background, max_tool_calls, …), and Chat-only fields in ChatOptions (logit_bias, prediction, logprobs, penalties, audio output, web search options). Each section is sent only on its own API.
use rig::prelude::*;use rig::providers::openai::extension::{ChatOptions, OpenAiOptions, ReasoningSummary};use rig::providers::openai::{self, OpenAI};
let options = OpenAiOptions::new() .store(false) .prompt_cache_key("support-bot") .reasoning_summary(ReasoningSummary::Auto) .chat(ChatOptions::new().logprobs(true));
let agent = AgentBuilder::new(OpenAI::from_env()?.completion(openai::GPT_5_5)) .provider_option(options) .build();Reading OpenAI-only reply fields
Section titled “Reading OpenAI-only reply fields”The same extension types the reply fields only OpenAI returns, such as service_tier, the reasoning settings the model used, system_fingerprint, and token details. Read them with extras::<OpenAiExt>() on a CompletionResponse; it returns None for a reply from another provider.
use rig::completion::CompletionRequest;use rig::providers::openai::extension::OpenAiExt;use rig::providers::openai::{self, OpenAI};
let model = OpenAI::from_env()?.completion(openai::GPT_5_5);let response = model.call(CompletionRequest::new("Name a prime number.")).await?;
println!("{}", response.text());if let Some(Ok(extras)) = response.extras::<OpenAiExt>() { println!("served on tier {:?}", extras.service_tier);}Inside an agent, an on_outcome hook sees the same CompletionResponse for every model call. The full reply is always available as response.raw.
Embedding models
Section titled “Embedding models”| Constant | Dimensions | Notes |
|---|---|---|
TEXT_EMBEDDING_3_LARGE | 3072 | |
TEXT_EMBEDDING_3_SMALL | 1536 | |
TEXT_EMBEDDING_ADA_002 | 1536 | legacy |
use rig::providers::openai::{self, OpenAI};
let client = OpenAI::from_env()?;
// The model's default width...let embedder = client.embedding(openai::TEXT_EMBEDDING_3_SMALL, None);// ...or a shorter vector, for models that support `dimensions`.let small = client.embedding(openai::TEXT_EMBEDDING_3_LARGE, Some(256));The width matters when you create a vector store collection or index: it must match the model you embed with. See Embeddings and Vector Stores.
Websocket sessions
Section titled “Websocket sessions”OpenAI’s Responses API also runs over a websocket: one connection serves many turns, and each turn continues from the previous response. With the websocket feature, a Responses model opens a session:
[dependencies]rig = { version = "0.44.0", features = ["websocket"] }use rig::completion::CompletionRequest;use rig::providers::openai::{self, OpenAI};
let model = OpenAI::from_env()?.responses(openai::GPT_5_5);let mut session = model.responses_websocket().connect().await?;
let first = session.completion(CompletionRequest::new("What is ownership in Rust?")).await?;println!("{}", first.text());
// The session sends the previous response id for you.let second = session.completion(CompletionRequest::new("And borrowing?")).await?;println!("{}", second.text());
session.close().await?;A session runs one turn at a time. session.warmup(request) prepares request state without generating output, send plus next_event gives you the raw event stream, and clear_previous_response_id starts a fresh chain. The builder sets a 30-second connect timeout by default (connect_timeout, event_timeout). Without the websocket feature, open a session with connect_with(&backend) and your own WebSocketClientExt implementation.
OpenAI models call any tool you register on an agent. Rig converts tool definitions to OpenAI’s function format and parses tool calls back into its own types, on both APIs. See Tools.
See also
Section titled “See also”- Model Providers: every provider and the shared patterns
- Completions and Agents
- Media generation: images, speech and transcription
- Embeddings
