KI-Agent

DeepSeek V4: Mehrere 400-Fehler reproduzieren

MacHTML Lab2026.08.18 ~15 Min. Lesezeit
DeepSeek V4: Mehrere 400-Fehler reproduzieren

Last updated: 18.08.2026. Die Angaben wurden anhand der offiziellen DeepSeek-Dokumentation zum Thinking Mode und der aktuellen vLLM-Dokumentation zu Reasoning Outputs geprüft.

Bei einem DeepSeek V4 Mehrfach-400-Fehler sollten Sie nicht zuerst Ihr Agent-Framework ändern. Die offizielle DeepSeek-API verlangt bei Tool-Aufrufen, dass reasoning_content in allen nachfolgenden Anfragen vollständig zurückgegeben wird. vLLM verwendet in der aktuellen Dokumentation dagegen reasoning; mischen Sie beide Felder nicht in einem Payload. Bauen Sie zwei getrennte Roh-HTTP-Reproduktionsketten und wandeln Sie Nachrichten erst an der Endpoint-Grenze um.

Diese Anleitung ist für Sie gedacht, wenn Sie reproduzierbare Belege für Modell- oder Framework-Verantwortliche liefern müssen, wenn Sie zwischen Client, Gateway und Inferenzserver unterscheiden wollen oder wenn Sie für die offizielle API und vLLM eine gemeinsame Regressionstestumgebung aufbauen.

Fehlerbild und Vertragsgrenzen

Ein typischer Fall sieht zunächst widersprüchlich aus:

  1. Die erste Anfrage mit tools liefert eine gültige Assistant-Antwort.
  2. Die Funktion wird korrekt ausgeführt.
  3. Sie hängen die tool-Nachricht an.
  4. Die zweite Anfrage endet mit HTTP 400.

Der Grund liegt oft nicht im Tool selbst. Die erste Anfrage prüft nur, ob der Endpunkt eine Tool-Auswahl erzeugen kann. Die zweite Anfrage prüft zusätzlich, ob der komplette Gesprächszustand zum erwarteten Nachrichtenvertrag passt.

Bei der offiziellen DeepSeek-API sind vier Grenzen entscheidend:

  • reasoning_content steht auf derselben Assistant-Ebene wie content.
  • tool_calls bleiben Teil dieser Assistant-Nachricht.
  • Die role: "tool"-Nachricht benötigt die passende tool_call_id.
  • Die Assistant-Nachricht muss vor dem Tool-Ergebnis stehen.

DeepSeek beschreibt ausdrücklich, dass reasoning_content bei Anfragen mit tools in allen folgenden Requests vollständig zurückgegeben werden muss. Fehlt es, kann die API 400 liefern. Bei einer normalen Unterhaltung ohne Tool-Aufruf gelten andere Regeln: Dort muss das Reasoning vorheriger Runden nicht zwingend weitergereicht werden. (api-docs.deepseek.com)

vLLM ist kein automatischer Vertragspartner der DeepSeek-API. Die aktuelle vLLM-Dokumentation verwendet das Ausgabeattribut reasoning und weist darauf hin, dass reasoning_content die ältere Bezeichnung war. Ein Client, der weiterhin ausschließlich reasoning_content liest, kann deshalb einen scheinbar leeren Wert sehen, obwohl reasoning gefüllt ist.

Weitere versteckte Fehlerquellen:

  • Ein Gateway entfernt unbekannte Felder aus Assistant-Nachrichten.
  • Ein JSON-Serializer lässt optionale Felder mit leerem Wert weg.
  • Streaming-Code sammelt content, aber keine Reasoning-Deltas.
  • Ein Logger schreibt eine gekürzte Nachricht zurück in den Testlauf.
  • Der Modellname bleibt gleich, während sich die base_url geändert hat.
  • Eine vLLM-Konfiguration liefert kein Reasoning, weil der passende Parser oder die Thinking-Aktivierung fehlt.

Der Modellname ist daher kein ausreichender Beweis für den Zielvertrag. Prüfen Sie immer URL, Response-Schema und laufende Serverversion.

