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 cloud providers, hide secrets and configure price, context window and retries.

Both blocks are defined in eonyx.json: the provider describes API access, the model binds a specific id to a provider, and you can switch models right inside a session.

There is only 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 can reference environment variables ($OPENAI_API_KEY) — they are expanded after the config layers are merged. That way the key never ends up in a file committed to the repository. The same applies to 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 are only needed for the cost indicator in the TUI header ($…); they do not affect behavior. context_window matters more: without it auto-summarization does not work.

  • In the TUI — Ctrl+N or /model: a list of configured models, the current one is marked.
  • In headless mode — the -m/--model flag:
eonyx run -m deepseek-v4-pro "fix the failing test"

It is convenient to keep several models in the config: a cheap fast one for rough work and a powerful one for hard tasks.

How EONYX retries transient failures and how to make sure the config was read without errors.

The retry block configures how the provider retries transient failures and how long it waits 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 — long token streams must not be cut off by a timeout.

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 a fatal error at startup (for an unknown field — with its name and line number). EONYX would rather not start than silently ignore 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)