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:
- Die erste Anfrage mit
toolsliefert eine gültige Assistant-Antwort. - Die Funktion wird korrekt ausgeführt.
- Sie hängen die
tool-Nachricht an. - 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_contentsteht auf derselben Assistant-Ebene wiecontent.tool_callsbleiben Teil dieser Assistant-Nachricht.- Die
role: "tool"-Nachricht benötigt die passendetool_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_urlgeä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:
- die exakte Ziel-URL;
- den Modellwert;
- die Reihenfolge aller Nachrichten;
- die vorhandenen Reasoning-Felder;
tool_call_idundtool_calls[].id;- 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_callsundfinish_reasonwerden einzeln geprüft. - [ ] Die Assistant-Nachricht wird vor dem Tool-Ergebnis eingefügt.
- [ ] Jede
tool_call_idpasst 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_urlerzeugt 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
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.