Zwei Endpunkte, zwei Feldverträge

Bevor Sie eine Anfrage bauen, legen Sie pro Testlauf eine eigene Konfigurationsdatei an. Verwenden Sie keine globale Variable wie REASONING_FIELD, die für beide Systeme gilt.

Prüfpunkt Offizielle DeepSeek-API vLLM-Endpoint
Typischer Zielpfad Vom Anbieter dokumentierter Chat-Completion-Endpunkt Häufig OpenAI-kompatibler /v1/chat/completions-Endpunkt
Reasoning-Ausgabe reasoning_content Aktuelle Dokumentation: reasoning
Tool-Aufruf tool_calls in der Assistant-Nachricht tool_calls; Reasoning-Unterstützung hängt von Parser und Modell ab
Rückspielregel Bei Tool-Schleifen reasoning_content vollständig erhalten Eingabe- und Rückspielverhalten der konkreten Version prüfen
Sichere Vorgehensweise Originalfeld unverändert speichern Originalfeld reasoning unverändert speichern
Risiko beim Wechsel Fehlendes reasoning_content führt laut DeepSeek-Dokumentation zu 400 Stilles Lesen eines alten Feldnamens kann einen leeren Wert erzeugen

Die Tabelle ist keine Aussage, dass beide Systeme gegenseitig kompatibel sind. Sie markiert nur die beobachtbaren Ausgangspunkte der beiden Verträge. vLLM dokumentiert zusätzlich, dass Reasoning-Ausgaben mit Tool Calling verfügbar sein können, während Tool-Aufrufe aus dem content-Bereich und nicht aus dem reasoning-Bereich geparst werden. (docs.vllm.ai)

Dokumentieren Sie außerdem:

  • vollständige base_url, ohne geheime Zugangsdaten;
  • Modellkennung;
  • Server- und Parser-Version;
  • Thinking- beziehungsweise Reasoning-Einstellungen;
  • HTTP-Status und Fehlerkörper;
  • den Hash oder die Versionsnummer Ihres Testskripts.

Für die offizielle API können Sie den DeepSeek-Leitfaden zu Tool Calls und den DeepSeek-Leitfaden zu mehrstufigen Gesprächen danebenlegen. Für vLLM gehört die offizielle Tool-Calling-Dokumentation mit Reasoning in denselben Prüfordner.

Erste HTTP-Kette mit einem harmlosen Tool

Verwenden Sie ein Tool ohne Seiteneffekt. Das Tool muss weder Datenbankzugriff noch Netzwerkzugriff besitzen. Für die Reproduktion genügt ein Funktionsname und ein kleines JSON-Argument.

Beispiel für einen anonymisierten Start:

curl -sS "$BASE_URL/chat/completions" \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4-pro",
    "messages": [
      {
        "role": "user",
        "content": "Prüfen Sie den Status des Testobjekts."
      }
    ],
    "tools": [
      {
        "type": "function",
        "function": {
          "name": "get_test_status",
          "description": "Liefert einen festen Status für einen lokalen Test.",
          "parameters": {
            "type": "object",
            "properties": {},
            "additionalProperties": false
          }
        }
      }
    ],
    "tool_choice": "auto",
    "stream": false
  }' | tee response-01.json

Ersetzen Sie BASE_URL für den ersten Lauf ausschließlich durch den offiziellen DeepSeek-Zielendpunkt. Starten Sie danach einen zweiten Lauf gegen vLLM. Verwenden Sie dieselbe Tool-Definition, dieselbe User-Nachricht und dieselben nicht sensiblen Header. So ist die Nachrichtenvertragsdifferenz die wichtigste verbleibende Variable.

Aus der Antwort benötigen Sie zunächst nur diese Felder:

{
  "id": "redacted",
  "choices": [
    {
      "finish_reason": "tool_calls",
      "message": {
        "content": "redacted",
        "reasoning_content": "redacted",
        "reasoning": "redacted",
        "tool_calls": [
          {
            "id": "redacted",
            "type": "function",
            "function": {
              "name": "get_test_status",
              "arguments": "{}"
            }
          }
        ]
      }
    }
  ]
}

