Overview
The OpenAI provider connects to GPT models including GPT-4, GPT-4o, o1, and GPT-3.5. It also serves as the base for OpenAI-compatible providers.
Source: crates/goose/src/providers/openai.rs
Configuration
Environment Variables
OPENAI_HOST
string
default:"https://api.openai.com"
API endpoint URL
OPENAI_BASE_PATH
string
default:"v1/chat/completions"
API path for chat completions
OpenAI organization ID (optional)
OpenAI project ID (optional)
Request timeout in seconds
Custom headers in format: Header1=Value1,Header2=Value2 (stored securely)
Setup
# Configure using the CLI
goose configure
# Or set environment variables
export OPENAI_API_KEY="sk-..."
export OPENAI_HOST="https://api.openai.com"
export OPENAI_ORGANIZATION="org-..."
export OPENAI_PROJECT="proj_..."
Supported Models
GPT-4 Series
gpt-4o (default) - GPT-4 Optimized (128K context)
gpt-4o-mini (fast model) - Smaller, faster GPT-4o (128K context)
gpt-4.1 - Latest GPT-4 (128K context)
gpt-4.1-mini - Smaller GPT-4.1 (128K context)
gpt-4-turbo - GPT-4 Turbo (128K context)
Reasoning Models
o1 - Advanced reasoning model (200K context)
o3 - Next-generation reasoning (200K context)
o4-mini - Compact reasoning model (128K context)
GPT-5 Series (Future)
gpt-5-nano - Ultra-efficient model (400K context)
gpt-5.1-codex - Code-specialized model (400K context)
gpt-5-codex - Code generation model (400K context)
Legacy
gpt-3.5-turbo - GPT-3.5 Turbo (16K context)
Documentation: https://platform.openai.com/docs/models
Usage
Basic Usage
use goose::providers::create;
use goose::model::ModelConfig;
use goose::conversation::message::Message;
// Create with default model (gpt-4o)
let model_config = ModelConfig::new("gpt-4o")?;
let provider = create("openai", model_config, vec![]).await?;
// Stream a response
let messages = vec![Message::user().with_text("Hello, GPT-4!")];
let stream = provider.stream(
&provider.get_model_config(),
"session-123",
"You are a helpful assistant.",
&messages,
&[],
).await?;
Custom Configuration
let model_config = ModelConfig::new("gpt-4-turbo")?
.with_temperature(0.7)
.with_max_tokens(2048)
.with_top_p(0.95);
let provider = create("openai", model_config, vec![]).await?;
Using Fast Models
// Automatically tries gpt-4o-mini, falls back to main model on failure
let (response, usage) = provider.complete_fast(
"session-123",
"You are a helpful assistant.",
&messages,
&[],
).await?;
Advanced Features
Embeddings
The OpenAI provider supports text embeddings:
if provider.supports_embeddings() {
let texts = vec![
"Hello world".to_string(),
"How are you?".to_string(),
];
let embeddings = provider.create_embeddings(
"session-123",
texts,
).await?;
// embeddings is Vec<Vec<f32>>
println!("Embedding dimension: {}", embeddings[0].len());
}
Default embedding model: text-embedding-3-small (configure via GOOSE_EMBEDDING_MODEL)
For team accounts:
export OPENAI_ORGANIZATION="org-abc123"
export OPENAI_PROJECT="proj_xyz789"
These are sent as headers:
OpenAI-Organization: org-abc123
OpenAI-Project: proj_xyz789
For proxies or special configurations:
export OPENAI_CUSTOM_HEADERS="X-Custom-Header=value1,X-Another=value2"
Responses API (GPT-5 Codex)
The provider automatically uses the Responses API for codex models:
let model_config = ModelConfig::new("gpt-5-codex")?;
let provider = create("openai", model_config, vec![]).await?;
// Automatically uses /v1/responses endpoint instead of /v1/chat/completions
You can force the responses API with a custom base path:
export OPENAI_BASE_PATH="v1/responses"
OpenAI-Compatible Providers
Many providers offer OpenAI-compatible APIs. Configure by changing the host:
Example: Local LLM Server
export OPENAI_API_KEY="not-needed"
export OPENAI_HOST="http://localhost:8000"
export OPENAI_BASE_PATH="v1/chat/completions"
Example: Azure OpenAI
Use the dedicated Azure provider, or configure manually:
export OPENAI_API_KEY="your-azure-key"
export OPENAI_HOST="https://your-resource.openai.azure.com"
export OPENAI_BASE_PATH="openai/deployments/your-deployment/chat/completions?api-version=2024-02-15-preview"
Implementation Details
impl ProviderDef for OpenAiProvider {
fn metadata() -> ProviderMetadata {
ProviderMetadata::with_models(
"openai",
"OpenAI",
"GPT-4 and other OpenAI models, including OpenAI compatible ones",
"gpt-4o",
models,
"https://platform.openai.com/docs/models",
vec![
ConfigKey::new("OPENAI_API_KEY", false, true, None, true),
ConfigKey::new("OPENAI_HOST", true, false, Some("https://api.openai.com"), false),
ConfigKey::new("OPENAI_BASE_PATH", true, false, Some("v1/chat/completions"), false),
ConfigKey::new("OPENAI_ORGANIZATION", false, false, None, false),
ConfigKey::new("OPENAI_PROJECT", false, false, None, false),
ConfigKey::new("OPENAI_CUSTOM_HEADERS", false, true, None, false),
ConfigKey::new("OPENAI_TIMEOUT", false, false, Some("600"), false),
],
)
}
}
Chat Completions API:
{
"model": "gpt-4o",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hello!"
}
],
"temperature": 0.7,
"max_tokens": 2048,
"stream": true
}
Authentication
Uses Bearer token authentication:
let auth = AuthMethod::BearerToken(api_key);
Or no authentication for compatible providers:
let auth = AuthMethod::NoAuth;
Streaming
Supports Server-Sent Events (SSE) streaming:
data: {"choices":[{"delta":{"content":"Hello"}}]}
data: {"choices":[{"delta":{"content":" world"}}]}
data: [DONE]
Path Mapping
The provider intelligently maps base paths:
// Automatically maps chat/completions to responses for codex models
if model_name.contains("codex") {
// Uses /v1/responses instead of /v1/chat/completions
}
// Maps to models endpoint for model listing
let models_path = map_base_path(base_path, "models", "v1/models");
Error Handling
match provider.stream(...).await {
Ok(stream) => { /* handle stream */ },
Err(ProviderError::Authentication(msg)) => {
eprintln!("Invalid API key: {}", msg);
},
Err(ProviderError::RateLimited { retry_after }) => {
eprintln!("Rate limited");
},
Err(ProviderError::ContextLengthExceeded(msg)) => {
eprintln!("Context too long: {}", msg);
},
Err(e) => eprintln!("Error: {}", e),
}
Fetching Models
// Get all available models
let models = provider.fetch_supported_models().await?;
// Returns Vec<String> of model IDs
for model in models {
println!("Available model: {}", model);
}
Usage Tracking
let (message, usage) = provider.complete(...).await?;
println!("Model: {}", usage.model);
println!("Input tokens: {:?}", usage.usage.input_tokens);
println!("Output tokens: {:?}", usage.usage.output_tokens);
println!("Total tokens: {:?}", usage.usage.total_tokens);
Custom Provider Configuration
For advanced use cases, create a provider programmatically:
use goose::config::declarative_providers::DeclarativeProviderConfig;
use goose::providers::openai::OpenAiProvider;
let config = DeclarativeProviderConfig {
name: "my-provider".to_string(),
engine: ProviderEngine::OpenAI,
base_url: "http://localhost:8000".to_string(),
// ... other fields
};
let provider = OpenAiProvider::from_custom_config(model_config, config)?;
See Also