xAI (Grok) Provider Guide
View SourcexAI's Grok models provide powerful reasoning capabilities with real-time web search through Live Search integration.
Configuration
Set your xAI API key:
# Add to .env file (automatically loaded)
XAI_API_KEY=xai-...
Or use in-memory storage:
ReqLLM.put_key(:xai_api_key, "xai-...")Supported Models
xAI Grok models:
- grok-4- Latest and most capable
- grok-3-mini,- grok-3-mini-fast- Efficient with reasoning support
- grok-2-1212,- grok-2-vision-1212- Previous generation with vision
- grok-beta- Beta features
See the full list with mix req_llm.model_sync xai.
Basic Usage
# Simple text generation
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-4",
  "Explain quantum computing"
)
# Streaming
{:ok, stream_response} = ReqLLM.stream_text(
  "xai:grok-4",
  "Write a story"
)
ReqLLM.StreamResponse.tokens(stream_response)
|> Stream.each(&IO.write/1)
|> Stream.run()Provider-Specific Options
Max Completion Tokens
Preferred over max_tokens for Grok-4 models:
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-4",
  "Long explanation",
  provider_options: [max_completion_tokens: 2000]
)Note: ReqLLM automatically translates max_tokens to max_completion_tokens for models that require it.
Live Search
Enable real-time web search capabilities:
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-4",
  "What are today's top tech headlines?",
  provider_options: [
    search_parameters: %{
      mode: "auto",              # auto, always, or never
      max_sources: 5,            # Maximum sources to cite
      date_range: "recent",      # recent, week, month, year
      citations: true            # Include citations in response
    }
  ]
)Search modes:
- "auto"- Search when beneficial (default)
- "always"- Always search
- "never"- Disable search
Note: Live Search incurs additional costs per source retrieved.
Reasoning Effort
Control reasoning level (grok-3-mini models only):
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-3-mini",
  "Complex problem",
  provider_options: [reasoning_effort: "high"]
)Levels: "low", "medium", "high"
Note: Only supported for grok-3-mini and grok-3-mini-fast models.
Parallel Tool Calls
Control whether multiple tools can be called simultaneously:
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-4",
  "Check weather in multiple cities",
  tools: [weather_tool],
  provider_options: [parallel_tool_calls: true]  # Default
)Structured Output Mode
xAI supports two modes for structured outputs:
schema = [
  name: [type: :string, required: true],
  age: [type: :integer, required: true]
]
# Auto mode (recommended) - automatic selection
{:ok, response} = ReqLLM.generate_object(
  "xai:grok-4",
  "Generate a person",
  schema,
  provider_options: [xai_structured_output_mode: :auto]
)
# JSON schema mode - uses native response_format (models >= grok-2-1212)
{:ok, response} = ReqLLM.generate_object(
  "xai:grok-4",
  "Generate a person",
  schema,
  provider_options: [xai_structured_output_mode: :json_schema]
)
# Tool strict mode - uses strict tool calling (fallback for older models)
{:ok, response} = ReqLLM.generate_object(
  "xai:grok-2",
  "Generate a person",
  schema,
  provider_options: [xai_structured_output_mode: :tool_strict]
)Modes:
- :auto- Automatic selection based on model (default)
- :json_schema- Native structured outputs (requires grok-2-1212+)
- :tool_strict- Strict tool calling fallback
Stream Options
Configure streaming behavior:
{:ok, stream_response} = ReqLLM.stream_text(
  "xai:grok-4",
  "Story",
  provider_options: [
    stream_options: %{include_usage: true}
  ]
)Complete Example with Live Search
import ReqLLM.Context
context = Context.new([
  system("You are a helpful assistant with access to real-time web search"),
  user("Summarize today's news about AI developments")
])
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-4",
  context,
  temperature: 0.7,
  max_tokens: 1500,
  provider_options: [
    search_parameters: %{
      mode: "always",
      max_sources: 10,
      date_range: "recent",
      citations: true
    },
    parallel_tool_calls: true
  ]
)
text = ReqLLM.Response.text(response)
usage = response.usage
IO.puts(text)
IO.puts("Cost: $#{usage.total_cost}")Tool Calling
Grok supports function calling:
tools = [
  ReqLLM.tool(
    name: "get_weather",
    description: "Get weather for a location",
    parameter_schema: [
      location: [type: :string, required: true]
    ],
    callback: {WeatherAPI, :fetch}
  ),
  ReqLLM.tool(
    name: "get_stock_price",
    description: "Get stock price",
    parameter_schema: [
      symbol: [type: :string, required: true]
    ],
    callback: {StockAPI, :fetch}
  )
]
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-4",
  "What's the weather in NYC and the price of AAPL?",
  tools: tools,
  provider_options: [parallel_tool_calls: true]  # Can call both tools at once
)Structured Output
Grok models support native structured outputs (grok-2-1212 and newer):
schema = [
  title: [type: :string, required: true],
  summary: [type: :string, required: true],
  tags: [type: {:list, :string}],
  confidence: [type: :float]
]
{:ok, response} = ReqLLM.generate_object(
  "xai:grok-4",
  "Analyze this article and extract structured data",
  schema
)
data = ReqLLM.Response.object(response)Schema Constraints
xAI's native structured outputs have limitations:
Not Supported:
- minLength/- maxLengthfor strings
- minItems/- maxItems/- minContains/- maxContainsfor arrays
- patternconstraints
- allOf(must be expanded/flattened)
Supported:
- anyOf
- additionalProperties: false(enforced on root)
ReqLLM automatically sanitizes schemas to comply with these constraints.
Model-Specific Notes
Grok-4 Models
- Do NOT support stop,presence_penalty, orfrequency_penalty
- Use max_completion_tokensinstead ofmax_tokens
- Support native structured outputs
Grok-3-mini Models
- Support reasoning_effortparameter
- Efficient for cost-sensitive applications
- Good balance of speed and quality
Grok-2 Models (1212+)
- Support native structured outputs
- Support vision (grok-2-vision-1212)
- Previous generation capabilities
Vision Support
Grok vision models support image analysis:
import ReqLLM.Context
alias ReqLLM.Message.ContentPart
context = Context.new([
  user([
    ContentPart.text("Describe this image"),
    ContentPart.image_url("https://example.com/photo.jpg")
  ])
])
{:ok, response} = ReqLLM.generate_text(
  "xai:grok-2-vision-1212",
  context
)Error Handling
case ReqLLM.generate_text("xai:grok-4", "Hello") do
  {:ok, response} -> 
    handle_success(response)
    
  {:error, error} -> 
    IO.puts("Error: #{error.message}")
endCost Considerations
- Live Search: Each source retrieved adds cost
- Model Selection: grok-3-mini more cost-effective than grok-4
- Token Limits: Set appropriate max_completion_tokensto control costs