Zeigen Sie in einem Fehlerbericht niemals vollständige Gedankengänge, API-Schlüssel, private User-Eingaben oder echte Tool-Ergebnisse. Für die Diagnose reichen Feldnamen, Existenz, Typ, Länge und ein stabiler Hash. Eine Länge ist nur dann sinnvoll, wenn sie aus Ihrer eigenen anonymisierten Reproduktion stammt; verwenden Sie keine erfundenen Beispielwerte als Messung.

Assistant-Nachricht und fehlerhafte Rückgabe

Die wichtigste Beweisaufnahme passiert direkt nach der ersten Modellantwort. Schreiben Sie die Assistant-Nachricht in eine separate Datei, bevor irgendeine Normalisierung stattfindet.

Für die offizielle DeepSeek-API sollte die Struktur sinngemäß so aussehen:

{
  "role": "assistant",
  "content": "[redigiert]",
  "reasoning_content": "[redigiert]",
  "tool_calls": [
    {
      "id": "call_redacted",
      "type": "function",
      "function": {
        "name": "get_test_status",
        "arguments": "{}"
      }
    }
  ]
}

Der häufigste negative Test entfernt absichtlich reasoning_content:

{
  "role": "assistant",
  "content": "[redigiert]",
  "tool_calls": [
    {
      "id": "call_redacted",
      "type": "function",
      "function": {
        "name": "get_test_status",
        "arguments": "{}"
      }
    }
  ]
}

Dieser negative Test ist nur für die offizielle API belastbar, wenn Ihr tatsächlicher Lauf Thinking Mode und tools aktiviert hat. Laut DeepSeek muss das Reasoning dann in den nachfolgenden Requests vollständig vorhanden sein; andernfalls wird ein 400-Fehler erwartet. (api-docs.deepseek.com)

Prüfen Sie vor dem Senden:

def assert_assistant_message(message, expected_field):
    assert message["role"] == "assistant"
    assert "tool_calls" in message
    assert message["tool_calls"][0]["id"]
    assert message["tool_calls"][0]["function"]["name"]

    if expected_field == "deepseek":
        assert "reasoning_content" in message
    elif expected_field == "vllm":
        assert "reasoning" in message

Diese Prüfung muss nach der Serialisierung erfolgen. Ein Objekt kann im Speicher ein Attribut besitzen, das beim Umwandeln in ein Dictionary verloren geht. Ebenso kann eine Datenschutz-Middleware Felder entfernen. Das ist dann ein Fehler in Client oder Zwischenkomponente, nicht automatisch ein Fehler des Modellservers.

Tool-Ergebnis und zweite Anfrage

Fügen Sie das Tool-Ergebnis erst nach der vollständigen Assistant-Nachricht ein:

{
  "messages": [
    {
      "role": "user",
      "content": "Prüfen Sie den Status des Testobjekts."
    },
    {
      "role": "assistant",
      "content": "[redigiert]",
      "reasoning_content": "[redigiert]",
      "tool_calls": [
        {
          "id": "call_redacted",
          "type": "function",
          "function": {
            "name": "get_test_status",
            "arguments": "{}"
          }
        }
      ]
    },
    {
      "role": "tool",
      "tool_call_id": "call_redacted",
      "content": "{\"status\":\"ok\"}"
    }
  ]
}

Senden Sie danach die zweite rohe HTTP-Anfrage. Speichern Sie nicht nur den Statuscode, sondern auch:

  1. die exakte Ziel-URL;
  2. den Modellwert;
  3. die Reihenfolge aller Nachrichten;
  4. die vorhandenen Reasoning-Felder;
  5. tool_call_id und tool_calls[].id;
  6. den vollständigen, redigierten Fehlerkörper.

Ihre Testserie sollte mindestens drei Fälle enthalten:

