Contents

Configuring providers and models in EONYX

EONYX talks to any OpenAI-compatible API.
A provider is the way to reach a backend.
A model binds an id to a provider.
Here is how to connect one, hide the secrets and set price, window and retries.

There is one type so far: "openai".
It covers any OpenAI-compatible endpoint.
base_url is required.

"providers": {
  "openai":     { "type": "openai", "base_url": "https://api.openai.com/v1",     "api_key": "$OPENAI_API_KEY" },
  "openrouter": { "type": "openai", "base_url": "https://openrouter.ai/api/v1",  "api_key": "$OPENROUTER_API_KEY" },
  "deepseek":   { "type": "openai", "base_url": "https://api.deepseek.com",       "api_key": "$DEEPSEEK_API_KEY" },
  "moonshot":   { "type": "openai", "base_url": "https://api.moonshot.cn/v1",     "api_key": "$MOONSHOT_API_KEY" }
}
Secrets go through environment variables
api_key and base_url may reference variables such as $OPENAI_API_KEY.
They are expanded after the config layers merge.
So the key never lands in a committed file.
The same holds for report.database_url and MCP headers.

A model links an id, as the API understands it, to a provider:

"models": [
  { "id": "gpt-5",            "provider": "openai",     "context_window": 400000, "input_price": 1.25, "output_price": 10 },
  { "id": "deepseek-v4-pro",  "provider": "deepseek",   "context_window": 1000000, "input_price": 0.435, "output_price": 0.87 }
],
"default_model": "deepseek-v4-pro"
FieldPurpose
idthe model name at the provider
providera key from the providers block
context_windowwindow size in tokens — enables history auto-summarization
input_priceprice per 1M input tokens (USD) — for the cost counter
output_priceprice per 1M output tokens (USD)

Prices only feed the cost indicator in the TUI header.
They change no behaviour.
context_window matters more: without it there is no auto-summarization.

  • In the TUI, press Ctrl+N or type /model. The configured models are listed, the current one marked.
  • Headless, pass -m/--model:
eonyx run -m deepseek-v4-pro "fix the failing test"

Keeping several models around pays off.
A cheap fast one for rough work.
A strong one for the hard problems.

The retry block controls transient failures and the wait for the first response:

"retry": {
  "max_retries": 3,
  "base_delay_ms": 500,
  "response_header_timeout_sec": 60
}
FieldDefaultMeaning
max_retries3extra attempts on 429/5xx and transport errors (0 disables them)
base_delay_ms500the first backoff step; it doubles, capped at 30s; honors Retry-After
response_header_timeout_sec60how long to wait for the first response header before streaming starts

There is deliberately no global Client.Timeout.
A long token stream must never be cut off by a clock.

eonyx config   # providers (keys hidden), models, default, limits
eonyx info     # where the config, data, cache and project root live
Strict schema
The config is parsed strictly.
An unknown field, a wrong type or broken JSON is fatal at startup.
For an unknown field you get its name and line number.
EONYX would rather not start than quietly swallow a typo.
Cheat sheet
  • Provider
    • type: "openai" + base_url
    • covers OpenAI, OpenRouter, DeepSeek, Moonshot and local servers
  • Secrets
    • via $ENV references in api_key/base_url
    • expanded after merging
  • Model
    • id + provider
    • context_window enables summarization, prices drive the cost counter
  • Switching
    • Ctrl+N / /model in the TUI or -m in headless mode
  • retry
    • max_retries (3), base_delay_ms (500), response_header_timeout_sec (60)