diff --git a/agent-schema.json b/agent-schema.json index 3194d4d081..b2dcd47522 100644 --- a/agent-schema.json +++ b/agent-schema.json @@ -214,7 +214,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, azure, xai, ollama, mistral, baseten, ovhcloud, groq, fireworks, deepseek, cerebras, together, huggingface, moonshot, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, nvidia, github-copilot, chatgpt, 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, azure, xai, ollama, mistral, baseten, daoxe, ovhcloud, groq, fireworks, deepseek, cerebras, together, huggingface, moonshot, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, nvidia, github-copilot, chatgpt, etc.).", "examples": [ "openai", "anthropic", diff --git a/docs/concepts/models/index.md b/docs/concepts/models/index.md index e12fb5fd54..8cb8f242c7 100644 --- a/docs/concepts/models/index.md +++ b/docs/concepts/models/index.md @@ -83,6 +83,7 @@ for details. | NVIDIA NIM | `nvidia` | Nemotron, Llama, Qwen, DeepSeek (open models) | `NVIDIA_API_KEY` | | MiniMax | `minimax` | MiniMax models | `MINIMAX_API_KEY` | | Baseten | `baseten` | DeepSeek, Kimi, GLM, Llama models | `BASETEN_API_KEY` | +| DaoXE | `daoxe` | Multi-model gateway (OpenAI-compatible) | `DAOXE_API_KEY` | | OVHcloud | `ovhcloud` | Qwen, Llama, Mistral, DeepSeek (EU-hosted) | `OVH_AI_ENDPOINTS_ACCESS_TOKEN` | | Groq | `groq` | Llama, Qwen, GPT-OSS (fast inference) | `GROQ_API_KEY` | | Fireworks AI | `fireworks` | Kimi, Llama, Qwen, DeepSeek, GLM (open models) | `FIREWORKS_API_KEY` | diff --git a/docs/configuration/models/index.md b/docs/configuration/models/index.md index 7e7656c1e8..50e59b9654 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, ovhcloud, groq, fireworks, deepseek, cerebras, together, huggingface, moonshot, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, requesty, openrouter, + # dmr, mistral, xai, nebius, nvidia, minimax, baseten, daoxe, ovhcloud, groq, fireworks, deepseek, cerebras, together, huggingface, moonshot, vercel, cloudflare-workers-ai, cloudflare-ai-gateway, requesty, openrouter, # 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`, `ovhcloud`, `groq`, `fireworks`, `deepseek`, `cerebras`, `together`, `huggingface`, `moonshot`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `azure`, `ollama`, `github-copilot`, `chatgpt`, 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`, `deepseek`, `cerebras`, `together`, `huggingface`, `moonshot`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `azure`, `ollama`, `github-copilot`, `chatgpt`, 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. | @@ -591,7 +591,7 @@ See the [Anthropic provider page](../../providers/anthropic/index.md#thinking-di ## Custom HTTP Headers For OpenAI-compatible providers (`openai`, `github-copilot`, `mistral`, `xai`, -`nebius`, `nvidia`, `minimax`, `baseten`, `ovhcloud`, `groq`, `fireworks`, `deepseek`, `cerebras`, `together`, `huggingface`, `moonshot`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `ollama`, and any custom provider using the OpenAI API), +`nebius`, `nvidia`, `minimax`, `baseten`, `daoxe`, `ovhcloud`, `groq`, `fireworks`, `deepseek`, `cerebras`, `together`, `huggingface`, `moonshot`, `vercel`, `cloudflare-workers-ai`, `cloudflare-ai-gateway`, `requesty`, `openrouter`, `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 88e362a4db..99fa3145d9 100644 --- a/docs/data/nav.yml +++ b/docs/data/nav.yml @@ -177,6 +177,8 @@ url: /providers/cloudflare-workers-ai/ - title: ChatGPT url: /providers/chatgpt/ + - title: DaoXE + url: /providers/daoxe/ - title: DeepSeek url: /providers/deepseek/ - title: Docker Model Runner diff --git a/docs/providers/daoxe/index.md b/docs/providers/daoxe/index.md new file mode 100644 index 0000000000..5e72e059c4 --- /dev/null +++ b/docs/providers/daoxe/index.md @@ -0,0 +1,66 @@ +--- +title: "DaoXE" +description: "Use DaoXE models with Docker Agent." +keywords: docker agent, ai agents, model providers, llm, daoxe +weight: 245 +canonical: https://docs.docker.com/ai/docker-agent/providers/daoxe/ +--- + +_Use DaoXE models with Docker Agent._ + +## Overview + +[DaoXE](https://daoxe.com) is a multi-model LLM gateway that serves models from +multiple vendors behind one OpenAI-compatible endpoint. Docker Agent includes +built-in support for DaoXE as an alias provider. + +## Setup + +1. Create an API key from your DaoXE account dashboard. +2. Set the environment variable: + + ```bash + export DAOXE_API_KEY=your-api-key + ``` + +## Usage + +### Inline Syntax + +```yaml +agents: + root: + model: daoxe/ + description: Assistant using DaoXE + instruction: You are a helpful assistant. +``` + +### Named Model + +```yaml +models: + daoxe_model: + provider: daoxe + model: + temperature: 0.7 + max_tokens: 8192 + +agents: + root: + model: daoxe_model + description: Assistant using DaoXE + instruction: You are a helpful assistant. +``` + +## Available Models + +DaoXE's catalog is account-scoped and changes over time: new models appear as +upstream vendors release them. List the model IDs your account can call with: + +```bash +curl https://api.daoxe.com/v1/models \ + -H "Authorization: Bearer $DAOXE_API_KEY" +``` + +Use any ID from that response as the `model` value. Docker Agent's default for +DaoXE is `claude-sonnet-4-6`. diff --git a/docs/providers/overview/index.md b/docs/providers/overview/index.md index a7a048f1f3..fe4308b408 100644 --- a/docs/providers/overview/index.md +++ b/docs/providers/overview/index.md @@ -47,6 +47,7 @@ Docker Agent also includes built-in aliases for these providers: | NVIDIA NIM | `nvidia` | `NVIDIA_API_KEY` | | MiniMax | `minimax` | `MINIMAX_API_KEY` | | Baseten | `baseten` | `BASETEN_API_KEY` | +| DaoXE | `daoxe` | `DAOXE_API_KEY` | | OVHcloud | `ovhcloud` | `OVH_AI_ENDPOINTS_ACCESS_TOKEN` | | Groq | `groq` | `GROQ_API_KEY` | | Fireworks AI | `fireworks` | `FIREWORKS_API_KEY` | diff --git a/examples/README.md b/examples/README.md index a5b8ad5666..af3c6a30fa 100644 --- a/examples/README.md +++ b/examples/README.md @@ -197,6 +197,7 @@ remote MCP endpoints. | [`model_env_substitution.yaml`](model_env_substitution.yaml) | `${env.VAR}` substitution in a model's `model` / `base_url`. | | [`nebius.yaml`](nebius.yaml) | Nebius cloud provider. | | [`baseten.yaml`](baseten.yaml) | Baseten cloud provider. | +| [`daoxe.yaml`](daoxe.yaml) | DaoXE multi-model gateway provider. | | [`ovhcloud.yaml`](ovhcloud.yaml) | OVHcloud AI Endpoints provider. | | [`groq.yaml`](groq.yaml) | Groq fast-inference provider. | | [`fireworks.yaml`](fireworks.yaml) | Fireworks AI open-model inference provider. | diff --git a/examples/daoxe.yaml b/examples/daoxe.yaml new file mode 100644 index 0000000000..4ab1c96c6c --- /dev/null +++ b/examples/daoxe.yaml @@ -0,0 +1,17 @@ +# yaml-language-server: $schema=../agent-schema.json + +models: + daoxe_model: + provider: daoxe + model: claude-sonnet-4-6 + +agents: + root: + model: daoxe_model + description: Assistant using DaoXE + 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 cc16f7babc..09b1c9f113 100644 --- a/pkg/config/auto.go +++ b/pkg/config/auto.go @@ -63,6 +63,7 @@ var cloudProviders = []providerConfig{ {"openrouter", []string{"OPENROUTER_API_KEY"}, "OPENROUTER_API_KEY", "OPENROUTER_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"}, {"groq", []string{"GROQ_API_KEY"}, "GROQ_API_KEY", "GROQ_API_KEY"}, {"fireworks", []string{"FIREWORKS_API_KEY"}, "FIREWORKS_API_KEY", "FIREWORKS_API_KEY"}, {"deepseek", []string{"DEEPSEEK_API_KEY"}, "DEEPSEEK_API_KEY", "DEEPSEEK_API_KEY"}, @@ -159,6 +160,7 @@ var DefaultModels = map[string]string{ "openrouter": "meta-llama/llama-4-maverick", "baseten": "deepseek-ai/DeepSeek-V4-Pro", "ovhcloud": "Qwen3.5-397B-A17B", + "daoxe": "claude-sonnet-4-6", "groq": "llama-3.3-70b-versatile", "fireworks": "accounts/fireworks/models/kimi-k3", "deepseek": "deepseek-v4-pro", diff --git a/pkg/config/auto_test.go b/pkg/config/auto_test.go index f2db1d2988..aa9ee0bd8d 100644 --- a/pkg/config/auto_test.go +++ b/pkg/config/auto_test.go @@ -87,6 +87,13 @@ func TestAvailableProviders_NoGateway(t *testing.T) { }, expectedProvider: "ovhcloud", }, + { + name: "daoxe api key present", + envVars: map[string]string{ + "DAOXE_API_KEY": "test-key", + }, + expectedProvider: "daoxe", + }, { name: "groq api key present", envVars: map[string]string{ @@ -323,6 +330,15 @@ func TestAutoModelConfig(t *testing.T) { expectedModel: "Qwen3.5-397B-A17B", expectedMaxTokens: 32000, }, + { + name: "daoxe provider", + envVars: map[string]string{ + "DAOXE_API_KEY": "test-key", + }, + expectedProvider: "daoxe", + expectedModel: "claude-sonnet-4-6", + expectedMaxTokens: 32000, + }, { name: "groq provider", envVars: map[string]string{ diff --git a/pkg/model/provider/aliases.go b/pkg/model/provider/aliases.go index 49e6123643..265e1bf23c 100644 --- a/pkg/model/provider/aliases.go +++ b/pkg/model/provider/aliases.go @@ -88,6 +88,11 @@ var Aliases = map[string]Alias{ BaseURL: "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1", TokenEnvVar: "OVH_AI_ENDPOINTS_ACCESS_TOKEN", }, + "daoxe": { + APIType: "openai", + BaseURL: "https://api.daoxe.com/v1", + TokenEnvVar: "DAOXE_API_KEY", + }, "groq": { APIType: "openai", BaseURL: "https://api.groq.com/openai/v1", diff --git a/pkg/model/provider/aliases_test.go b/pkg/model/provider/aliases_test.go index e0c48a1b56..6db47f729b 100644 --- a/pkg/model/provider/aliases_test.go +++ b/pkg/model/provider/aliases_test.go @@ -38,6 +38,7 @@ func TestCatalogAliases(t *testing.T) { expected := map[string]Alias{ "openrouter": {APIType: "openai", BaseURL: "https://openrouter.ai/api/v1", TokenEnvVar: "OPENROUTER_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"}, "ovhcloud": {APIType: "openai", BaseURL: "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1", TokenEnvVar: "OVH_AI_ENDPOINTS_ACCESS_TOKEN"}, "groq": {APIType: "openai", BaseURL: "https://api.groq.com/openai/v1", TokenEnvVar: "GROQ_API_KEY"}, "deepseek": {APIType: "openai", BaseURL: "https://api.deepseek.com/v1", TokenEnvVar: "DEEPSEEK_API_KEY"}, diff --git a/pkg/model/provider/openai/client.go b/pkg/model/provider/openai/client.go index 604c56b909..f1bb84352f 100644 --- a/pkg/model/provider/openai/client.go +++ b/pkg/model/provider/openai/client.go @@ -265,6 +265,7 @@ func (c *Client) convertMessages(ctx context.Context, messages []chat.Message) [ // system messages and are deliberately absent so their behavior is unchanged. var openModelHostProviders = map[string]bool{ "baseten": true, + "daoxe": true, "ovhcloud": true, "openrouter": true, "nebius": true, diff --git a/pkg/model/provider/openai/system_message_merge_test.go b/pkg/model/provider/openai/system_message_merge_test.go index ccb962f641..6db0426816 100644 --- a/pkg/model/provider/openai/system_message_merge_test.go +++ b/pkg/model/provider/openai/system_message_merge_test.go @@ -35,6 +35,16 @@ func TestChatCompletions_MergesConsecutiveSystemMessages(t *testing.T) { }) } +func TestDaoxe_MergesConsecutiveSystemMessages(t *testing.T) { + t.Parallel() + + assertMergesConsecutiveMessages(t, &latest.ModelConfig{ + Provider: "daoxe", + Model: "gpt-4o", + TokenKey: "MY_TOKEN", + }) +} + func TestBaseten_MergesConsecutiveSystemMessages(t *testing.T) { t.Parallel()