Testfall Assistant-Nachricht Erwarteter Zweck
Negativ, offizieller API-Vertrag reasoning_content fehlt Bestätigt, ob der dokumentierte 400-Pfad reproduzierbar ist
Positiv, offizieller API-Vertrag reasoning_content vollständig vorhanden Prüft die korrekte Tool-Fortsetzung
Negativ oder Vergleich, vLLM Nur reasoning_content trotz Ausgabe reasoning Zeigt eine Client-Feldverwechslung, nicht automatisch API-Inkompatibilität
Positiv, vLLM-Vertrag reasoning aus der Response erhalten Prüft das Verhalten des konkreten vLLM-Deployments

Bei vLLM müssen Sie die konkrete Modell- und Parserkonfiguration mitprotokollieren. Die Dokumentation beschreibt, dass ein Reasoning Parser für die Ausgabe aktiviert werden muss und dass bestimmte Modelle Thinking Mode über Template-Parameter benötigen. Für DeepSeek-V4-Pro nennt die aktuelle vLLM-Dokumentation enable_thinking: true als Voraussetzung, sofern dies nicht bereits durch andere Request-Einstellungen aktiviert wird.

FAQ für die Fehlerübergabe

Erster Erfolg, späterer 400-Fehler

Ein erfolgreicher erster Tool-Aufruf beweist nur, dass die Initialanfrage akzeptiert wurde. Der zweite Request enthält eine zusätzliche Assistant-Nachricht, ein Tool-Ergebnis und eine Referenz-ID. Fehlt bei der offiziellen API reasoning_content, kann genau diese Erweiterung den 400-Fehler auslösen. Prüfen Sie deshalb zuerst den serialisierten Request unmittelbar vor dem HTTP-Versand.

Position von reasoning_content

Die Position ist nicht die Tool-Nachricht. Sie gehört in die historische Assistant-Nachricht, zusammen mit content und tool_calls. Die Reihenfolge lautet: User, Assistant mit vollständigem Reasoning und Tool-Aufruf, danach Tool-Ergebnis. Verschieben Sie das Feld in role: "tool" oder in eine neue User-Nachricht, testen Sie einen anderen Vertrag und erhalten keine belastbare Reproduktion.

vLLM reasoning gegenüber der offiziellen API

Ein vLLM-Response-Feld namens reasoning darf nicht ungeprüft als reasoning_content an DeepSeek weitergereicht werden. Die aktuelle vLLM-Dokumentation markiert reasoning_content als ältere Bezeichnung. Das bedeutet nicht, dass jeder vLLM-Endpoint automatisch DeepSeek-kompatible Eingaben akzeptiert. Die Umwandlung muss am Ausgang des jeweiligen Endpunkts erfolgen.

Reproduktion ohne SDK

Mit curl können Sie die entscheidenden Variablen sichtbar halten. Das ist besonders hilfreich, wenn ein SDK Assistant-Objekte automatisch ergänzt, unbekannte Attribute verwirft oder Streaming-Chunks zusammenführt. Ein Roh-HTTP-Test ersetzt keine Integrationstests, liefert aber die klarste erste Trennung zwischen Nachrichtenvertrag und Framework-Verhalten.

Endpoint-Grenze und interne Nachrichtennormalisierung

Wenn Ihre Anwendung beide Systeme unterstützt, definieren Sie intern ein neutrales Nachrichtenmodell. Dieses Modell darf nicht einfach einen der beiden externen Feldnamen als universelle Wahrheit übernehmen.

Beispiel:

{
  "role": "assistant",
  "final_content": "[redigiert]",
  "reasoning_value": "[redigiert]",
  "reasoning_source_field": "reasoning",
  "tool_calls": []
}

Am Eingang des vLLM-Adapters lesen Sie reasoning. Am Eingang des DeepSeek-Adapters lesen Sie reasoning_content. Beim Ausgang entscheiden Sie anhand der Ziel-URL, welches Feld in die historische Assistant-Nachricht geschrieben wird.

