feat: add CloudGPU provider to the embedded catalog

Register cloudgpu as an OpenAI-compatible catalog provider at
https://cloudgpu.app/v1, discover CLOUDGPU_API_KEY, and default to
deepseek-v4.1-flash.

Co-authored-by: CloudGPU <mrhy7176@users.noreply.github.com>
This commit is contained in:
Cursor AgentandCloudGPU committed 2026-10-29 10:12:27 +00:00
1 parent 1dcaf58bc2
commit a70ece7245
14 files changed
+208 -5

No files matched your search

+1 -1
View File
@@ -224,7 +224,7 @@
"properties": {
"provider": {
"type": "string",
"description": "The underlying provider type. Defaults to \"openai\" when not set. Supported values: openai, anthropic, google, amazon-bedrock, dmr, and any built-in alias (requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud, azure, xai, ollama, mistral, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, nvidia, github-copilot, chatgpt, opencode, opencode-go, etc.).",
"description": "The underlying provider type. Defaults to \"openai\" when not set. Supported values: openai, anthropic, google, amazon-bedrock, dmr, and any built-in alias (requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud, cloudgpu, azure, xai, ollama, mistral, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, nvidia, github-copilot, chatgpt, opencode, opencode-go, etc.).",
"examples": [
"openai",
"anthropic",
+3 -3
View File
@@ -18,7 +18,7 @@ models:
first_available: [list] # Optional: candidate model refs, tried in order by available credentials.
# Mutually exclusive with other model settings.
provider: string # Required unless using first_available. One of: openai, anthropic, google, amazon-bedrock,
# dmr, mistral, xai, nebius, nvidia, minimax, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud,
# dmr, mistral, xai, nebius, nvidia, minimax, baseten, daoxe, ovhcloud, groq, fireworks-ai, deepseek, cerebras, togetherai, huggingface, moonshotai, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, requesty, openrouter, opper, runcrate, api-route, lunaroute, orcarouter, atlascloud, cloudgpu,
# azure, ollama, github-copilot, or a named provider defined
# under the top-level `providers:` section.
model: string # Required: model identifier
@@ -60,7 +60,7 @@ models:
| Property | Type | Required | Description |
| --------------------- | ---------- | -------- | ------------------------------------------------------------------------------------- |
| `first_available` | array | ✗ | Candidate model references tried in order; selects the first whose credentials are configured. Mutually exclusive with other model settings. |
| `provider` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Provider: `openai`, `anthropic`, `google`, `amazon-bedrock`, `dmr`, `mistral`, `xai`, `nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `api-route`, `lunaroute`, `orcarouter`, `atlascloud`, `azure`, `ollama`, `github-copilot`, `chatgpt`, `opencode`, `opencode-go`, or any [named provider](../../providers/custom/index.md). |
| `provider` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Provider: `openai`, `anthropic`, `google`, `amazon-bedrock`, `dmr`, `mistral`, `xai`, `nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `api-route`, `lunaroute`, `orcarouter`, `atlascloud`, `cloudgpu`, `azure`, `ollama`, `github-copilot`, `chatgpt`, `opencode`, `opencode-go`, or any [named provider](../../providers/custom/index.md). |
| `model` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Model name (e.g., `gpt-4o`, `claude-sonnet-4-5`, `gemini-3.5-flash`) |
| `description` | string | ✗ | Informational, human-readable summary of the model's purpose or strengths (e.g., "fast and cheap, good for summaries"). Not sent to the model. Can be combined with `first_available` (a selector's description is kept when it resolves). |
| `temperature` | float | ✗ | Sampling randomness. Range is provider-dependent — typically `0.0–2.0` (Anthropic caps at `1.0`). `0.0` is deterministic. |
@@ -558,7 +558,7 @@ for a complete local-server configuration.
## Custom HTTP Headers
For OpenAI-compatible providers (`openai`, `github-copilot`, `mistral`, `xai`,
`nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `lunaroute`, `orcarouter`, `atlascloud`, `ollama`, and any custom provider using the OpenAI API),
`nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks-ai`, `deepseek`, `cerebras`, `togetherai`, `huggingface`, `moonshotai`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `opper`, `runcrate`, `lunaroute`, `orcarouter`, `atlascloud`, `cloudgpu`, `ollama`, and any custom provider using the OpenAI API),
`provider_opts.http_headers` adds arbitrary HTTP headers to every outgoing
request:
+2
View File
@@ -191,6 +191,8 @@
url: /providers/cloudflare-workers-ai/
- title: ChatGPT
url: /providers/chatgpt/
- title: CloudGPU
url: /providers/cloudgpu/
- title: DaoXE
url: /providers/daoxe/
- title: DeepSeek
+114
View File
@@ -0,0 +1,114 @@
---
title: "CloudGPU"
description: "Use CloudGPU models with Docker Agent."
keywords: docker agent, ai agents, model providers, llm, cloudgpu
weight: 26
canonical: https://docs.docker.com/ai/docker-agent/providers/cloudgpu/
---
_Use CloudGPU models with Docker Agent._
## Overview
[CloudGPU](https://cloudgpu.app/api/docs) serves DeepSeek, Kimi, GLM and MiniMax
models through an OpenAI-compatible API. Docker Agent includes built-in support
for CloudGPU as an alias provider. Current model IDs are on the live
[model list](https://cloudgpu.app/v1/models).
## Setup
1. Create an API key in the [CloudGPU console](https://cloudgpu.app/)
2. Set the environment variable:
```bash
export CLOUDGPU_API_KEY=your-api-key
```
## Usage
### Inline Syntax
Use a CloudGPU model by prefixing its model ID with `cloudgpu/`:
```yaml
agents:
root:
model: cloudgpu/deepseek-v4.1-flash
description: Assistant using CloudGPU
instruction: You are a helpful assistant.
```
### Named Model
For more control over parameters:
```yaml
models:
cloudgpu_kimi:
provider: cloudgpu
model: kimi-k2.6
temperature: 0.7
max_tokens: 8192
agents:
root:
model: cloudgpu_kimi
description: Assistant using CloudGPU
instruction: You are a helpful assistant.
```
When CloudGPU is selected automatically from available credentials, the default
model is `deepseek-v4.1-flash`.
## Available Models
Some chat model IDs CloudGPU serves:
| Model ID | Model |
| --- | --- |
| `deepseek-v4.1-flash` | DeepSeek V4.1 Flash (default) |
| `deepseek-v4-pro` | DeepSeek V4 Pro |
| `kimi-k2.6` | Kimi K2.6 |
| `glm-5.2` | GLM 5.2 |
| `minimax-m3` | MiniMax M3 |
Model IDs are case-sensitive. The live [`/v1/models` endpoint](https://cloudgpu.app/v1/models)
lists current IDs, and the [API docs](https://cloudgpu.app/api/docs) describe
the endpoints. A listing does not guarantee that inference is currently available.
CloudGPU is absent from the embedded models.dev catalog. Docker Agent does not
import context limits or attachment capabilities from CloudGPU's model list.
Attachment capabilities fall back to text-only, so image and PDF attachments
are dropped, with a warning logged once per model.
If you have verified that your chosen model accepts a particular attachment
type, set `models.<name>.capabilities` to override detection. See
[Attachment Capability Overrides](../../configuration/models/index.md#attachment-capability-overrides)
for all supported flags.
## How It Works
CloudGPU is a built-in alias in Docker Agent:
- **API type:** OpenAI-compatible Chat Completions (`openai_chatcompletions`)
- **Base URL:** `https://cloudgpu.app/v1`
- **Token variable:** `CLOUDGPU_API_KEY`
Some models CloudGPU serves require a single leading system message, so Docker
Agent coalesces consecutive system messages into one.
## Example: Code Assistant
```yaml
agents:
coder:
model: cloudgpu/deepseek-v4.1-flash
description: Code assistant using CloudGPU
instruction: |
You are an expert programmer.
Write clean code and follow language best practices.
toolsets:
- type: filesystem
- type: shell
- type: think
```
+1
View File
@@ -73,6 +73,7 @@ Use this table to find a built-in provider's config key and authentication metho
| OrcaRouter | `orcarouter` | `ORCAROUTER_API_KEY` |
| Atlas Cloud | [`atlascloud`](../atlascloud/index.md) | `ATLASCLOUD_API_KEY` |
| Runcrate | [`runcrate`](../runcrate/index.md) | `RUNCRATE_API_KEY` |
| CloudGPU | [`cloudgpu`](../cloudgpu/index.md) | `CLOUDGPU_API_KEY` |
| Azure OpenAI | `azure` | `AZURE_API_KEY` + `base_url` (override the key with `token_key`) |
| [Ollama](../local/index.md) | `ollama` | None (local; optional `base_url`) |
| GitHub Copilot | `github-copilot` | `GITHUB_TOKEN` or `GH_TOKEN` (PAT with `copilot` scope) |
+1
View File
@@ -223,6 +223,7 @@ remote MCP endpoints.
| [`huggingface.yaml`](huggingface.yaml) | Hugging Face Inference Providers open-model router. |
| [`moonshot.yaml`](moonshot.yaml) | Moonshot AI Kimi provider (`moonshotai`). |
| [`vercel.yaml`](vercel.yaml) | Vercel AI Gateway multi-provider router. |
| [`cloudgpu.yaml`](cloudgpu.yaml) | CloudGPU OpenAI-compatible provider (`cloudgpu`). |
| [`cloudflare-workers-ai.yaml`](cloudflare-workers-ai.yaml) | Cloudflare Workers AI edge-hosted open models. |
| [`cloudflare-ai-gateway.yaml`](cloudflare-ai-gateway.yaml) | Cloudflare AI Gateway multi-provider router. |
| [`grok.yaml`](grok.yaml) | xAI Grok model. |
+17
View File
@@ -0,0 +1,17 @@
# yaml-language-server: $schema=../agent-schema.json
models:
cloudgpu_model:
provider: cloudgpu
model: deepseek-v4.1-flash
agents:
root:
model: cloudgpu_model
description: Assistant using CloudGPU
instruction: |
You are a helpful assistant.
toolsets:
- type: filesystem
- type: shell
- type: think
+20 -1
View File
@@ -113,6 +113,13 @@ func TestAvailableProviders_NoGateway(t *testing.T) {
},
expectedProvider: "runcrate",
},
{
name: "cloudgpu api key present",
envVars: map[string]string{
"CLOUDGPU_API_KEY": "test-key",
},
expectedProvider: "cloudgpu",
},
{
name: "baseten api key present",
envVars: map[string]string{
@@ -379,6 +386,15 @@ func TestAutoModelConfig(t *testing.T) {
expectedModel: "deepseek-ai/DeepSeek-V4.1-Flash",
expectedMaxTokens: 32000,
},
{
name: "cloudgpu provider",
envVars: map[string]string{
"CLOUDGPU_API_KEY": "test-key",
},
expectedProvider: "cloudgpu",
expectedModel: "deepseek-v4.1-flash",
expectedMaxTokens: 32000,
},
{
name: "lunaroute provider",
envVars: map[string]string{"LUNAROUTE_API_KEY": "lr_test"},
@@ -596,6 +612,7 @@ func TestDefaultModels(t *testing.T) {
assert.Equal(t, "meta-llama/llama-4-maverick", DefaultModels["openrouter"])
assert.Equal(t, "orcarouter/auto", DefaultModels["orcarouter"])
assert.Equal(t, "glm-5.3", DefaultModels["lunaroute"])
assert.Equal(t, "deepseek-v4.1-flash", DefaultModels["cloudgpu"])
assert.Equal(t, "qwen/qwen3.8-max", DefaultModels["atlascloud"])
assert.Equal(t, "deepseek-ai/DeepSeek-V4-Pro-0813", DefaultModels["baseten"])
assert.Equal(t, "Qwen3.5-397B-A17B", DefaultModels["ovhcloud"])
@@ -616,7 +633,7 @@ func TestAutoModelConfig_IntegrationWithDefaultModels(t *testing.T) {
t.Parallel()
// Verify that AutoModelConfig always returns a model from DefaultModels
providers := []string{"openai", "anthropic", "google", "mistral", "openrouter", "api-route", "orcarouter", "atlascloud", "baseten", "ovhcloud", "groq", "fireworks-ai", "deepseek", "cerebras", "togetherai", "huggingface", "moonshotai", "vercel", "opencode", "github-copilot"}
providers := []string{"openai", "anthropic", "google", "mistral", "openrouter", "api-route", "orcarouter", "atlascloud", "cloudgpu", "baseten", "ovhcloud", "groq", "fireworks-ai", "deepseek", "cerebras", "togetherai", "huggingface", "moonshotai", "vercel", "opencode", "github-copilot"}
for _, provider := range providers {
t.Run(provider, func(t *testing.T) {
@@ -644,6 +661,8 @@ func TestAutoModelConfig_IntegrationWithDefaultModels(t *testing.T) {
envVars["ORCAROUTER_API_KEY"] = "test-key"
case "atlascloud":
envVars["ATLASCLOUD_API_KEY"] = "test-key"
case "cloudgpu":
envVars["CLOUDGPU_API_KEY"] = "test-key"
case "baseten":
envVars["BASETEN_API_KEY"] = "test-key"
case "ovhcloud":
+28
View File
@@ -0,0 +1,28 @@
package config
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/docker/docker-agent/pkg/config/latest"
"github.com/docker/docker-agent/pkg/environment"
)
func TestCloudGPURequiredCredentials(t *testing.T) {
t.Parallel()
cfg := &latest.Config{
Agents: []latest.AgentConfig{{Name: "root", Model: "cloudgpu/deepseek-v4.1-flash"}},
Models: map[string]latest.ModelConfig{
"cloudgpu/deepseek-v4.1-flash": {Provider: "cloudgpu", Model: "deepseek-v4.1-flash"},
},
}
err := CheckRequiredEnvVars(t.Context(), cfg, "", environment.NewNoEnvProvider())
var required *environment.RequiredEnvError
require.ErrorAs(t, err, &required)
assert.Equal(t, []string{"CLOUDGPU_API_KEY"}, required.Missing)
assert.True(t, required.MissingModelCredentials)
require.NoError(t, CheckRequiredEnvVars(t.Context(), cfg, "", environment.NewMapEnvProvider(map[string]string{"CLOUDGPU_API_KEY": "test-key"})))
}
+1
View File
@@ -32,6 +32,7 @@ var modelsDevAbsentProviders = map[string]bool{
"api-route": true, // API Route model IDs come from its own /v1/models endpoint, not models.dev.
"lunaroute": true, // Lunaroute model IDs come from its own /v1/models endpoint, not models.dev.
"atlascloud": true, // Atlas Cloud model IDs come from its own /v1/models endpoint, not models.dev.
"cloudgpu": true, // CloudGPU model IDs come from its own /v1/models endpoint, not models.dev.
"runcrate": true, // Runcrate model IDs come from its own /v1/models endpoint, not models.dev.
"dmr": true, // Docker Model Runner (local, not in catalog)
"cloudflare-workers-ai": true, // example uses an @cf/... model id not present in the models.dev snapshot (only variant ids like -fp8 are listed)
+10
View File
@@ -134,6 +134,16 @@
"RUNCRATE_API_KEY"
]
},
{
"name": "cloudgpu",
"merge_consecutive_messages": true,
"api_type": "openai",
"base_url": "https://cloudgpu.app/v1",
"default_model": "deepseek-v4.1-flash",
"token_env_vars": [
"CLOUDGPU_API_KEY"
]
},
{
"name": "baseten",
"merge_consecutive_messages": true,
+1
View File
@@ -74,6 +74,7 @@ func TestProviderIDsMatchEmbeddedCatalog(t *testing.T) {
absent := map[string]string{
"api-route": "model IDs come from API Route's /v1/models endpoint, not models.dev",
"atlascloud": "model IDs come from Atlas Cloud's /v1/models endpoint, not models.dev",
"cloudgpu": "model IDs come from CloudGPU's /v1/models endpoint, not models.dev",
"chatgpt": "subscription backend, distinct from OpenAI",
"lunaroute": "model IDs come from Lunaroute’s /v1/models endpoint, not models.dev",
"runcrate": "model IDs come from Runcrate's /v1/models endpoint, not models.dev",
@@ -164,6 +164,7 @@ func TestShouldMergeConsecutiveMessages_Gating(t *testing.T) {
{"daoxe, no base_url", &latest.ModelConfig{Provider: "daoxe", Model: "claude-sonnet-4-6"}, true},
{"opper, no base_url", &latest.ModelConfig{Provider: "opper", Model: "claude-sonnet-4-6"}, true},
{"runcrate, no base_url", &latest.ModelConfig{Provider: "runcrate", Model: "deepseek-ai/DeepSeek-V4.1-Flash"}, true},
{"cloudgpu, no base_url", &latest.ModelConfig{Provider: "cloudgpu", Model: "deepseek-v4.1-flash"}, true},
{"ovhcloud", &latest.ModelConfig{Provider: "ovhcloud", Model: "Qwen3.5-397B-A17B"}, true},
{"open-model host alias cerebras", &latest.ModelConfig{Provider: "cerebras", Model: "qwen-3-coder-480b"}, true},
{"open-model host fireworks", &latest.ModelConfig{Provider: "fireworks", Model: "accounts/fireworks/models/kimi-k3"}, true},
@@ -97,6 +97,14 @@ var openAIAliasProviders = []openAIAliasProvider{
greeting: "Hello from Runcrate",
mergesSystemMessages: true,
},
{
provider: "cloudgpu",
envVar: "CLOUDGPU_API_KEY",
testKey: "test-cloudgpu-key",
model: "deepseek-v4.1-flash",
greeting: "Hello from CloudGPU",
mergesSystemMessages: true,
},
{
provider: "deepseek",
envVar: "DEEPSEEK_API_KEY",