Aha!

Warum die Antwort mitten im Satz abbricht

Die Ausgabe hört auf, als hätte jemand den Stecker gezogen - mitten im Wort, mitten in der Codezeile. Vier Ursachen kommen dafür infrage, und sie sehen im Ergebnis fast gleich aus.

29. Juli 2026token · abbruch · betrieb

Die Antwort läuft, wird lang, wird länger - und endet dann mit return calcul. Kein Fehler, keine Meldung, nur ein Text, der aufhört. Das ist fast nie ein Aussetzer des Modells. Es ist eine Grenze, gegen die etwas gelaufen ist, und die Anzeige verrät meistens nicht, welche.

1. Das Ausgabelimit ist erreicht

Der häufigste Fall. Jeder Aufruf hat eine Obergrenze für die Ausgabe (max_tokens, je nach Anbieter auch anders benannt), und wenn die erreicht ist, hört die Generierung auf - egal wo im Satz. Das Modell weiß davon nichts: Es gibt Token für Token aus, und irgendwann nimmt der Server keins mehr entgegen.

Erkennbar ist es am Abschlussgrund der Antwort. Steht dort length statt stop, ist genau das passiert. Dieses Feld ist der wichtigste Hinweis überhaupt und wird in vielen Integrationen schlicht nicht ausgewertet - weshalb ein abgeschnittener Text dann als vollständiger Text weiterverarbeitet wird.

Baustein

Der LLM-Call

Ein Request, eine Antwort - der rohe Baustein, aus dem alles andere entsteht. Und die wichtigste Erkenntnis gleich zu Beginn: Das Gehirn ist nicht im Agenten. Es ist am anderen Ende der Leitung.

Wir rufen zum ersten Mal ein Sprachmodell auf: eine Nachricht hin, eine Antwort zurück - und danach ist die Leitung tot. Kein Zustand, kein Gedächtnis, keine Werkzeuge. Genau dieses Auflegen erklärt fast alles, was später kommt. Und wir rufen nicht irgendein Modell: Wir sprechen mit unserem eigenen - qwen3.8-27b-fast, das auf unserem Inferenz-Stack läuft. Wie man so ein Modell selbst betreibt, ist Thema von Block III; hier gehen wir erst einmal davon aus, dass es irgendwo eines gibt.

Chat + GPT: wer macht hier eigentlich was?

Der Name ChatGPT verrät die Arbeitsteilung, um die es in diesem ganzen Block geht: GPT ist das Modell - es läuft irgendwo auf GPUs und kann genau eines: Text rein, Text raus. Chat ist die Software drumherum - sie merkt sich das Gespräch, gibt dem Modell eine Rolle, reicht Werkzeuge an. Diesen Software-Teil bauen wir hier nach, Schicht für Schicht - nur eben nicht als Chat, sondern als Agent. Der Harness ist der Chat-Teil. Das Modell mieten wir an - oder betreiben es, wie in unserem Fall, gleich selbst.

Ein Anruf, kein Abo

Nachdem wir nach dem Video nun wissen, dass die ganze Magie bei "KI" und ChatGPT eigentlich im LLM steckt, werden wir uns zunächst damit genauer befassen. Wir gehen jetzt also zunächst davon aus, dass wir Zugang zu einem Sprachmodell haben. Wie wir Sprachmodelle selber betreiben, lernen wir in Block 3 (Inferenz). Wie wir an eine API kommen, sehen wir unter anderem in unserem Tutorial zum OpenRouter-Key. Versuchen wir einmal darauf zuzugreifen: die allereinfachste Form ist ein nackter Web-Request - curl reicht. Adresse des Endpunkts (LLM_BASE_URL, bei uns die eines selbst betriebenen vLLM-Servers) und Schlüssel (LLM_API_KEY) kommen aus der Umgebung - dort trägst du ein, welchen Anbieter oder eigenen Server du ansprichst. Im Aufruf selbst geben wir an, welches Modell wir sprechen wollen (model), wie lang die Antwort höchstens werden darf (max_tokens), und was gesagt werden soll (messages):

curl "$LLM_BASE_URL"/chat/completions \
  -H "Authorization: Bearer $LLM_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "model": "qwen3.8-27b-fast",
    "max_tokens": 200,
    "messages": [
      { "role": "user", "content": "Erkläre in 2 Sätzen, was ein KI-Agent ist." }
    ]
  }'

Zurück kommt - ebenfalls nur JSON, und deutlich technischer als alles, was ChatGPT je anzeigt:

{
  "choices": [
    {
      "message": { "role": "assistant", "content": "Ein KI-Agent ist ein Programm, das …" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 23, "completion_tokens": 61 }
}

Drei Felder bestimmen alles Weitere: choices[0].message ist die Antwort. finish_reason sagt, warum das Modell aufgehört hat zu reden - stop heißt „von alleine fertig“, length heißt „abgeschnitten“. Und usage zählt die Tokens - die Währung, in der Inferenz gerechnet wird, auch auf der eigenen Hardware.

Aus Software heraus macht man denselben Aufruf mit ein paar Zeilen Python oder JavaScript - Bibliothek braucht es dafür keine, ein HTTP-Client genügt. In den Experimenten unten siehst du bei jedem Lauf den rohen Request und die rohe Response; weiter unten gibt es beides als fertige Referenz-Dateien und als Prompt für deinen Coding-Agenten zum Selberbauen.

Der Brieffreund mit dem Kurzzeitgedächtnis

Das Überraschendste am ersten Call ist, was nicht passiert: Das Modell merkt sich nichts. Der zweite Aufruf ist für das Modell eine Anfrage wie jede andere - es weiß nicht, dass es je einen ersten gab, auch wenn er nur Millisekunden her ist. Stell es dir wie einen Brieffreund vor, der sich zwischen zwei Anrufen an nichts erinnert: Jedes Mal, wenn wir anrufen, müssen wir alles noch einmal erzählen, was je passiert ist - und sobald er geantwortet hat, legen wir auf.

Ein LLM-Call ist nichts Magisches: JSON rein, JSON raus. Kein Login, keine Sitzung, kein Konto-Stand auf der Gegenseite - nur ein Request und eine Antwort.

Und der Call ist zustandslos: Der nächste Anruf beginnt bei null, die Stimme am anderen Ende erinnert sich an nichts - technisch ist sie ein riesiger, schlauer Zufallsgenerator ohne jedes Gedächtnis. Alles, was ein Agent später kann - Gespräch, Rolle, Werkzeuge - muss der Harness bei jedem Anruf neu mitbringen. Das Gehirn ist nicht im Agenten. Es ist am anderen Ende der Leitung - und wir bauen in den nächsten Bauteilen alles drumherum.

→ Zum Baustein

Warum passiert das gerade bei Agenten so oft? Weil die Voreinstellungen aus einer Zeit stammen, in der Antworten kurz waren. 1024 Token sind für einen Chat viel und für eine generierte Datei wenig. Und es fällt spät auf: Der abgeschnittene Text sieht bis zur letzten Zeile richtig aus.

2. Das Kontextfenster ist voll

Ein Modell hat ein Gesamtbudget für Eingabe und Ausgabe. Wenn der Nachrichtenverlauf 190 000 Token belegt und das Fenster 200 000 fasst, bleiben für die Antwort 10 000 - selbst wenn max_tokens viel höher steht. Der Effekt ist derselbe wie oben, aber die Ursache liegt woanders: nicht am Limit, sondern am Verlauf.

Das erklärt ein Verhalten, das viele beobachten: Ein Agent liefert am Anfang eines Laufs ordentliche Antworten und schneidet sie gegen Ende reihenweise ab. Der Verlauf ist einfach größer geworden. Wer den Grund dahinter genauer wissen will: Er ist derselbe, aus dem der zehnte Turn so viel mehr kostet als der erste - der Verlauf fährt bei jedem Aufruf vollständig mit.

3. Eine Stoppsequenz kam im Text vor

Stoppsequenzen sagen dem Modell, es solle aufhören, sobald eine bestimmte Zeichenfolge auftaucht. Sinnvoll, um Rollenmarken wie \nUser: abzuschneiden - und tückisch, wenn die Sequenz mitten im gewünschten Inhalt legitim vorkommt. Klassiker: ``` als Stoppsequenz, während die Antwort einen Codeblock enthält. Der Abschlussgrund lautet dann meist stop, weil aus Sicht des Servers alles nach Plan lief - nur eben zu früh.

4. Die Verbindung ist gestorben

Beim Streaming kommt die Antwort in vielen kleinen Häppchen über eine offene Verbindung. Alles, was dazwischenliegt, kann sie kappen: ein Proxy mit Zeitlimit, ein Load Balancer, der stille Verbindungen schließt, ein Neustart. Für die Anwendung sieht das aus wie ein Ende - der Text bricht ab, und ein Abschlussgrund kommt nie an.

Das ist der einzige der vier Fälle, bei dem tatsächlich etwas kaputt ist. Man erkennt ihn daran, dass kein finales Ereignis eintrifft: kein finish_reason, keine Verbrauchsangabe, kein Abschluss-Chunk. Wer nur den gesammelten Text betrachtet, sieht denselben Stummel wie in Fall 1.

Die Reihenfolge beim Nachsehen

  1. Abschlussgrund auslesen. length → Ausgabelimit. stop bei offensichtlich unfertigem Text → Stoppsequenz. Gar keiner → abgerissene Verbindung.
  2. Verbrauch anschauen. Liegen die Ausgabe-Token exakt auf dem Limit, ist der Fall klar. Sind Eingabe-Token plus Limit größer als das Fenster, ist es Fall 2.
  3. Erst dann am Prompt drehen. „Fasse dich kürzer“ behebt keinen der vier Fälle, es verschiebt nur, wann sie eintreten.

Und für den Betrieb die eine Regel, die den meisten Ärger erspart: Eine Antwort mit Abschlussgrund length ist ein Fehlerfall, kein Ergebnis. Behandle sie so - abbrechen, erneut anfordern, fortsetzen lassen. Nur nicht so tun, als wäre sie vollständig.

Passt dazu
Weitere Stücke