ReqLLM provides two API layers for AI interactions: high-level convenience functions and low-level Req plugin access.
# Simple text generation
ReqLLM.generate_text!("anthropic:claude-haiku-4-5", "Hello world")
#=> "Hello! How can I assist you today?"
# With full response metadata
{:ok, response} = ReqLLM.generate_text("openai:gpt-4", "Hello", temperature: 0.7)
response.usage
#=> %{
# input_tokens: 8,
# output_tokens: 12,
# total_tokens: 20,
# input_cost: 0.00024,
# output_cost: 0.00036,
# total_cost: 0.0006,
# cost: %{tokens: 0.0006, tools: 0.0, images: 0.0, total: 0.0006}
# }# New API returns StreamResponse struct
{:ok, response} = ReqLLM.stream_text("anthropic:claude-haiku-4-5", "Write a story")
response.stream
|> Stream.each(&IO.write(&1.text))
|> Stream.run()
# Note: stream_text! is deprecated, use stream_text/3 insteadschema = [name: [type: :string, required: true], age: [type: :pos_integer]]
person = ReqLLM.generate_object!("openai:gpt-4", "Generate a person", schema)
#=> %{name: "John Doe", age: 30}weather_tool = ReqLLM.tool(
name: "get_weather",
description: "Get current weather for a location",
parameter_schema: [location: [type: :string, required: true]],
callback: {WeatherAPI, :fetch_weather}
)
ReqLLM.generate_text("openai:gpt-4", "What's the weather in Paris?", tools: [weather_tool])context = ReqLLM.Context.new([
ReqLLM.Context.system("You are a helpful coding assistant"),
ReqLLM.Context.user("Explain recursion in Elixir")
])
{:ok, response} = ReqLLM.generate_text("anthropic:claude-haiku-4-5", context)# String format
ReqLLM.generate_text("anthropic:claude-haiku-4-5", "Hello")
# Tuple format with options
ReqLLM.generate_text({:anthropic, "claude-3-sonnet-20240229", temperature: 0.7}, "Hello")
# Model struct
model = %ReqLLM.Model{provider: :anthropic, model: "claude-3-sonnet-20240229", max_tokens: 100}
ReqLLM.generate_text(model, "Hello")# Keys auto-loaded from .env files via dotenvy at startup
# ANTHROPIC_API_KEY=sk-ant-...
# OPENAI_API_KEY=sk-...
# Optional: Store in application config
ReqLLM.put_key(:anthropic_api_key, "sk-ant-...")
ReqLLM.get_key(:openai_api_key)
# Per-request override
ReqLLM.generate_text("openai:gpt-4", "Hello", api_key: "sk-...")Direct Req plugin access for custom HTTP control:
# Canonical implementation from ReqLLM.Generation.generate_text/3
with {:ok, model} <- ReqLLM.Model.from("anthropic:claude-haiku-4-5"),
{:ok, provider_module} <- ReqLLM.provider(model.provider),
{:ok, request} <- provider_module.prepare_request(:chat, model, "Hello!", temperature: 0.7),
{:ok, %Req.Response{body: response}} <- Req.request(request) do
{:ok, response}
end
# Custom headers and middleware
{:ok, model} = ReqLLM.Model.from("anthropic:claude-haiku-4-5")
{:ok, provider_module} = ReqLLM.provider(model.provider)
{:ok, request} = provider_module.prepare_request(:chat, model, "Hello!")
custom_request =
request
|> Req.Request.put_header("x-request-id", "my-id")
|> Req.Request.put_header("x-source", "my-app")
{:ok, response} = Req.request(custom_request)IMPORTANT: Streaming uses Finch, not Req. The prepare_request/4 and attach/3 callbacks do NOT work for streaming operations.
For custom streaming, use the provider's attach_stream/4 callback or use ReqLLM.Streaming.start_stream/4:
# High-level streaming API (recommended)
{:ok, response} = ReqLLM.stream_text("anthropic:claude-haiku-4-5", "Hello")
response.stream |> Stream.each(&IO.write(&1.text)) |> Stream.run()
# Low-level streaming (for advanced use cases)
{:ok, model} = ReqLLM.Model.from("anthropic:claude-haiku-4-5")
{:ok, provider_module} = ReqLLM.provider(model.provider)
context = ReqLLM.Context.new("Hello!")
{:ok, stream_response} = ReqLLM.Streaming.start_stream(
provider_module,
model,
context,
timeout: 60_000
)
stream_response.stream
|> Stream.each(&IO.write(&1.text))
|> Stream.run()case ReqLLM.generate_text("anthropic:claude-haiku-4-5", "Hello") do
{:ok, response} -> response.text
{:error, %ReqLLM.Error.API.RateLimit{retry_after: seconds}} ->
:timer.sleep(seconds * 1000)
{:error, %ReqLLM.Error.API.Authentication{}} ->
{:error, :auth_failed}
{:error, error} ->
{:error, :unknown}
end:temperature- Randomness (0.0-2.0):max_tokens- Response length limit:tools- Function calling definitions:system_prompt- System message:provider_options- Provider-specific parameters:api_key- Override stored key