# Configuration Reference
All OpenResponses configuration lives under the `:open_responses` application key.
## Provider routing
Controls which adapter is used for each model name pattern.
```elixir
config :open_responses, :routing, %{
~r/^gpt-/ => OpenResponses.Adapters.OpenAI,
~r/^claude-/ => OpenResponses.Adapters.Anthropic,
~r/^gemini-/ => OpenResponses.Adapters.Gemini,
~r/^llama|^mistral|^phi|^qwen/ => OpenResponses.Adapters.Ollama,
"default" => OpenResponses.Adapters.Mock
}
```
Keys may be a `Regex` (matched with `Regex.match?/2`) or the string `"default"`. Patterns are evaluated in insertion order; the first match wins. The `"default"` key matches any model that no pattern matched.
---
## Provider credentials
```elixir
config :open_responses, :provider_config, %{
openai: [
api_key: System.fetch_env!("OPENAI_API_KEY"),
base_url: "https://api.openai.com/v1" # optional override
],
anthropic: [
api_key: System.fetch_env!("ANTHROPIC_API_KEY"),
base_url: "https://api.anthropic.com/v1" # optional override
],
gemini: [
api_key: System.fetch_env!("GEMINI_API_KEY"),
base_url: "https://generativelanguage.googleapis.com/v1beta" # optional
]
}
```
Put this in `config/runtime.exs` so secrets are read at runtime, not compile time.
---
## Hosted tools
Maps tool names to modules that implement `OpenResponses.Tool`.
```elixir
config :open_responses, :hosted_tools, %{
"get_time" => MyApp.Tools.TimeZone,
"search_docs" => MyApp.Tools.DocSearch
}
```
Default: `%{}` (no hosted tools — all function calls are external).
---
## Middleware
List of modules implementing `OpenResponses.Middleware`, applied in order.
```elixir
config :open_responses, :middlewares, [
MyApp.Middleware.AuditLog,
MyApp.Middleware.TokenBudget
]
```
Default: `[]` (no middleware).
---
## MCP servers
Pre-configured MCP server connections available to all requests.
```elixir
config :open_responses, :mcp_servers, [
%{
name: "docs",
url: "https://docs-mcp.example.com",
headers: [{"authorization", "Bearer #{System.get_env("MCP_TOKEN")}"}]
}
]
```
Default: `[]` (no pre-configured MCP servers).
---
## Ash domains
Required for Ash framework integration. The installer sets this automatically.
```elixir
config :open_responses, :ash_domains, [OpenResponses.Responses]
```
---
## Ash async
Controls Ash's internal async behaviour. Set to `false` in development to simplify debugging.
```elixir
config :ash, :disable_async?, false
```
---
## Cachex
The response cache is a standard Cachex instance named `:response_cache`. Configure it in your supervision tree:
```elixir
# Limit to 10,000 entries, default TTL 24h
{Cachex, name: :response_cache, limit: 10_000}
```
See the [Cachex documentation](https://hexdocs.pm/cachex) for full options.
---
## PromEx
```elixir
config :open_responses, OpenResponses.PromEx,
manual_metrics_start: :no_async,
drop_metrics_groups: [],
grafana: :disabled,
metrics_server: :disabled
```
See the [PromEx documentation](https://hexdocs.pm/prom_ex) for full options including Grafana dashboard upload.
---
## Request timeouts
The default timeout for non-streaming requests waiting for loop completion is 30 seconds. For long-running agentic loops, use streaming mode (`"stream": true`).
To change the non-streaming timeout, override the controller in your application and adjust the `receive ... after` block.
---
## Full example
A complete `config/runtime.exs` for production:
```elixir
import Config
config :open_responses, :provider_config, %{
openai: [api_key: System.fetch_env!("OPENAI_API_KEY")],
anthropic: [api_key: System.fetch_env!("ANTHROPIC_API_KEY")],
gemini: [api_key: System.fetch_env!("GEMINI_API_KEY")]
}
config :open_responses, :routing, %{
~r/^gpt-/ => OpenResponses.Adapters.OpenAI,
~r/^claude-/ => OpenResponses.Adapters.Anthropic,
~r/^gemini-/ => OpenResponses.Adapters.Gemini,
"default" => OpenResponses.Adapters.OpenAI
}
config :open_responses, :hosted_tools, %{
"search_docs" => MyApp.Tools.DocSearch
}
config :open_responses, :middlewares, [
MyApp.Middleware.AuditLog,
MyApp.Middleware.RateLimit
]
```