Skip to content

Providers & Routing

LoopForge loads provider config from ~/.loopforge/config.toml and routes each task kind (planning, coding, summary) to a (provider, model) pair.

For field-by-field config details, see Config Reference. For the runtime path that consumes routing decisions, see Runtime Architecture.

Mental model

Think about provider setup in three layers:

  1. providers.* defines how to talk to one provider: API kind, base URL, credentials, and default model.
  2. router.* decides which (provider, model) pair each task kind should use.
  3. The runtime reads that routing choice before each model turn, so you can keep planning local while moving coding to a stronger cloud model.

In practice, the safest workflow is:

loopforge config validate
loopforge doctor

Run those after every routing change.

A good default progression is:

  1. Local-first — point all routes at ollama until your workflow is stable.
  2. Hybrid — keep planning and summary local, move coding to a stronger cloud provider.
  3. Cloud-heavy — only after you trust cost, latency, and security posture, move more task kinds to hosted providers.

That path keeps iteration cheap while making it easy to upgrade coding quality later.

Built-in presets (out of the box)

After loopforge init, your ~/.loopforge/config.toml already includes common providers and sensible defaults:

  • Local: ollama
  • OpenAI-compatible: deepseek, kimi / kimi_cn, qwen / qwen_cn / qwen_sg, glm, minimax, nvidia
  • Provider-native: qwen_native*, glm_native, minimax_native
  • Gateways: minimax_anthropic
  • First-party APIs: anthropic, gemini
  • AWS: bedrock

You usually only need to:

  1. set the corresponding API key env var (if any)
  2. point one or more [router.*] entries at the provider you want

How to choose a provider kind

  • openai_compatible — best when the provider exposes an OpenAI-style Chat Completions API; this covers Ollama and many hosted gateways.
  • dashscope_native — use when you want Alibaba DashScope native behavior.
  • zhipu_native — use GLM native APIs when you want Zhipu-specific auth and semantics.
  • minimax_native — use MiniMax native APIs directly.
  • anthropic — use Claude directly or through compatible gateways supported by the driver.
  • gemini — use Google Gemini directly.
  • bedrock — use AWS Bedrock via the Converse API (native AWS SDK; uses standard AWS credential resolution).

If you are unsure, prefer the preset already generated by loopforge init instead of inventing a custom provider entry from scratch.

Safe switch checklist

When switching providers or models, do it incrementally:

  1. set or update the provider API key env var
  2. update providers.<name> if the endpoint or default model changes
  3. change one router.* entry at a time
  4. run validation and diagnostics
  5. run one small agent task before moving all routes

A practical smoke path looks like this:

1
2
3
loopforge config validate
loopforge doctor
loopforge agent run --workspace loopforge-smoke --prompt "Create hello.txt"

If you are enabling a new hosted provider for the first time, also consider running the provider-specific smoke tests documented below.

Provider kinds

  • openai_compatible: OpenAI-compatible Chat Completions APIs (Ollama, DeepSeek, Kimi, many gateways)
  • dashscope_native: Alibaba DashScope native API (Qwen native)
  • zhipu_native: Zhipu GLM native API (JWT auth handled)
  • minimax_native: MiniMax native text/chatcompletion_v2
  • anthropic: Claude API (and compatible gateways)
  • gemini: Google Gemini API
  • bedrock: AWS Bedrock (Converse API)

Example: Ollama (local)

1
2
3
4
5
6
7
8
9
[providers.ollama]
kind = "openai_compatible"
base_url = "http://127.0.0.1:11434/v1"
api_key_env = ""
default_model = "llama3.2"

[router.coding]
provider = "ollama"
model = "default"

Example: GLM (Zhipu native)

1
2
3
4
5
6
7
8
9
[providers.glm_native]
kind = "zhipu_native"
base_url = "https://open.bigmodel.cn/api/paas/v4"
api_key_env = "ZHIPUAI_API_KEY" # typically "id.secret"
default_model = "glm-4"

[router.coding]
provider = "glm_native"
model = "default"

Zhipu auth format

If ZHIPUAI_API_KEY looks like id.secret, LoopForge will sign a short-lived JWT automatically.

Example: MiniMax (native)

1
2
3
4
5
6
7
8
9
[providers.minimax_native]
kind = "minimax_native"
base_url = "https://api.minimax.chat/v1"
api_key_env = "MINIMAX_API_KEY"
default_model = "MiniMax-M2.5"

