diff --git a/agent-schema.json b/agent-schema.json index 9d5dcde85..221166374 100644 --- a/agent-schema.json +++ b/agent-schema.json @@ -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, 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, cloudgpu, api-route, 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.).", "examples": [ "openai", "anthropic", diff --git a/docs/configuration/models/index.md b/docs/configuration/models/index.md index 51124d69e..1c1abec25 100644 --- a/docs/configuration/models/index.md +++ b/docs/configuration/models/index.md @@ -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, 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, cloudgpu, api-route, orcarouter, atlascloud, # 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`, `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`, `cloudgpu`, `api-route`, `orcarouter`, `atlascloud`, `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`, `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`, `cloudgpu`, `orcarouter`, `atlascloud`, `ollama`, and any custom provider using the OpenAI API), `provider_opts.http_headers` adds arbitrary HTTP headers to every outgoing request: diff --git a/docs/data/nav.yml b/docs/data/nav.yml index 66970a059..b165f68ad 100644 --- a/docs/data/nav.yml +++ b/docs/data/nav.yml @@ -237,6 +237,8 @@ url: /providers/ovhcloud/ - title: Runcrate url: /providers/runcrate/ + - title: CloudGPU + url: /providers/cloudgpu/ - title: Together AI url: /providers/together/ - title: Vercel AI Gateway diff --git a/docs/providers/cloudgpu/index.md b/docs/providers/cloudgpu/index.md new file mode 100644 index 000000000..d0316a17b --- /dev/null +++ b/docs/providers/cloudgpu/index.md @@ -0,0 +1,110 @@ +--- +title: "CloudGPU" +description: "Use CloudGPU models with Docker Agent." +keywords: docker agent, ai agents, model providers, llm, cloudgpu +weight: 25 +canonical: https://docs.docker.com/ai/docker-agent/providers/cloudgpu/ +--- + +_Use CloudGPU models with Docker Agent._ + +## Overview + +[CloudGPU](https://cloudgpu.app/api?utm_source=github&utm_medium=directory&utm_campaign=202611_seg04_codingagent&utm_content=github_docker_agent_provider) +rents cloud GPUs and serves DeepSeek, Kimi, GLM, MiniMax and other models +through an OpenAI-compatible API. Docker Agent includes built-in support for +CloudGPU as an alias provider. + +## 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. +``` + +## Available Models + +Some chat model IDs CloudGPU serves: + +| Model ID | Model | +| --- | --- | +| `deepseek-v4.1-flash` | DeepSeek V4.1 Flash (default) | +| `kimi-k2.6` | Kimi K2.6 | +| `glm-5.3-flash` | GLM-5.3 Flash | +| `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. + +CloudGPU is not in the models.dev catalog. Docker Agent does not import metadata +from CloudGPU's model list, so it has no catalog-derived pricing or context limits +for these models. Attachment capabilities conservatively fall back to text-only; +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..capabilities` to override detection. See +[Attachment Capability Overrides](../../configuration/models/index.md#attachment-capability-overrides) +for all supported flags. + +## How It Works + +CloudGPU is implemented as 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 model chat templates reject multiple leading system messages, so Docker +Agent coalesces its per-source system messages into one for CloudGPU. + +## 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 +``` diff --git a/docs/providers/overview/index.md b/docs/providers/overview/index.md index 154bc4dda..266d2af2f 100644 --- a/docs/providers/overview/index.md +++ b/docs/providers/overview/index.md @@ -72,6 +72,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) | diff --git a/examples/README.md b/examples/README.md index c58b94644..09e67e05e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -214,6 +214,7 @@ remote MCP endpoints. | [`orcarouter.yaml`](orcarouter.yaml) | OrcaRouter multi-model gateway provider. | | [`ovhcloud.yaml`](ovhcloud.yaml) | OVHcloud AI Endpoints provider. | | [`runcrate.yaml`](runcrate.yaml) | Runcrate open-model host (`runcrate`). | +| [`cloudgpu.yaml`](cloudgpu.yaml) | CloudGPU OpenAI-compatible model API (`cloudgpu`). | | [`groq.yaml`](groq.yaml) | Groq fast-inference provider. | | [`fireworks.yaml`](fireworks.yaml) | Fireworks AI open-model inference (`fireworks-ai`). | | [`deepseek.yaml`](deepseek.yaml) | DeepSeek chat and reasoning provider. | diff --git a/examples/cloudgpu.yaml b/examples/cloudgpu.yaml new file mode 100644 index 000000000..dcced7c05 --- /dev/null +++ b/examples/cloudgpu.yaml @@ -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 diff --git a/pkg/config/auto.go b/pkg/config/auto.go index 195bf1506..f9da17f1a 100644 --- a/pkg/config/auto.go +++ b/pkg/config/auto.go @@ -67,6 +67,7 @@ var cloudProviders = []providerConfig{ {"atlascloud", []string{"ATLASCLOUD_API_KEY"}, "ATLASCLOUD_API_KEY", "ATLASCLOUD_API_KEY"}, {"opper", []string{"OPPER_API_KEY"}, "OPPER_API_KEY", "OPPER_API_KEY"}, {"runcrate", []string{"RUNCRATE_API_KEY"}, "RUNCRATE_API_KEY", "RUNCRATE_API_KEY"}, + {"cloudgpu", []string{"CLOUDGPU_API_KEY"}, "CLOUDGPU_API_KEY", "CLOUDGPU_API_KEY"}, {"baseten", []string{"BASETEN_API_KEY"}, "BASETEN_API_KEY", "BASETEN_API_KEY"}, {"ovhcloud", []string{"OVH_AI_ENDPOINTS_ACCESS_TOKEN"}, "OVH_AI_ENDPOINTS_ACCESS_TOKEN", "OVH_AI_ENDPOINTS_ACCESS_TOKEN"}, {"daoxe", []string{"DAOXE_API_KEY"}, "DAOXE_API_KEY", "DAOXE_API_KEY"}, @@ -169,6 +170,7 @@ var DefaultModels = map[string]string{ "atlascloud": "qwen/qwen3.8-max", "opper": "claude-sonnet-4-6", "runcrate": "deepseek-ai/DeepSeek-V4.1-Flash", + "cloudgpu": "deepseek-v4.1-flash", "baseten": "deepseek-ai/DeepSeek-V4-Pro-0813", "ovhcloud": "Qwen3.5-397B-A17B", "daoxe": "claude-sonnet-4-6", diff --git a/pkg/config/auto_test.go b/pkg/config/auto_test.go index 767083232..531aa7a05 100644 --- a/pkg/config/auto_test.go +++ b/pkg/config/auto_test.go @@ -109,6 +109,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{ @@ -375,6 +382,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: "orcarouter provider", envVars: map[string]string{ diff --git a/pkg/config/examples_test.go b/pkg/config/examples_test.go index a3da240bf..de98a6086 100644 --- a/pkg/config/examples_test.go +++ b/pkg/config/examples_test.go @@ -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. "atlascloud": true, // Atlas Cloud 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. + "cloudgpu": true, // CloudGPU 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) "cloudflare-ai-gateway": true, // multi-provider router; example model ids use the gateway's provider/model form, not guaranteed to match a models.dev id diff --git a/pkg/model/provider/aliases.go b/pkg/model/provider/aliases.go index aec856a36..ac0c0b22c 100644 --- a/pkg/model/provider/aliases.go +++ b/pkg/model/provider/aliases.go @@ -75,6 +75,11 @@ var Aliases = map[string]Alias{ BaseURL: "https://api.runcrate.ai/v1", TokenEnvVar: "RUNCRATE_API_KEY", }, + "cloudgpu": { + APIType: "openai", + BaseURL: "https://cloudgpu.app/v1", + TokenEnvVar: "CLOUDGPU_API_KEY", + }, "orcarouter": { APIType: "openai", BaseURL: "https://api.orcarouter.ai/v1", diff --git a/pkg/model/provider/aliases_test.go b/pkg/model/provider/aliases_test.go index 85a91a72e..1fd66c462 100644 --- a/pkg/model/provider/aliases_test.go +++ b/pkg/model/provider/aliases_test.go @@ -43,6 +43,7 @@ func TestCatalogAliases(t *testing.T) { "orcarouter": {APIType: "openai", BaseURL: "https://api.orcarouter.ai/v1", TokenEnvVar: "ORCAROUTER_API_KEY"}, "atlascloud": {APIType: "openai", BaseURL: "https://api.atlascloud.ai/v1", TokenEnvVar: "ATLASCLOUD_API_KEY"}, "runcrate": {APIType: "openai", BaseURL: "https://api.runcrate.ai/v1", TokenEnvVar: "RUNCRATE_API_KEY"}, + "cloudgpu": {APIType: "openai", BaseURL: "https://cloudgpu.app/v1", TokenEnvVar: "CLOUDGPU_API_KEY"}, "opper": {APIType: "openai", BaseURL: "https://api.opper.ai/v3/compat", TokenEnvVar: "OPPER_API_KEY"}, "baseten": {APIType: "openai", BaseURL: "https://inference.baseten.co/v1", TokenEnvVar: "BASETEN_API_KEY"}, "daoxe": {APIType: "openai", BaseURL: "https://api.daoxe.com/v1", TokenEnvVar: "DAOXE_API_KEY"}, @@ -135,6 +136,7 @@ func TestProviderIDsMatchEmbeddedCatalog(t *testing.T) { "atlascloud": "model IDs come from Atlas Cloud's /v1/models endpoint, not models.dev", "chatgpt": "subscription backend, distinct from OpenAI", "runcrate": "model IDs come from Runcrate's /v1/models endpoint, not models.dev", + "cloudgpu": "model IDs come from CloudGPU's /v1/models endpoint, not models.dev", "dmr": "local Docker Model Runner", "ollama": "local Ollama server", } diff --git a/pkg/model/provider/openai/client.go b/pkg/model/provider/openai/client.go index f4f5a907c..ab5d4b231 100644 --- a/pkg/model/provider/openai/client.go +++ b/pkg/model/provider/openai/client.go @@ -283,6 +283,7 @@ var openModelHostProviders = map[string]bool{ "openrouter": true, "opper": true, "runcrate": true, + "cloudgpu": true, "orcarouter": true, "nebius": true, "nvidia": true, diff --git a/pkg/model/provider/openai/system_message_merge_test.go b/pkg/model/provider/openai/system_message_merge_test.go index c3773b4a9..7cfd80b10 100644 --- a/pkg/model/provider/openai/system_message_merge_test.go +++ b/pkg/model/provider/openai/system_message_merge_test.go @@ -75,6 +75,16 @@ func TestRuncrate_MergesConsecutiveSystemMessages(t *testing.T) { }) } +func TestCloudGPU_MergesConsecutiveSystemMessages(t *testing.T) { + t.Parallel() + + assertMergesConsecutiveMessages(t, &latest.ModelConfig{ + Provider: "cloudgpu", + Model: "deepseek-v4.1-flash", + TokenKey: "MY_TOKEN", + }) +} + func TestBaseten_MergesConsecutiveSystemMessages(t *testing.T) { t.Parallel() @@ -204,6 +214,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}, diff --git a/pkg/model/provider/openai_alias_providers_test.go b/pkg/model/provider/openai_alias_providers_test.go index 845999bea..05e14793f 100644 --- a/pkg/model/provider/openai_alias_providers_test.go +++ b/pkg/model/provider/openai_alias_providers_test.go @@ -89,6 +89,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",