Multi-Provider Routing
niuma_code supports multiple API providers simultaneously. Configure different endpoints in factories, and requests are automatically routed to the correct provider based on the selected model.
Configuration
Provider config lives in ~/.niuma/settings.json (user layer) or <project>/.niuma/settings.json (project layer):
{
"factories": [
{
"base_url": "https://api.anthropic.com",
"api_key": "sk-ant-key1",
"options": ["claude-sonnet-4-6", "claude-opus-4-8"]
},
{
"base_url": "https://openrouter.ai/api",
"api_key": "sk-or-key2",
"options": ["gpt-4o", "gemini-2.5-pro"]
}
],
"llm": {
"default_model": "claude-sonnet-4-6",
"default_effort": "medium",
"thinking_budget_low": "0",
"thinking_budget_medium": "0",
"thinking_budget_high": "10000",
"thinking_budget_max": "20000"
}
}
Factory Fields
| Field | Required | Description |
|---|---|---|
base_url |
Yes | API endpoint URL (supports Anthropic-compatible proxies) |
api_key |
Yes | Authentication key for the provider |
options |
Yes | List of model names available from this provider |
LLM Block
| Field | Required | Default | Description |
|---|---|---|---|
default_model |
No | claude-sonnet-4-6 |
Model used at session start |
default_effort |
No | medium |
Thinking depth: low, medium, high, max |
thinking_budget_low |
No | "0" |
Token budget when effort is low |
thinking_budget_medium |
No | "0" |
Token budget when effort is medium |
thinking_budget_high |
No | "10000" |
Token budget when effort is high |
thinking_budget_max |
No | "20000" |
Token budget when effort is max |
How Routing Works
You type: /model
→ TUI: Model Settings overlay opens, showing all factories and their models
→ CLI: Lists all providers with model names
→ You select a model from the list
→ Config.get_current_model() switches the session model
→ get_factory_for_model() routes to the matching factory's base_url + api_key
→ Switches instantly, no restart needed
The first provider in the list is the default. Switching is instant and triggers a prompt cache invalidation warning.
Switching Models
Via /model Command
/model → Open model selection overlay (TUI) or list all providers (CLI)
The /model command opens a visual model selection overlay in TUI mode. In CLI mode, it displays the current model and a numbered list of all available models from each provider.
Selecting a new model updates the session-level current_model — all subsequent LLM requests use the new model and its corresponding provider endpoint.
Effort Control
Effort controls thinking depth, not model selection. Switch effort during a session:
| Effort | Thinking Budget | Use Case |
|---|---|---|
low |
0 tokens | Quick responses, greetings |
medium |
0 tokens | General coding tasks (default) |
high |
10,000 tokens | Complex refactoring, architecture |
max |
20,000 tokens | Deep analysis, multi-step reasoning |
Configure thinking token budgets in the llm block of settings.json.
Config File Selection (Single-Source)
factories/llm/env/compact/memory_quality 等主配置采用单一来源(不叠加):
| Mode | Config Path | When |
|---|---|---|
| Development | <project>/.niuma/settings.json |
CWD contains "niuma" and has app/ + app/core/ subdirectories |
| Deploy | ~/.niuma/settings.json |
All other cases |
No local.json layer exists. No three-layer merge. Each mode reads exactly one file — "where you run is what you get."
Exception — memory_palace: This section uses a two-layer override (project → user fallback), independent of the main config. If memory_palace is present in the project-level settings.json, it is used; otherwise falls back to ~/.niuma/settings.json.
// Development mode: .niuma/settings.json
// (CWD has app/ + app/core/ → project-level only)
{
"factories": [
{ "base_url": "https://api.anthropic.com", "api_key": "...", "options": ["claude-sonnet-4-6"] }
]
}
// Deploy mode: ~/.niuma/settings.json
// (other CWD → user-level only)
{
"factories": [
{ "base_url": "https://custom-proxy.com", "api_key": "...", "options": ["claude-sonnet-4-6"] }
]
}
Adding a New Provider
- Get an API key from the provider
- Add a new entry to
settings.json:
{
"factories": [
{ "base_url": "https://api.anthropic.com", "api_key": "sk-ant-...", "options": ["claude-sonnet-4-6", "claude-opus-4-8"] },
{ "base_url": "https://openrouter.ai/api", "api_key": "sk-or-...", "options": ["gpt-4o", "gemini-2.5-pro"] },
{ "base_url": "https://api.deepseek.com", "api_key": "sk-ds-...", "options": ["deepseek-chat", "deepseek-coder"] }
]
}
- Use
/modelto open the selection overlay and switch to the new model
Common Provider Configurations
Anthropic (Direct or via Proxy)
{
"base_url": "https://api.anthropic.com",
"api_key": "sk-ant-...",
"options": ["claude-sonnet-4-6", "claude-opus-4-8"]
}
OpenRouter (Multi-model)
{
"base_url": "https://openrouter.ai/api",
"api_key": "sk-or-...",
"options": ["gpt-4o", "gemini-2.5-pro", "llama-3.1-405b"]
}
Self-Hosted (Ollama)
{
"base_url": "http://localhost:11434/v1",
"api_key": "not-needed",
"options": ["llama3.1", "codellama"]
}
Troubleshooting
| Issue | Solution |
|---|---|
| Model not found in selection | Check the options list in the matching factory for exact model name |
| 401 Unauthorized | Verify api_key is correct for that factory |
| Connection refused | Check base_url and network access |
| Slow responses | Try a different provider or region-specific endpoint |
| Model switch not taking effect | Ensure the model name matches exactly (case-sensitive) |
| Prompt cache warning after switch | Expected — switching models invalidates the prompt cache |