[router.coding]
provider = "minimax_native"
model = "default"

Example: NVIDIA NIM (OpenAI-compatible)

1
2
3
4
5
6
7
8
9
[providers.nvidia]
kind = "openai_compatible"
base_url = "https://integrate.api.nvidia.com/v1"
api_key_env = "NVIDIA_API_KEY"
default_model = "meta/llama-3.2-3b-instruct"

[router.coding]
provider = "nvidia"
model = "default"

Example: AWS Bedrock (Converse API)

[providers.bedrock]
kind = "bedrock"
base_url = ""     # unused for Bedrock
api_key_env = ""  # unused for Bedrock
default_model = "anthropic.claude-3-5-sonnet-20241022-v2:0"

[providers.bedrock.aws_bedrock]
region = "us-east-1"
# optional: cross_region = "us"   # prefixes model id with "us." if not already present
# optional: profile = "my-profile"

[router.coding]
provider = "bedrock"
model = "default"

Credentials

Bedrock uses the AWS SDK credential chain (env vars, shared config, profiles, instance role, etc.). If you set profile in config, LoopForge will pass it to the SDK.

Routing patterns

All-local starter

[router.planning]
provider = "ollama"
model = "default"

[router.coding]
provider = "ollama"
model = "default"

[router.summary]
provider = "ollama"
model = "default"

Local planning, stronger cloud coding

[router.planning]
provider = "ollama"
model = "default"

[router.coding]
provider = "glm_native" # or minimax_native / deepseek / kimi / qwen_native ...
model = "default"

[router.summary]
provider = "ollama"
model = "default"

Use model = "default" when you want routing to follow providers.<name>.default_model.

API keys (env vars)

LoopForge reads provider keys from the env var referenced by api_key_env.

1
2
3
4
5
6
export DEEPSEEK_API_KEY="..."
export MOONSHOT_API_KEY="..."
export DASHSCOPE_API_KEY="..."
export ZHIPUAI_API_KEY="id.secret"
export MINIMAX_API_KEY="..."
export NVIDIA_API_KEY="..."
1
2
3
4
5
6
$env:DEEPSEEK_API_KEY = "..."
$env:MOONSHOT_API_KEY = "..."
$env:DASHSCOPE_API_KEY = "..."
$env:ZHIPUAI_API_KEY = "id.secret"
$env:MINIMAX_API_KEY = "..."
$env:NVIDIA_API_KEY = "..."

Optional smoke tests (real providers)

These tests hit real provider endpoints and are #[ignore] by default:

# Ollama (OpenAI-compatible)
LOOPFORGE_OLLAMA_MODEL=<your-model> cargo test -p rexos --test ollama_smoke -- --ignored

# GLM (Zhipu native)
ZHIPUAI_API_KEY=<id.secret> LOOPFORGE_GLM_MODEL=<model> cargo test -p rexos --test zhipu_smoke -- --ignored

# MiniMax (native)
MINIMAX_API_KEY=<key> LOOPFORGE_MINIMAX_MODEL=<model> cargo test -p rexos --test minimax_smoke -- --ignored

# NVIDIA NIM (OpenAI-compatible)
NVIDIA_API_KEY=<key> LOOPFORGE_NVIDIA_MODEL=<model> cargo test -p rexos --test nvidia_nim_smoke -- --ignored

# AWS Bedrock (Converse API)
LOOPFORGE_BEDROCK_MODEL=<model-id> cargo test -p rexos --features bedrock --test bedrock_smoke -- --ignored

Provider health report (nightly-friendly)

To generate a provider quality report (JSON + Markdown):

1
2
3
4
5
# dry-run planning (no test execution)
python3 scripts/provider_health_report.py --out-dir .tmp/provider-health

# run available provider smokes
python3 scripts/provider_health_report.py --out-dir .tmp/provider-health --run

Artifacts: - .tmp/provider-health/provider-health.json - .tmp/provider-health/provider-health.md

Tips: - Set ZHIPUAI_API_KEY / MINIMAX_API_KEY / NVIDIA_API_KEY to include those provider checks. - For CI environments without local Ollama, set:

export LOOPFORGE_SKIP_OLLAMA_SMOKE=1