Providers
Provider implementations live in go-llm-router (v0.4.0), an external module extracted from Agenvoy. Agenvoy builds every agent through router.New(cfg) and calls one Agent.Send() surface — no per-vendor code remains in this repository.
Supported list
| Provider | ID | Auth | Notes |
|---|---|---|---|
| OpenAI | openai |
API key | Chat Completions / Responses API |
| OpenAI Codex | codex |
OAuth | Uses your ChatGPT / Codex subscription, no API key; SSE streaming |
| Anthropic Claude | claude |
API key | Messages API; parallel tool use on by default |
| Google Gemini | gemini |
API key | gemini-2.x / 3.x families |
| xAI Grok | grok |
API key | grok-4 / grok-3 families |
| xAI Grok (OAuth) | grok-oauth |
OAuth | xAI subscription instead of pay-per-token |
| GitHub Copilot | copilot |
OAuth | Device-code login flow |
| DeepSeek | deepseek |
API key | deepseek-chat (tool use) and deepseek-reasoner |
| NVIDIA NIM | nvidia |
API key | Llama, Mistral, gpt-oss, and other hosted open-weight models |
| OpenRouter | openrouter |
API key | Aggregator — routes to models from many vendors through one key |
| Cloudflare | cloudflare |
API token + account ID | Workers AI; optional gateway ID |
| Compat | compat |
Custom URL (+ optional key) | Any OpenAI-compatible endpoint — Ollama, LM Studio, vLLM, LiteLLM |
Model lists are fetched live from each provider's API when a model is added (TUI /model, or GET /v1/provider/:provider/models). There are no static model catalogs in the repository.
Configuration
Everything is managed from the TUI or the local HTTP API — there is no agen model CLI subcommand:
| Task | TUI | HTTP |
|---|---|---|
| Add / remove a provider or model | /model |
POST /v1/models, DELETE /v1/models/*name |
| Pick the dispatcher model | /model (or Shift+W / Shift+S to cycle) |
GET POST /v1/model/dispatcher |
| Pick the summary model | /model |
GET POST /v1/model/summary |
| Pick a session's model | /model |
POST /v1/session/:id/model |
| Store a credential | /key |
POST /v1/provider/:provider/key |
| OAuth login | /model |
GET /v1/provider/:provider/oauth (SSE device code) |
Credentials (API keys, OAuth tokens) live in the OS keychain under service agenvoy, never in plain JSON.
Dispatcher model
The dispatcher LLM decides which worker model handles each task. It runs through SelectAgent() before Execute() enters its iteration loop, receiving the user input plus a hint about any matched skill. Its own routing call is issued at ReasoningNone to keep dispatch cheap.
Set it with /model in the TUI, or POST /v1/model/dispatcher. When no dispatcher is configured, the first successfully initialized agent becomes the fallback.
Reasoning levels
go-llm-router normalizes reasoning onto one scale — none, low, medium (default), high, xhigh, max — and maps it per provider (Claude thinking budgets, Gemini thinking budgets, OpenAI effort, …). Levels outside a model's supported range are clamped rather than rejected.
The level is passed explicitly through each Send call; there is no global reasoning setting in config.json. Cycle it with Shift+A / Shift+D in the TUI.
Fast mode
Shift+F toggles fast mode, which passes provider.ModeFast through the router so supported backends request a faster service tier. Support is model-specific (core.SupportFast) — for example recent OpenAI and Claude Opus generations, most Grok models, and selected Gemini families. Unsupported models silently fall back to the default tier. Fast mode is process-local and not persisted.
Adding a custom OpenAI-compatible endpoint
Use the compat provider type and point it at any endpoint that accepts the OpenAI Chat Completions schema. URL convention follows Zed: enter the URL up to /v1 (e.g. http://192.168.1.10:4000/v1, Ollama default http://localhost:11434/v1); the router appends /chat/completions.
Storage split (URL vs key)
| What | Where | API |
|---|---|---|
| URL | ~/.config/agenvoy/config.json compats[].URL |
session.UpsertCompat / session.GetCompatURL |
| API key | OS keychain | keychain.Set("COMPAT_<NAME>_API_KEY", value) |
There is no COMPAT_<NAME>_URL keychain key — it was removed after a bug where the TUI wrote the URL to config while the runtime read the keychain and always fell back to localhost.
Tested compat targets
| Target | Works | Notes |
|---|---|---|
| Ollama | Yes | default http://localhost:11434/v1 |
| LM Studio | Yes | |
| vLLM | Yes | --enable-auto-tool-choice --tool-call-parser <name> for tool use |
| llama.cpp server | Yes | |
| LiteLLM proxy | Yes | virtual key as Bearer token |
| Groq / Together / DeepInfra / Fireworks | Yes | |
| Azure OpenAI | No | needs an api-key header (not Bearer) plus ?api-version= — not supported |
Send timeout and failure handling
| Layer | Value | Catches |
|---|---|---|
| Provider HTTP client | set inside go-llm-router per provider |
Transport-level stalls |
AgentSendTimeoutSec |
limits.agent_send_timeout_seconds in config.json, default 600 |
Exec-layer ceiling via context.WithTimeout |
On failure the exec layer retries a timeout on the same model up to three times, registers a 30-minute cooldown for rate-limit-class errors, then falls back to the next healthy model. See the Execution Engine page for the full escalation table.