Die Vorteile:

  • Ein Endpoint-Wechsel verändert nicht Ihre gesamte Historie.
  • Alte Gesprächsdaten behalten die Information über ihre Herkunft.
  • Fehlerberichte können zwischen Quelldaten und transformierter Nachricht unterscheiden.
  • Eine spätere Feldumbenennung bleibt auf den Adapter begrenzt.

Die Nachteile:

  • Sie benötigen explizite Adaptertests.
  • Jede Transformation muss Datenschutzregeln beachten.
  • Ein gemeinsames Modell kann Unterschiede bei Tool- und Thinking-Regeln nicht vollständig verstecken.
  • Eine erfolgreiche Normalisierung darf nicht als Kompatibilitätsgarantie gelten.

Für Debugging-Logs sollten Sie reasoning_source_field, Ziel-base_url, Nachrichtenindex und Tool-ID erfassen. Den Inhalt selbst können Sie durch [redigiert], Länge und Hash ersetzen. So bleibt der Nachweis für DSGVO- und Datenschutzprüfungen brauchbar, ohne vollständige Gedankengänge zu speichern.

Regressionstest und Abnahmekriterien

Machen Sie aus der Reproduktion einen festen Test. Ein einzelner manueller Erfolg ist zu schwach, besonders wenn sich API-Verträge, vLLM-Parser oder Chat-Templates ändern.

  • [ ] Die Testkonfiguration enthält die vollständige Ziel-base_url.
  • [ ] Offizielle DeepSeek-API und vLLM werden in getrennten Testläufen angesprochen.
  • [ ] Das Modell wird über die Antwort oder den Serverstatus verifiziert, nicht nur aus einer Variablen übernommen.
  • [ ] Die erste Anfrage verwendet genau ein harmloses Tool.
  • [ ] Die vollständige Rohantwort wird verschlüsselt oder redigiert abgelegt.
  • [ ] content, Reasoning-Feld, tool_calls und finish_reason werden einzeln geprüft.
  • [ ] Die Assistant-Nachricht wird vor dem Tool-Ergebnis eingefügt.
  • [ ] Jede tool_call_id passt exakt zur ursprünglichen Tool-ID.
  • [ ] Der absichtlich fehlerhafte Payload bleibt als negativer Test erhalten.
  • [ ] Der korrekte Payload wird für jeden Endpoint separat erzeugt.
  • [ ] Ein Test ohne Tool-Aufruf ist enthalten.
  • [ ] Ein einzelner Tool-Aufruf ist enthalten.
  • [ ] Mehrere aufeinanderfolgende Tool-Aufrufe sind enthalten.
  • [ ] Ein Wechsel der base_url erzeugt einen neuen, klar markierten Testlauf.
  • [ ] Logs enthalten keine API-Schlüssel, privaten Eingaben oder vollständigen Reasoning-Texte.
  • [ ] Der Test schlägt auch bei falschem Feldnamen fehl, nicht nur bei einem falschen HTTP-Status.
  • [ ] Die Reparatur gilt erst als abgeschlossen, wenn positive und negative Fälle stabil das erwartete Ergebnis liefern.

Die Regression ist bestanden, wenn beide Zielketten mit ihrer jeweiligen Feldkonvention funktionieren, der absichtlich beschädigte Payload zuverlässig scheitert und die Fehlerausgabe den betroffenen Layer benennt. Prüfen Sie zusätzlich die Nachrichtensequenz. Ein HTTP-200 allein beweist nicht, dass tool_call_id, Feldherkunft und Endpoint-Auswahl korrekt sind.

Wenn Ihr lokaler Rechner beide sauberen Endpunkte nicht dauerhaft parallel vorhalten kann, ist eine isolierte Testumgebung oft die bessere Entscheidung. Ein gemeinsam genutztes Entwicklergerät bringt wechselnde Umgebungsvariablen, alte Container, unklare Ports und nicht reproduzierbare Cache-Zustände in den Test. Für kurzzeitige Regressionen ist eine gemietete Mac-Umgebung von MacHTML sinnvoller als ein dauerhaft veränderter Arbeitsplatz: Sie können dieselben Skripte, Konfigurationsdateien und redigierten Payloads wiederholt ausführen, ohne Ihre lokale Entwicklungsumgebung umzubauen. Prüfen Sie vorab, ob Ihr Test echte Linux-GPU-Anforderungen oder physische Schnittstellen benötigt; dann ist eine Mac-Umgebung nicht automatisch die passende Wahl.

