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 @@ -182,7 +182,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, 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, ovhcloud, groq, deepseek, etc.).",
"examples": [
"openai",
"anthropic",
Expand Down
2 changes: 2 additions & 0 deletions docs/_data/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@
url: /providers/ovhcloud/
- title: Groq
url: /providers/groq/
- title: DeepSeek
url: /providers/deepseek/
- title: MiniMax
url: /providers/minimax/
- title: OpenRouter
Expand Down
1 change: 1 addition & 0 deletions docs/concepts/models/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ for details.
| Baseten | `baseten` | DeepSeek, Kimi, GLM, Llama models | `BASETEN_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` |
| DeepSeek | `deepseek` | DeepSeek-V3 chat and R1 reasoner | `DEEPSEEK_API_KEY` |
| Requesty | `requesty` | Multi-provider gateway | `REQUESTY_API_KEY` |
| OpenRouter | `openrouter` | Multi-provider gateway | `OPENROUTER_API_KEY` |
| Azure OpenAI | `azure` | gpt-4o, gpt-5 on Azure | `AZURE_API_KEY` + `base_url` |
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 @@ -17,7 +17,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, minimax, baseten, ovhcloud, groq, requesty, openrouter,
# dmr, mistral, xai, nebius, minimax, baseten, ovhcloud, groq, deepseek, requesty, openrouter,
# azure, ollama, github-copilot, or a named provider defined
# under the top-level `providers:` section.
model: string # Required: model identifier
Expand Down Expand Up @@ -48,7 +48,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`, `minimax`, `baseten`, `ovhcloud`, `groq`, `requesty`, `openrouter`, `azure`, `ollama`, `github-copilot`, or any [named provider]({{ '/providers/custom/' | relative_url }}). |
| `provider` | string | ✓/✗ | Required for regular model definitions; omitted for `first_available` selectors. Provider: `openai`, `anthropic`, `google`, `amazon-bedrock`, `dmr`, `mistral`, `xai`, `nebius`, `minimax`, `baseten`, `ovhcloud`, `groq`, `deepseek`, `requesty`, `openrouter`, `azure`, `ollama`, `github-copilot`, or any [named provider]({{ '/providers/custom/' | relative_url }}). |
| `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`) |
| `temperature` | float | ✗ | Sampling randomness. Range is provider-dependent — typically `0.0–2.0` (Anthropic caps at `1.0`). `0.0` is deterministic. |
| `max_tokens` | int | ✗ | Maximum response length in tokens |
Expand Down Expand Up @@ -404,7 +404,7 @@ See the [Anthropic provider page]({{ '/providers/anthropic/#thinking-display' |
## Custom HTTP Headers

For OpenAI-compatible providers (`openai`, `github-copilot`, `mistral`, `xai`,
`nebius`, `minimax`, `baseten`, `ovhcloud`, `groq`, `requesty`, `openrouter`, `ollama`, and any custom provider using the OpenAI API),
`nebius`, `minimax`, `baseten`, `ovhcloud`, `groq`, `deepseek`, `requesty`, `openrouter`, `ollama`, and any custom provider using the OpenAI API),
`provider_opts.http_headers` adds arbitrary HTTP headers to every outgoing
request:

Expand Down
96 changes: 96 additions & 0 deletions docs/providers/deepseek/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: "DeepSeek"
description: "Use DeepSeek models with docker-agent."
permalink: /providers/deepseek/
---

# DeepSeek

_Use DeepSeek models with docker-agent._

## Overview

[DeepSeek](https://www.deepseek.com/) serves its frontier chat and reasoning
models through an OpenAI-compatible API, with strong price/performance on coding
and reasoning tasks. docker-agent includes built-in support for DeepSeek as an
alias provider.

## Setup

1. Create an API key from the [DeepSeek Platform](https://platform.deepseek.com/api_keys).
2. Set the environment variable:

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

## Usage

### Inline Syntax

The simplest way to use DeepSeek:

```yaml
agents:
root:
model: deepseek/deepseek-chat
description: Assistant using DeepSeek
instruction: You are a helpful assistant.
```

### Named Model

For more control over parameters:

```yaml
models:
deepseek_model:
provider: deepseek
model: deepseek-chat
temperature: 0.7
max_tokens: 8192

agents:
root:
model: deepseek_model
description: Assistant using DeepSeek
instruction: You are a helpful assistant.
```

## Available Models

DeepSeek exposes a small, vendor-controlled model lineup. Check the
[DeepSeek models documentation](https://api-docs.deepseek.com/quick_start/pricing)
for current model IDs, context limits, and pricing.

| Model | Description |
| --- | --- |
| `deepseek-chat` | DeepSeek-V3, general-purpose chat and tool calling |
| `deepseek-reasoner` | DeepSeek-R1, extended-reasoning model |

> Model IDs are case-sensitive and must be passed exactly as the catalogue lists
> them.

## How It Works

DeepSeek is implemented as a built-in alias in docker-agent:

- **API Type:** OpenAI-compatible (`openai_chatcompletions`)
- **Base URL:** `https://api.deepseek.com/v1`
- **Token Variable:** `DEEPSEEK_API_KEY`

## Example: Code Assistant

```yaml
agents:
coder:
model: deepseek/deepseek-chat
description: Code assistant using DeepSeek-V3
instruction: |
You are an expert programmer.
Write clean, well-documented code and follow language best practices.
toolsets:
- type: filesystem
- type: shell
- type: think
```
1 change: 1 addition & 0 deletions docs/providers/overview/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ docker-agent also includes built-in aliases for these providers:
| Baseten | `baseten` | `BASETEN_API_KEY` |
| OVHcloud | `ovhcloud` | `OVH_AI_ENDPOINTS_ACCESS_TOKEN` |
| Groq | `groq` | `GROQ_API_KEY` |
| DeepSeek | `deepseek` | `DEEPSEEK_API_KEY` |
| Requesty | `requesty` | `REQUESTY_API_KEY` |
| OpenRouter | `openrouter` | `OPENROUTER_API_KEY` |
| Azure OpenAI | `azure` | `AZURE_API_KEY` + `base_url` |
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ remote MCP endpoints.
| [`baseten.yaml`](baseten.yaml) | Baseten cloud provider. |
| [`ovhcloud.yaml`](ovhcloud.yaml) | OVHcloud AI Endpoints provider. |
| [`groq.yaml`](groq.yaml) | Groq fast-inference provider. |
| [`deepseek.yaml`](deepseek.yaml) | DeepSeek chat and reasoning provider. |
| [`grok.yaml`](grok.yaml) | xAI Grok model. |
| [`github-copilot.yaml`](github-copilot.yaml) | GitHub Copilot models via OAuth device-flow. |
| [`fallback_models.yaml`](fallback_models.yaml) | Automatic fallback to a secondary model when the primary fails. |
Expand Down
17 changes: 17 additions & 0 deletions examples/deepseek.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# yaml-language-server: $schema=../agent-schema.json

models:
deepseek_model:
provider: deepseek
model: deepseek-chat

agents:
root:
model: deepseek_model
description: Assistant using DeepSeek
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 @@ -47,6 +47,7 @@ var cloudProviders = []providerConfig{
{"baseten", []string{"BASETEN_API_KEY"}, "BASETEN_API_KEY"},
{"ovhcloud", []string{"OVH_AI_ENDPOINTS_ACCESS_TOKEN"}, "OVH_AI_ENDPOINTS_ACCESS_TOKEN"},
{"groq", []string{"GROQ_API_KEY"}, "GROQ_API_KEY"},
{"deepseek", []string{"DEEPSEEK_API_KEY"}, "DEEPSEEK_API_KEY"},
{"amazon-bedrock", []string{
"AWS_BEARER_TOKEN_BEDROCK",
"AWS_ACCESS_KEY_ID",
Expand Down Expand Up @@ -113,6 +114,7 @@ var DefaultModels = map[string]string{
"baseten": "deepseek-ai/DeepSeek-V3.1",
"ovhcloud": "Qwen3.5-397B-A17B",
"groq": "llama-3.3-70b-versatile",
"deepseek": "deepseek-chat",
"amazon-bedrock": "global.anthropic.claude-sonnet-4-5-20250929-v1:0",
"opencode-go": "deepseek-v4-flash",
"opencode-zen": "deepseek-v4-flash-free",
Expand Down
37 changes: 32 additions & 5 deletions pkg/config/auto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,13 @@ func TestAvailableProviders_NoGateway(t *testing.T) {
},
expectedProvider: "groq",
},
{
name: "deepseek api key present",
envVars: map[string]string{
"DEEPSEEK_API_KEY": "test-key",
},
expectedProvider: "deepseek",
},
{
name: "no api keys - defaults to dmr",
envVars: map[string]string{},
Expand Down Expand Up @@ -265,6 +272,15 @@ func TestAutoModelConfig(t *testing.T) {
expectedModel: "llama-3.3-70b-versatile",
expectedMaxTokens: 32000,
},
{
name: "deepseek provider",
envVars: map[string]string{
"DEEPSEEK_API_KEY": "test-key",
},
expectedProvider: "deepseek",
expectedModel: "deepseek-chat",
expectedMaxTokens: 32000,
},
{
name: "dmr provider (no api keys)",
envVars: map[string]string{},
Expand Down Expand Up @@ -347,7 +363,7 @@ func TestDefaultModels(t *testing.T) {
t.Parallel()

// Test that DefaultModels map has all expected providers
expectedProviders := []string{"openai", "anthropic", "google", "dmr", "mistral", "openrouter", "baseten", "ovhcloud", "groq", "amazon-bedrock", "opencode-zen", "opencode-go"}
expectedProviders := []string{"openai", "anthropic", "google", "dmr", "mistral", "openrouter", "baseten", "ovhcloud", "groq", "deepseek", "amazon-bedrock", "opencode-zen", "opencode-go"}

for _, provider := range expectedProviders {
t.Run(provider, func(t *testing.T) {
Expand All @@ -367,6 +383,7 @@ func TestDefaultModels(t *testing.T) {
assert.Equal(t, "deepseek-ai/DeepSeek-V3.1", DefaultModels["baseten"])
assert.Equal(t, "Qwen3.5-397B-A17B", DefaultModels["ovhcloud"])
assert.Equal(t, "llama-3.3-70b-versatile", DefaultModels["groq"])
assert.Equal(t, "deepseek-chat", DefaultModels["deepseek"])
assert.Equal(t, "global.anthropic.claude-sonnet-4-5-20250929-v1:0", DefaultModels["amazon-bedrock"])
assert.Equal(t, "deepseek-v4-flash", DefaultModels["opencode-go"])
assert.Equal(t, "deepseek-v4-flash-free", DefaultModels["opencode-zen"])
Expand All @@ -376,7 +393,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", "baseten", "ovhcloud", "groq", "opencode-zen"}
providers := []string{"openai", "anthropic", "google", "mistral", "openrouter", "baseten", "ovhcloud", "groq", "deepseek", "opencode-zen"}

for _, provider := range providers {
t.Run(provider, func(t *testing.T) {
Expand All @@ -402,6 +419,8 @@ func TestAutoModelConfig_IntegrationWithDefaultModels(t *testing.T) {
envVars["OVH_AI_ENDPOINTS_ACCESS_TOKEN"] = "test-token"
case "groq":
envVars["GROQ_API_KEY"] = "test-key"
case "deepseek":
envVars["DEEPSEEK_API_KEY"] = "test-key"
case "opencode-zen":
envVars["OPENCODE_API_KEY"] = "test-key"
}
Expand Down Expand Up @@ -523,14 +542,22 @@ func TestAvailableProviders_PrecedenceOrder(t *testing.T) {
providers = AvailableProviders(t.Context(), "", env)
assert.Equal(t, "ovhcloud", providers[0])

// groq wins over amazon-bedrock
// groq wins over deepseek
env = environment.NewMapEnvProvider(map[string]string{
"GROQ_API_KEY": "test-key",
"AWS_ACCESS_KEY_ID": "test-key",
"GROQ_API_KEY": "test-key",
"DEEPSEEK_API_KEY": "test-key",
})
providers = AvailableProviders(t.Context(), "", env)
assert.Equal(t, "groq", providers[0])

// deepseek wins over amazon-bedrock
env = environment.NewMapEnvProvider(map[string]string{
"DEEPSEEK_API_KEY": "test-key",
"AWS_ACCESS_KEY_ID": "test-key",
})
providers = AvailableProviders(t.Context(), "", env)
assert.Equal(t, "deepseek", providers[0])

// Only OPENCODE_API_KEY set - opencode-zen should win (higher priority than opencode-go)
env = environment.NewMapEnvProvider(map[string]string{
"OPENCODE_API_KEY": "test-key",
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 @@ -83,6 +83,11 @@ var Aliases = map[string]Alias{
BaseURL: "https://api.groq.com/openai/v1",
TokenEnvVar: "GROQ_API_KEY",
},
"deepseek": {
APIType: "openai",
BaseURL: "https://api.deepseek.com/v1",
TokenEnvVar: "DEEPSEEK_API_KEY",
},
"github-copilot": {
APIType: "openai",
BaseURL: "https://api.githubcopilot.com",
Expand Down
14 changes: 14 additions & 0 deletions pkg/model/provider/aliases_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ func TestGroqAlias(t *testing.T) {
assert.True(t, IsCatalogProvider("groq"))
}

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

alias, ok := LookupAlias("deepseek")
require.True(t, ok)
assert.Equal(t, Alias{
APIType: "openai",
BaseURL: "https://api.deepseek.com/v1",
TokenEnvVar: "DEEPSEEK_API_KEY",
}, alias)
assert.True(t, IsKnownProvider("deepseek"))
assert.True(t, IsCatalogProvider("deepseek"))
}

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

Expand Down
Loading
Loading