DEV Community

boluo
boluo

Posted on

DeepSeek Harness: API-Protokoll für externe Modelle wählen und Fehler eingrenzen

Das Problem

Beim Einrichten eines externen Modells in DeepSeek Harness füllt man die API-Adresse aus, fügt den Schlüssel ein, prüft die Modell-ID — und steht dann vor einem Dropdown ohne jede Erklärung: OpenAI Chat Completions, OpenAI Responses, Anthropic Messages.

Wählt man die falsche Option, kommt ein Fehler, der nicht verrät, welche der drei gemeint war. Ein 401 sieht aus wie ein falscher Schlüssel, ein 404 wie eine falsche Adresse, und ein 400 wie ein Tippfehler im Feldnamen.

Dieser Beitrag zeigt, was sich hinter den drei Optionen tatsächlich unterscheidet, wie man sie in drei Schritten auseinanderhält und was bei einem Test am 20. Oktober 2026 herauskam.

Kurzfassung

  • Unklar? OpenAI Chat Completions wählen. Die meisten Anbieter implementieren dieses Format.
  • Der Anbieter bietet nur /v1/messages an, oder es wird ein Claude-natives Werkzeug angebunden: Anthropic Messages.
  • Responses nur dann, wenn nachweislich serverseitige Funktionen wie Kontextspeicherung oder eingebaute Werkzeuge vorhanden sind.

Umgebung

Punkt Wert
Betriebssystem Windows 10 / 11
Client DeepSeek Harness Desktop, Oberfläche Stand Oktober 2026
Gegenstelle beliebiger OpenAI- oder Anthropic-kompatibler Dienst (hier als Beispiel: Crazyrouter)
Basis-URL https://api.crazyrouter.com/v1 — nur bis /v1, den Rest ergänzt der Client
Testdatum 20.10.2026
Modelle deepseek-v4-pro, claude-opus-4-5
Authentifizierung Authorization: Bearer, Schlüssel aus der Umgebungsvariable CRAZYROUTER_API_KEY

Die Protokollauswahl in DeepSeek Harness, Stand Oktober 2026. Das Schlüsselfeld liegt außerhalb des Bildausschnitts.

Was sich wirklich unterscheidet

Die drei Optionen sind keine Stufen („einfach“, „fortgeschritten“, „profi“), sondern drei parallele Nachrichtenformate. Vier Dinge ändern sich:

  • Wer den Kontext hält: Chat Completions und Messages sind zustandslos, der Client sendet den Verlauf bei jeder Anfrage erneut. Responses kann ihn serverseitig speichern.
  • Wo die Systemanweisung liegt: im ersten Element von messages, im Feld instructions oder im Feld system auf oberster Ebene.
  • Wie Werkzeugaufrufe zurückkommen: tool_calls, function_call oder tool_use.
  • Wo der Text steht: in choices, in output oder in einem content-Array.

Wichtig: „OpenAI“ im Namen bezeichnet das Format, nicht die Modellmarke. Welches Modell antwortet, entscheidet die Modell-ID im Feld darüber.

Die drei Protokolle im Vergleich: Erinnerungsvermögen, eigene Werkzeuge, wann man sie wählt

Schritte

1. Felder ausfüllen

  1. „Einstellungen → Modelle → Modellanbieter hinzufügen“, dann „Benutzerdefinierte Modell-API“
  2. Provider-ID: freier Kleinbuchstabe, nicht mit anderen Einträgen doppelt (Beispiel: crazyrouter)
  3. Anzeigename: nur zur eigenen Orientierung im Menü
  4. API-Adresse: die Basis-URL des Dienstes, nur bis /v1 — nicht den vollständigen Pfad eintragen
  5. API-Protokoll: im Zweifel OpenAI Chat Completions
  6. API-Schlüssel: der Schlüssel desselben Dienstes
  7. Modellkatalog: „Verfügbare Modelle abrufen“ oder Modell-ID manuell eintragen
  8. Speichern, neue Sitzung öffnen, Modell auswählen

2. Prüfskript in drei Schritten

$base    = "https://api.crazyrouter.com/v1"   # Beispiel: Crazyrouter
$headers = @{ Authorization = "Bearer $env:CRAZYROUTER_API_KEY" }

# Schritt 1: Modellliste — prüft nur Adresse und Schlüssel
Invoke-RestMethod -Uri "$base/models" -Headers $headers |
  Select-Object -ExpandProperty data | Select-Object -First 5 -Property id

