Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agent-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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, api-route, 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, api-route, 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",
Expand Down
6 changes: 3 additions & 3 deletions docs/configuration/models/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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, api-route, 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, api-route, atlascloud,
# azure, ollama, github-copilot, or a named provider defined
# under the top-level `providers:` section.
model: string # Required: model identifier
Expand Down Expand Up @@ -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`, `api-route`, `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`, `api-route`, `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. |
Expand Down Expand Up @@ -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`, `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`, `atlascloud`, `ollama`, and any custom provider using the OpenAI API),
`provider_opts.http_headers` adds arbitrary HTTP headers to every outgoing
request:

Expand Down
2 changes: 2 additions & 0 deletions docs/data/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,8 @@
url: /providers/opencode-go/
- title: OpenCode Zen
url: /providers/opencode-zen/
- title: Opper
url: /providers/opper/
- title: OpenRouter
url: /providers/openrouter/
- title: OVHcloud
Expand Down
69 changes: 69 additions & 0 deletions docs/providers/opper/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
title: "Opper"
description: "Use Opper models with Docker Agent."
keywords: docker agent, ai agents, model providers, llm, opper
weight: 225
canonical: https://docs.docker.com/ai/docker-agent/providers/opper/
---

_Use Opper models with Docker Agent._

## Overview

[Opper](https://opper.ai) is an EU-hosted AI gateway that serves models from
many providers behind one OpenAI-compatible endpoint, with one API key.
Docker Agent includes built-in support for Opper as an alias provider.

## Setup

1. Create an API key at [platform.opper.ai](https://platform.opper.ai).
2. Set the environment variable:

```bash
export OPPER_API_KEY=your-api-key
```

## Usage

### Inline Syntax

```yaml
agents:
root:
model: opper/claude-sonnet-4-6
description: Assistant using Opper
instruction: You are a helpful assistant.
```

### Named Model

```yaml
models:
opper_model:
provider: opper
model: claude-sonnet-4-6
temperature: 0.7
max_tokens: 8192

agents:
root:
model: opper_model
description: Assistant using Opper
instruction: You are a helpful assistant.
```

## Available Models

Opper model IDs come in two forms. A bare pool name such as
`claude-sonnet-4-6` or `gpt-5.4-mini` lets Opper pick a provider for each
request. A `provider/model` ID such as `anthropic/claude-sonnet-4-6` pins one
route. List the model IDs your key can call with:

```bash
curl https://api.opper.ai/v3/compat/models \
-H "Authorization: Bearer $OPPER_API_KEY"
```

The public catalogue is also available without a key at
`https://api.opper.ai/v3/models`. Docker Agent's default for Opper is
`claude-sonnet-4-6`.
1 change: 1 addition & 0 deletions docs/providers/overview/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Use this table to find a built-in provider's config key and authentication metho
| Cloudflare AI Gateway | `cloudflare-ai-gateway` | `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` + `CLOUDFLARE_GATEWAY_ID` |
| Requesty | `requesty` | `REQUESTY_API_KEY` |
| OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
| Opper | `opper` | `OPPER_API_KEY` |
| API Route | `api-route` | `API_ROUTE_API_KEY` |
| Atlas Cloud | [`atlascloud`](../atlascloud/index.md) | `ATLASCLOUD_API_KEY` |
| Azure OpenAI | `azure` | `AZURE_API_KEY` + `base_url` (override the key with `token_key`) |
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ remote MCP endpoints.
| [`atlascloud.yaml`](atlascloud.yaml) | Atlas Cloud open-model host (`atlascloud`). |
| [`baseten.yaml`](baseten.yaml) | Baseten cloud provider. |
| [`daoxe.yaml`](daoxe.yaml) | DaoXE multi-model gateway provider. |
| [`opper.yaml`](opper.yaml) | Opper 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 (`fireworks-ai`). |
Expand Down
17 changes: 17 additions & 0 deletions examples/opper.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# yaml-language-server: $schema=../agent-schema.json

models:
opper_model:
provider: opper
model: claude-sonnet-4-6

