Configuration¶
The LlmClient constructor accepts configuration for authentication, timeouts, retries, and endpoint overrides. All options have sensible defaults.
Client Construction¶
import asyncio
from liter_llm import LlmClient
async def main() -> None:
client = LlmClient(
api_key="sk-...", # or set OPENAI_API_KEY env var
base_url=None, # override provider base URL
model_hint="openai", # pre-resolve provider at construction
max_retries=3, # retry on transient failures
timeout=60, # request timeout in seconds
)
response = await client.chat(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)
asyncio.run(main())
import { LlmClient } from "@kreuzberg/liter-llm";
const client = new LlmClient({
apiKey: "sk-...", // or set OPENAI_API_KEY env var
baseUrl: undefined, // override provider base URL
modelHint: "openai", // pre-resolve provider at construction
maxRetries: 3, // retry on transient failures
timeoutSecs: 60, // request timeout in seconds
});
const response = await client.chat({
model: "openai/gpt-4o",
messages: [{ role: "user", content: "Hello!" }],
});
console.log(response.choices[0].message.content);
package main
import (
"context"
"fmt"
"time"
llm "github.com/kreuzberg-dev/liter-llm/packages/go"
)
func main() {
client := llm.NewClient(
llm.WithAPIKey("sk-..."), // or set OPENAI_API_KEY env var
llm.WithBaseURL("https://api.openai.com/v1"), // override provider base URL
llm.WithTimeout(60*time.Second), // request timeout
)
resp, err := client.Chat(context.Background(), &llm.ChatCompletionRequest{
Model: "openai/gpt-4o",
Messages: []llm.Message{
llm.NewTextMessage(llm.RoleUser, "Hello!"),
},
})
if err != nil {
panic(err)
}
if len(resp.Choices) > 0 && resp.Choices[0].Message.Content != nil {
fmt.Println(*resp.Choices[0].Message.Content)
}
}
Configuration Options¶
| Option | Type | Default | Description |
|---|---|---|---|
api_key |
string | required | Provider API key. Wrapped in SecretString internally. Read from env vars yourself (e.g. os.environ["OPENAI_API_KEY"]). |
base_url |
string | from registry | Override the provider's base URL. |
model_hint |
string | none | Pre-resolve a provider at construction (e.g. "openai"). |
timeout |
duration | 60s | Request timeout. |
max_retries |
int | 3 | Number of retries on transient failures. |
API Key Management¶
The recommended approach is environment variables. Read the standard variable for your provider and pass it to the constructor:
| Provider | Environment variable |
|---|---|
| OpenAI | OPENAI_API_KEY |
| Anthropic | ANTHROPIC_API_KEY |
| Google (Gemini) | GEMINI_API_KEY |
| Groq | GROQ_API_KEY |
| Mistral | MISTRAL_API_KEY |
| Cohere | CO_API_KEY |
| AWS Bedrock | AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY |
Never hardcode API keys
API keys passed to the constructor are wrapped in secrecy::SecretString. They are never logged, serialized, or included in error messages. Always prefer environment variables over hardcoded strings.
If you pass api_key explicitly, it takes precedence over the environment variable.
Timeouts and Retries¶
Retries use exponential backoff with jitter. Only transient failures (HTTP 429, 500, 502, 503, 504) are retried.
# Long timeout for large generations
client = LlmClient(api_key="sk-...", timeout=300, max_retries=5)
Custom Base URLs¶
Override base_url to point at a local inference server, corporate proxy, or alternative endpoint:
# Ollama running locally (no API key needed for local providers)
client = LlmClient(api_key="unused", base_url="http://localhost:11434/v1")
# Corporate proxy
client = LlmClient(api_key="sk-...", base_url="https://llm-proxy.internal.company.com/v1")
The base_url replaces the provider's default URL from the registry. The model prefix still controls which provider's auth and parameter logic is used.
Extra Headers¶
In Rust, the ClientConfigBuilder supports adding custom headers:
use liter_llm::ClientConfigBuilder;
let config = ClientConfigBuilder::new("sk-...")
.header("X-Custom-Header", "value")?
.timeout(std::time::Duration::from_secs(120))
.max_retries(5)
.build();
Credential Providers¶
For dynamic credentials (e.g. rotating tokens, AWS IAM roles), pass a credential_provider that implements the CredentialProvider trait. This is called before each request to fetch the current credential:
use liter_llm::ClientConfigBuilder;
use std::sync::Arc;
let config = ClientConfigBuilder::new("placeholder")
.credential_provider(Arc::new(my_credential_provider))
.build();
Model Hints¶
The model_hint parameter pre-resolves a provider at construction time. This is useful when you know you will only use one provider and want to avoid the prefix lookup on each request: