Skip to content

Models overview

Ongrid does not ship with a baked-in model. The platform is a multi-provider router: you supply API keys for one or more upstreams, the manager surfaces the configured catalog to the SPA's per-message picker, and every chat / RCA / translate call dispatches to the right upstream at runtime.

Seven providers are supported out of the box:

ProviderDefault modelEnv key
Anthropicclaude-sonnet-4-6ONGRID_ANTHROPIC_API_KEY
OpenAIgpt-5.4ONGRID_OPENAI_API_KEY
Zhipu (GLM)glm-4.7ONGRID_ZHIPU_API_KEY
DeepSeekdeepseek-v4-flashONGRID_DEEPSEEK_API_KEY
Geminigemini-2.5-proONGRID_GEMINI_API_KEY
Kimikimi-k2.6ONGRID_KIMI_API_KEY
Custom (OpenAI-compatible)ONGRID_CUSTOM_API_KEY + base URL

Plus:

The two configuration paths

Both paths produce the same []llm.ProviderConfig the router consumes; they differ only in who operates the knob.

Env-seeded (boot)

cmd/ongrid/main.go reads cfg.LLM.* and seeds matching rows into system_settings.llm.* via setting.Service.SetIfAbsent. First boot of a fresh install with ONGRID_ANTHROPIC_API_KEY=... ends with a working Anthropic-default install — no SPA login required.

SetIfAbsent is the key — re-boots never overwrite operator edits in the SPA.

Settings UI (runtime)

/settings/llm in the SPA lets an admin:

  • Add / rotate the per-provider API key (stored in system_settings.llm.<provider>_api_key with the secret flag set).
  • Edit the BaseURL (relays, regional endpoints, China-based mirrors).
  • Maintain the per-provider model list (the closed-set the picker shows).
  • Pin the default model per provider.
  • Pick the default provider — what the home-page chat falls back to when no per-message pin is set.

The 6 vendor cards plus the 7th "Custom" card render with their real provider mark logos (sourced from simple-icons) so admins recognise them without reading labels.

Hot swap

Provider edits take effect within 60s without a manager restart. The DB → router cache TTL is the resolver's 60s, plus the MultiClient's own 60s — so worst case 120s. Edge agents are unaffected; the manager is the only LLM client.

The resolver

LLMSettingsResolver reads from system_settings.llm.* and assembles []llm.ProviderConfig. Falls back to env defaults per field so a half-configured install (key set via env, BaseURL left blank) still works.

go
// internal/manager/biz/setting/llm.go:133
func (r *LLMSettingsResolver) ResolveProviders(ctx context.Context) (
    providers []llm.ProviderConfig, defaultProvider string, err error,
)

Provider IDs are stable strings: openai, anthropic, zhipu, gemini, deepseek, kimi, custom. These ids show up everywhere — the chat picker, audit logs, ChatReq.Provider, WithProvider option.

The catalog endpoint

GET /v1/aiops/models returns the catalog the SPA picker renders:

json
{
  "providers": [
    {
      "id": "anthropic",
      "label": "Anthropic",
      "default_model": "claude-sonnet-4-6",
      "models": ["claude-opus-4-7", "claude-sonnet-4-6", "claude-haiku-4-5"]
    },
    {
      "id": "zhipu", "label": "Zhipu (GLM)",
      "default_model": "glm-4.7",
      "models": ["glm-5.1", "glm-5", "glm-4.7", "glm-4.7-flash"]
    }
  ],
  "default": "anthropic"
}

Providers with no API key configured are silently dropped — that's how the picker knows what's actually available. API keys themselves are never returned by this endpoint.

Per-call dispatch

A ChatReq carries a Provider field; when set, MultiClient.Chat dispatches to the matching sub-client. When empty, the router uses the configured default (DB > env > first sorted).

go
// internal/pkg/llm/router.go
func (m *MultiClient) Chat(ctx context.Context, req ChatReq) (*ChatResp, error)

For graph-kernel calls (the ReAct agent), the equivalent is llm.WithProvider(id) as an eino model option — see Routing.

What's where

See also