# Schritt 2: alle drei Endpunkte abklopfen, nur den Statuscode lesen
foreach ($p in @("/chat/completions", "/responses", "/messages")) {
  $r = Invoke-WebRequest -Uri "$base$p" -Method Post -Headers $headers `
       -ContentType "application/json" -Body "{}" -SkipHttpErrorCheck
  Write-Output ("{0,-20} {1}" -f $p, $r.StatusCode)
}

# Schritt 3: kleinste mögliche Anfrage
$body = @{
  model    = "deepseek-v4-pro"
  messages = @(@{ role = "user"; content = "Antworte nur mit OK" })
} | ConvertTo-Json -Depth 5

Invoke-RestMethod -Uri "$base/chat/completions" -Method Post `
  -Headers $headers -ContentType "application/json" -Body $body |
  Select-Object -ExpandProperty choices
Enter fullscreen mode Exit fullscreen mode

Schritt 2 funktioniert auch ohne Schlüssel: $headers weglassen und einen leeren Body senden. Ein 401 heißt, die Route existiert; ein 404 heißt, sie existiert nicht.

Verifikation: Ergebnisse vom 20.10.2026

Ohne Schlüssel lässt sich die Existenz der Route prüfen. Alle vier echten Pfade antworteten mit 401 und dem Text 未提供令牌 („kein Token angegeben“); ein absichtlich falscher Pfad antwortete mit 404 und Invalid endpoint path. Der Dienst prüft die Route vor dem Token — deshalb funktioniert dieser Test auch vor der Einrichtung.

Alle drei Endpunkte antworteten mit 200. Die Antwortzeit lag zwischen zwei und vier Sekunden. Der Unterschied liegt in der Position des Textes:

Endpunkt Modell Status Felder auf oberster Ebene
/chat/completions deepseek-v4-pro 200 choices,id,model,object,usage
/responses deepseek-v4-pro 200 output,output_text,status,object
/messages claude-opus-4-5 200 content,stop_reason,type,role,usage

Drei Schritte zur Eingrenzung: erst die Route, dann die Felder

404 hat zwei Bedeutungen. Eine falsche Modell-ID ergibt ebenfalls 404, aber im Body steht model_not_found samt Modellnamen. Nur der Body unterscheidet „falscher Pfad“ von „falsches Modell“.

Der Dienst ist großzügiger als die Spezifikation. Anthropic verlangt max_tokens; hier wurde auch ohne dieses Feld 200 zurückgegeben. x-api-key und Authorization: Bearer wurden beide akzeptiert. Die OpenAI-kompatiblen Endpunkte akzeptierten dagegen nur Bearer — mit x-api-key kam 401. Regeln lassen sich also nicht ungeprüft von einem Anbieter auf einen anderen übertragen.

Werkzeugaufrufe funktionieren in allen drei Formaten, aber unterschiedlich:

Protokoll Anfrage Antwort
Chat Completions tools[].function.parameters message.tool_calls[], finish_reason=tool_calls
Messages tools[].input_schema content[0].type=tool_use, stop_reason=tool_use
Responses tools[].type=function function_call innerhalb von output[]

Responses: Die Websuche funktioniert, die Kontextfortsetzung nicht. Mit tools=[{"type":"web_search"}] erschienen fünf web_search_call-Einträge mit echten Suchergebnissen; instructions wurde ebenfalls beachtet. Im zweiseitigen Test mit previous_response_id erinnerte sich das Modell jedoch nicht an die erste Nachricht — die Antwort war von einem Kontrolllauf ohne diesen Parameter nicht zu unterscheiden. Ein akzeptiertes Feld ist kein Beweis für eine implementierte Funktion.

Fehlersuche

  • 401 — Schlüssel falsch oder am falschen Ort. OpenAI-Format: Authorization: Bearer. Messages: x-api-key (manche Dienste akzeptieren auch Bearer).
  • 404 — Route fehlt (Invalid endpoint path) oder Modell-ID falsch (model_not_found). Immer den Body lesen.
  • 400 / 422 — Route vorhanden, Anfrage nicht konform. Fehlt model, kommt Model name is required.
  • 200, aber wirkungslos — eine system-Anweisung im Anthropic-Stil an einen Chat-Completions-Endpunkt ergibt 200, wird aber ignoriert. Kein Fehler bedeutet nicht, dass die Anweisung greift.

Die Reihenfolge lautet: Adresse → Schlüssel → Route → Felder. Wer alle vier gleichzeitig ändert und dann einen Fehler bekommt, hat nichts gelernt.

Austausch

Mich würde interessieren, wie andere Anbieter sich hier verhalten: Akzeptiert euer Dienst ebenfalls beide Authentifizierungs-Header, und funktioniert die Kontextfortsetzung über previous_response_id tatsächlich? Genau das ist der Punkt, an dem sich Anbieter am stärksten unterscheiden, und der sich nur durch einen eigenen Test klären lässt.

Für diese Tests nutze ich Crazyrouter: ein Schlüssel für Modelle mehrerer Anbieter, mit getrennten OpenAI- und Anthropic-kompatiblen Einstiegspunkten — praktisch, um die drei Schritte oben im selben Konto zu vergleichen.

Quellen

Top comments (0)