agents:
root:
model: opper_model
description: Assistant using Opper
instruction: |
You are a helpful assistant.
toolsets:
- type: filesystem
- type: shell
- type: think
2 changes: 2 additions & 0 deletions pkg/config/auto.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ var cloudProviders = []providerConfig{
{"openrouter", []string{"OPENROUTER_API_KEY"}, "OPENROUTER_API_KEY", "OPENROUTER_API_KEY"},
{"api-route", []string{"API_ROUTE_API_KEY"}, "API_ROUTE_API_KEY", "API_ROUTE_API_KEY"},
{"atlascloud", []string{"ATLASCLOUD_API_KEY"}, "ATLASCLOUD_API_KEY", "ATLASCLOUD_API_KEY"},
{"opper", []string{"OPPER_API_KEY"}, "OPPER_API_KEY", "OPPER_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"},
Expand Down Expand Up @@ -163,6 +164,7 @@ var DefaultModels = map[string]string{
"openrouter": "meta-llama/llama-4-maverick",
"api-route": "gpt-6.1-sol",
"atlascloud": "qwen/qwen3.8-max",
"opper": "claude-sonnet-4-6",
"baseten": "deepseek-ai/DeepSeek-V4-Pro",
"ovhcloud": "Qwen3.5-397B-A17B",
"daoxe": "claude-sonnet-4-6",
Expand Down
16 changes: 16 additions & 0 deletions pkg/config/auto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ func TestAvailableProviders_NoGateway(t *testing.T) {
},
expectedProvider: "atlascloud",
},
{
name: "opper api key present",
envVars: map[string]string{
"OPPER_API_KEY": "test-key",
},
expectedProvider: "opper",
},
{
name: "baseten api key present",
envVars: map[string]string{
Expand Down Expand Up @@ -336,6 +343,15 @@ func TestAutoModelConfig(t *testing.T) {
expectedModel: "gpt-6.1-sol",
expectedMaxTokens: 32000,
},
{
name: "opper provider",
envVars: map[string]string{
"OPPER_API_KEY": "test-key",
},
expectedProvider: "opper",
expectedModel: "claude-sonnet-4-6",
expectedMaxTokens: 32000,
},
{
name: "baseten provider",
envVars: map[string]string{
Expand Down
5 changes: 5 additions & 0 deletions pkg/model/provider/aliases.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ var Aliases = map[string]Alias{
BaseURL: "https://api.atlascloud.ai/v1",
TokenEnvVar: "ATLASCLOUD_API_KEY",
},
"opper": {
APIType: "openai",
BaseURL: "https://api.opper.ai/v3/compat",
TokenEnvVar: "OPPER_API_KEY",
},
"mistral": {
APIType: "openai",
BaseURL: "https://api.mistral.ai/v1",
Expand Down
1 change: 1 addition & 0 deletions pkg/model/provider/aliases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func TestCatalogAliases(t *testing.T) {
"openrouter": {APIType: "openai", BaseURL: "https://openrouter.ai/api/v1", TokenEnvVar: "OPENROUTER_API_KEY"},
"api-route": {APIType: "openai", BaseURL: "https://global.api-route.com/v1", TokenEnvVar: "API_ROUTE_API_KEY"},
"atlascloud": {APIType: "openai", BaseURL: "https://api.atlascloud.ai/v1", TokenEnvVar: "ATLASCLOUD_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"},
"ovhcloud": {APIType: "openai", BaseURL: "https://oai.endpoints.kepler.ai.cloud.ovh.net/v1", TokenEnvVar: "OVH_AI_ENDPOINTS_ACCESS_TOKEN"},
Expand Down
1 change: 1 addition & 0 deletions pkg/model/provider/openai/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ var openModelHostProviders = map[string]bool{
"daoxe": true,
"ovhcloud": true,
"openrouter": true,
"opper": true,
"nebius": true,
"nvidia": true,
"cerebras": true,
Expand Down
11 changes: 11 additions & 0 deletions pkg/model/provider/openai/system_message_merge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ func TestDaoxe_MergesConsecutiveSystemMessages(t *testing.T) {
})
}

func TestOpper_MergesConsecutiveSystemMessages(t *testing.T) {
t.Parallel()

assertMergesConsecutiveMessages(t, &latest.ModelConfig{
Provider: "opper",
Model: "claude-sonnet-4-6",
TokenKey: "MY_TOKEN",
})
}

func TestBaseten_MergesConsecutiveSystemMessages(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -172,6 +182,7 @@ func TestShouldMergeConsecutiveMessages_Gating(t *testing.T) {
{"api-route, no base_url", &latest.ModelConfig{Provider: "api-route", Model: "gpt-6.1-sol"}, true},
{"baseten", &latest.ModelConfig{Provider: "baseten", Model: "zai-org/GLM-5.2"}, true},
{"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},
{"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},
Expand Down
Loading