Quickstart
Set a key
export OPENAI_API_KEY="sk-..."
Make a request
use rai_sdk::{ClientBuilder, Model};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ClientBuilder::new()
.from_env()
.model(Model::gpt4o_mini())
.build()?;
let response = client
.request()
.prompt("Explain Rust ownership in two sentences.")
.generate()
.await?;
println!("{}", response.text());
Ok(())
}
What each step does
ClientBuilder::new().from_env() reads credentials and settings from the environment. Anything you set explicitly on the builder afterwards takes precedence.
.model(Model::gpt4o_mini()) sets the default model. This also changes the builder’s type: only after a model is present does build() produce a client whose request() starts in a model-ready state. That is why the next step does not need to repeat the model.
.build()? constructs the HTTP client and validates configuration. It fails if the selected provider has no usable credentials.
.request().prompt(...) starts a request. prompt() accepts a &str, a String, a Message, or a full Prompt.
.generate().await? sends the request and, if tools are registered, runs the tool loop until the model produces a final answer. Use generate_once() for exactly one provider call with no tool execution.
response.text() concatenates the text content of the response.
Overriding the model per request
The client’s model is a default, not a constraint. Override it on a single request:
use rai_sdk::{ClientBuilder, Model};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ClientBuilder::new()
.from_env()
.model(Model::gpt4o_mini())
.build()?;
// Uses Anthropic for this one request; the client default is unchanged.
let response = client
.request()
.model(Model::claude_sonnet_46())
.prompt("Summarize the Rust borrow checker.")
.generate()
.await?;
println!("{}", response.text());
Ok(())
}
This requires credentials for whichever provider you name, so the example above needs ANTHROPIC_API_KEY in addition to OPENAI_API_KEY.
Tuning generation
Pass a GenerationConfig to control sampling and limits:
use rai_sdk::{ClientBuilder, GenerationConfig, Model};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = ClientBuilder::new()
.from_env()
.model(Model::gpt4o_mini())
.build()?;
let response = client
.request()
.config(
GenerationConfig::new()
.with_temperature(0.2)
.with_max_tokens(512),
)
.prompt("List three Rust testing tips.")
.generate()
.await?;
println!("{}", response.text());
Ok(())
}
Note that temperature and top_p are ignored for OpenAI reasoning (o-series) models, which do not accept them.
Next steps
- Configuration — every environment variable and its builder equivalent.
- Structured output — get a typed value instead of text.
- Tool calling — let the model call your code.
- Streaming — render tokens as they arrive.