Skip to content

Custom (OpenAI-compatible)

TL;DR

bash
ONGRID_CUSTOM_API_KEY=...
ONGRID_CUSTOM_BASE_URL=https://your-relay/v1     # REQUIRED — no upstream default
ONGRID_CUSTOM_MODEL=your-default-model

Provider id: custom. SDK adapter: eino-openai (any OpenAI Chat Completions–compatible endpoint).

The Custom slot is the 7th provider card in the Settings UI. It exists for everything that's OpenAI-compatible at the wire level but isn't one of the six baked-in providers:

  • Self-hosted vLLM / TGI / llama.cpp.
  • OpenRouter, Together, Fireworks, Anyscale, Groq, Mistral.
  • Internal corporate model gateways.
  • New providers that ship before Ongrid adds a dedicated slot for them.

The base-URL guard

The custom slot requires an explicit base URL. Without one, the underlying SDK would silently fall back to OpenAI's default (https://api.openai.com/v1), sending the operator's custom key to the wrong host. The resolver skips the provider in that case:

go
// internal/manager/biz/setting/llm.go:155
if pk.id == model.LLMProviderCustom && strings.TrimSpace(baseURL) == "" {
    continue
}

Provide a BaseURL via env or Settings UI; otherwise the provider never appears in the catalog.

Env vars

VarDefaultNotes
ONGRID_CUSTOM_API_KEYEmpty = provider dropped
ONGRID_CUSTOM_BASE_URLREQUIRED
ONGRID_CUSTOM_MODELDefault model id sent on every call
ONGRID_CUSTOM_MODELSCatalog list (closed set the SPA picker shows)

There's no out-of-box default catalog — fill in what your endpoint supports.

Pre-registered inner ChatModel

The graph-kernel runtime pre-registers an inner ChatModel for the custom provider id at boot, even when no key is yet configured. This is the "configured AFTER boot routes immediately, no restart" property operators expect from the Settings UI:

go
// cmd/ongrid/main.go:2457
for _, id := range []string{
    llm.ProviderOpenAI, llm.ProviderAnthropic, llm.ProviderZhipu,
    llm.ProviderGemini, llm.ProviderDeepSeek, llm.ProviderKimi, llm.ProviderCustom,
} {
    if _, ok := innerModels[id]; !ok {
        addInner(id, "") // model supplied per-call (picker / DefaultResolver)
    }
}

The inner exists at boot; the per-call key / baseURL is resolved dynamically via the LLM-settings resolver. Unconfigured providers never reach the picker (the /v1/aiops/models catalog gates on ResolveProviders), so the inner is harmless until it's actually needed.

Configuration examples

OpenRouter

bash
ONGRID_CUSTOM_API_KEY=sk-or-v1-...
ONGRID_CUSTOM_BASE_URL=https://openrouter.ai/api/v1
ONGRID_CUSTOM_MODEL=anthropic/claude-sonnet-4
ONGRID_CUSTOM_MODELS=anthropic/claude-sonnet-4,anthropic/claude-opus-4,meta-llama/llama-3.3-70b

Local vLLM

bash
ONGRID_CUSTOM_API_KEY=sk-not-checked-by-vllm
ONGRID_CUSTOM_BASE_URL=http://vllm.internal:8000/v1
ONGRID_CUSTOM_MODEL=Qwen2.5-72B-Instruct
ONGRID_CUSTOM_MODELS=Qwen2.5-72B-Instruct

vLLM doesn't validate API keys by default — set any non-empty string.

Groq

bash
ONGRID_CUSTOM_API_KEY=gsk_...
ONGRID_CUSTOM_BASE_URL=https://api.groq.com/openai/v1
ONGRID_CUSTOM_MODEL=llama-3.3-70b-versatile

Mistral

bash
ONGRID_CUSTOM_API_KEY=...
ONGRID_CUSTOM_BASE_URL=https://api.mistral.ai/v1
ONGRID_CUSTOM_MODEL=mistral-large-latest

Making Custom the default

bash
ONGRID_LLM_DEFAULT_PROVIDER=custom

Watch out for the LLM-resolver bug — if default_provider is unset, the resolver falls back to the first sorted provider id (anthropic). With OpenRouter wired via the custom slot but default_provider="", chat calls go to Anthropic's model id on Anthropic's endpoint, not OpenRouter — which fails on auth. Set default_provider=custom explicitly.

Quirks

  • Schema fidelity — assumes the endpoint speaks real OpenAI Chat Completions. Endpoints that strip fields (tool_calls, finish_reason) will degrade the agent's function-calling reliably.
  • Streaming — many relays don't yet support streaming. The adapter handles both modes; if Stream() errors with "streaming not supported", the chat UI auto-falls-back to buffered.
  • No native rate-limit — corporate gateways often impose per-token rate limits that don't show up as standard 429s. Set ONGRID_LLM_DAILY_TOKEN_LIMIT for a cross-provider budget guard — see Budget.

See also