Für die Bereitstellung können Sie die MacHTML-Konsole nutzen und bei Fragen zur Verbindung oder zum Zugriff die MacHTML-Hilfe heranziehen. Entscheidend ist nicht die Marke des Rechners, sondern eine getrennte, dokumentierte Umgebung mit stabiler base_url, kontrollierten Versionen und einem reproduzierbaren HTTP-Skript.

FAQ

Warum funktioniert der erste Tool-Aufruf, obwohl die nächste Anfrage mit 400 abgelehnt wird?+
Die erste Anfrage enthält nur die ursprüngliche Benutzernachricht und die Tool-Definition. Der Fehler entsteht erst beim Zurückspielen der Assistant-Nachricht zusammen mit dem Tool-Ergebnis. Bei der offiziellen DeepSeek-API fehlt dann häufig reasoning_content oder es wurde durch Serialisierung, Streaming-Logik oder Middleware entfernt. Der erste erfolgreiche Aufruf beweist daher nicht, dass die gesamte Tool-Schleife korrekt implementiert ist.
An welcher Stelle der nächsten Nachricht gehört reasoning_content?+
Bei der offiziellen DeepSeek-API gehört reasoning_content in dieselbe historische Assistant-Nachricht, die auch content und tool_calls enthält. Diese Nachricht wird nach der ersten Modellantwort vor der role=tool-Nachricht in messages eingefügt. Sie sollten den Wert nicht in die Tool-Nachricht verschieben und nicht als separates User-Feld senden. Bei vLLM müssen Sie dagegen die konkrete Ausgabeform Ihres Deployments prüfen.
Kann ein vLLM-Feld reasoning direkt an die DeepSeek-API weitergereicht werden?+
Nein, nicht ohne eine bewusst definierte Ausgangsabbildung. Die aktuelle vLLM-Dokumentation verwendet reasoning und beschreibt reasoning_content als ältere Bezeichnung. Die offizielle DeepSeek-Dokumentation verlangt bei Tool-Aufrufen jedoch reasoning_content in nachfolgenden Anfragen. Ein gemeinsames internes Nachrichtenmodell ist möglich; am jeweiligen Endpoint müssen Sie die Felder aber zielgerichtet und einseitig abbilden.
Wie lässt sich der Fehler ohne OpenAI SDK reproduzieren?+
Verwenden Sie curl oder eine andere rohe HTTP-Implementierung mit einem einzigen Tool, einer kurzen User-Nachricht und deaktivierter automatischer Nachrichtenanreicherung. Speichern Sie die vollständigen JSON-Antworten, senden Sie zuerst die Assistant-Nachricht ohne reasoning_content und danach mit dem vom Zielsystem erwarteten Feld. Vergleichen Sie Statuscode, Fehlerkörper, base URL, Nachrichtenreihenfolge, tool_call_id und Feldnamen.

Reproduzierbare API-Tests mit MacHTML ausführen

Mieten Sie bei MacHTML einen dedizierten Mac mini M4 für stabile und nachvollziehbare Regressionstests. Führen Sie Roh-HTTP-Anfragen, Fehlerprüfungen und wiederholte Testläufe in einer kontrollierten Remote-Umgebung aus. Dank SSH-Zugang, bis zu 1 Gbit/s dedizierter Ausgangsbandbreite und unbegrenztem Traffic bleibt Ihre Testumgebung flexibel einsetzbar. Wählen Sie Standort und Mietdauer passend zu Ihrem Projekt und starten Sie Ihre MacHTML-Instanz innerhalb weniger Minuten.

Cloud Mac mini mieten
Apple Silicon Cloud Mac