Deterministische KI-Workflows rund um Claude gestalten
Warum die Anschreiben- und CV-Pipelines Claude schreiben, aber nie entscheiden lassen
Bewerbungsunterlagen·Experte·8 Min. Lesezeit · 6. Juli 2026
Der Anfang
Die erste Version der Anschreiben-Idee, im Mai, war so einfach, wie eine Idee nur sein kann: Stellenbeschreibung nehmen, meinen Werdegang nehmen, Claude bitten, ein Anschreiben zu schreiben. Ich habe das an einem Nachmittag gebaut, und es hat etwas produziert, das sich gut las.
Die erste Lösung
"Liest sich gut" war anfangs die ganze Messlatte. Dem Modell die Stellenbeschreibung und genug Kontext zu meinem Hintergrund geben, der Prompt-Anweisung vertrauen, "nutze nur, was tatsächlich relevant ist", und schreiben lassen. Das fühlte sich vernünftig an, weil es die Art ist, wie die meisten Leute die Nutzung eines LLM beschreiben — Kontext geben, um Output bitten.
Was kaputtging
Es ging auf zwei getrennte Arten kaputt, Monate auseinander, und beide haben mich dieselbe Lektion aus einem anderen Blickwinkel gelehrt.
Die erste war offensichtlich, sobald ich sie sah: Ein Modell, das überzeugend schreiben soll, lässt Lücken nicht still. Wenn die tatsächliche Evidenz für eine Anforderung dünn war, füllte Claude sie mit etwas Plausiblem, statt es einfach nicht zu erwähnen. Das ist kein Ton-Problem. Ein Anschreiben, das mich gegenüber einem Arbeitgeber vertritt, kann kein Projekt enthalten, das ich nie gemacht habe, und ein CV, das meine tatsächlichen Daten für einen besseren erzählerischen Fluss umsortiert, ist schlimmer als eine Auslassung — es ist ein Faktenfehler mit meinem Namen darunter.
Die zweite war subtiler und zeigte sich später, nachdem ich bereits eine deterministische Evidenzbewertungs-Schicht gebaut hatte, um das erste Problem zu lösen. Das Schlüsselwort-Wörterbuch, das diese Schicht nutzte, um eine Stellenbeschreibung mit meiner Erfahrung abzugleichen, war zwangsläufig unvollständig — rund 150 Einträge, von Hand gepflegt, denen weiß Gott wie viele Synonyme und Beinahe-Treffer fehlten, an die ich nicht gedacht hatte. Also fügte ich einen Embedding-basierten Recovery-Schritt hinzu: Wenn eine Formulierung aus der Stellenbeschreibung nah genug an etwas war, das bereits in meinem eigenen Vokabular stand, wurde sie befördert. Ich nahm an, ein einzelner Ähnlichkeits-Schwellenwert würde reichen, einmal justieren, weitermachen. Tat er nicht. Als ich ihn gegen fünf echte Stellenbeschreibungen kalibrierte — Tausende von Formulierungen —, überlappten sich die Ähnlichkeitswerte für bestätigt gute und bestätigt schlechte Beförderungen vollständig. Es gab keinen sauberen Schnitt. Die manuelle Durchsicht förderte echte Falsch-Positive zutage, direkt in der Mitte dieses Bereichs: "velocity" befördert zu "vector" bei 0,570, "documentation" zu "database" bei 0,587, das englische Verb "architect" absorbiert in das deutsche Substantiv "Architektur" bei 0,567 — ein Artefakt davon, dass das Vokabular bewusst deutsche Begriffe enthält, damit deutschsprachige Stellenbeschreibungen denselben Vorteil bekommen, was bedeutete, dass sich deutsche und englische Formulierungen den Embedding-Raum auf eine Weise teilten, die ich nicht vorhergesehen hatte. Ich hatte angenommen, Ähnlichkeitswerte würden sich sauber in "klar gut" und "klar schlecht" clustern. Tun sie nicht, nicht in diesem Umfang, nicht mit diesen Daten.
Die Entscheidung
Für das erste Problem erwog ich, dem Prompt zu vertrauen — "nutze nur, was relevant ist" — und verwarf das, weil ich den Fehlermodus schon gesehen hatte: Ein Modell, dem zehn Evidenzstücke gegeben werden, obwohl nur drei tatsächlich passen, verwirft nicht sieben, es rationalisiert die Nutzung aller zehn. Also wurde die Evidenzbewertung wirklich maßgeblich, nicht nur ein Vorschlag, den das Modell überstimmen konnte, und das Paket, das an Claude geht, ist auf acht Einträge gedeckelt — nicht auf Länge getrimmt, sondern weil ein ungedeckeltes Paket eine offene Einladung ist, Verbindungen zwischen Dingen zu konstruieren, die nie zusammen gelesen werden sollten.
Für das zweite Problem war klar, dass ein einzelner Schwellenwert nicht funktionieren würde, also teilte ich ihn in zwei: einen lockereren Schwellenwert (0,55) auf der Expansionsstufe, der den vollen diagnostischen Bereich für künftige Neukalibrierung erhält, und einen strengeren (0,65) an dem Punkt, an dem eine Beförderung tatsächlich für den Abruf vertraut wird. Alles dazwischen wird berechnet und dann verworfen. Ich musste auch entscheiden, ob ich das Schlüsselwort-Wörterbuch stattdessen weiter von Hand erweitere — habe ich nicht, weil ein Wörterbuch, das jede Formulierung im Voraus antizipieren muss, genau das Problem war, dem ich entkommen wollte.
Es gab eine dritte Entscheidung, kleiner, aber eine, die ich froh bin, bewusst getroffen zu haben statt per Standard: Als später ein geteilter structuredGenerate()-Wrapper für andere Claude-Aufrufstellen entstand, erwog ich, die Anschreiben-Generierung aus Konsistenzgründen dorthin zu migrieren. Auch das verwarf ich. Die Anschreiben-Generierung braucht eine Retry-Schleife, die gezielt bei der verbotenen Formulierung oder den Einstiegsregel-Verstößen erneut anfragt, die sie gerade begangen hat, und bei jedem Versuch mit dem genauen anstößigen Text eskaliert — eine Form, die structuredGenerate() nicht hat. Es hineinzuzwingen hätte entweder bedeutet, jeden anderen Aufrufer dieses Wrappers zugunsten eines einzigen Aufrufers zu verkomplizieren, oder eine anschreiben-förmige Ausweichmöglichkeit in eine Primitive einzubauen, deren ganzer Wert darin liegt, einfach zu sein. Die CV-Zusammenfassungsgenerierung dagegen hatte einen kleinen Nachbearbeitungsschritt, der in einen generischen Hook passte, den der Wrapper bereits unterstützte, also migrierte sie sauber. Dass zwei unterschiedliche Formen unterschiedlich blieben, war kein Kompromiss — es war einfach ehrlich gegenüber dem, was jede Aufrufstelle tatsächlich brauchte.
Die neue Architektur
Stellenbeschreibung
↓
Deterministische Extraktion (Schlüsselwörter + Capability-Kandidaten)
↓
Capability-Normalisierung (0,55 Expansion / 0,65 Vertrauen)
↓
Evidenzbewertung [maßgeblich, gedeckelt auf 8]
↓
Persona + Rhetorik-Plan (nur Rahmen, nie neuer Inhalt)
↓
Claude (nur Text, Retry-mit-Eskalation bei Verstößen)
↓
PDF (Python/ReportLab, deterministisches Layout)
Die CV-Anpassung nutzt dieselbe Pipeline-Ausgabe, engt aber ein, was Claude anfassen darf, auf nur Headline und Zusammenfassung — ein Validator läuft nach der Generierung genau deshalb, um sicherzustellen, dass sich sonst nichts verändert hat, weil ein CV ein faktisches Dokument ist, auf eine Weise, wie es der Anschreiben-Text nicht ist.
Was ich gelernt habe
Das Evidenzdeckel-Verhalten hat mich überrascht, als ich es das erste Mal live sah — ich hatte angenommen, ein gut geschriebener Prompt würde reichen, damit sich ein Modell selbst begrenzt, und das stimmt einfach nicht zuverlässig. Das Kalibrierungsergebnis hat mich noch mehr überrascht, weil es bedeutete, dass eine Annahme, von der ich nicht einmal wusste, dass ich sie traf — "Ähnlichkeitswerte trennen sich sauber" — schlicht falsch war, und ich habe das nur herausgefunden, weil ich tatsächlich gegen echte Daten kalibriert habe, statt eine Zahl zu wählen, die sich richtig anfühlte.
Ehrlich gesagt hätte ich den Schwellenwert kalibrieren sollen, bevor ich die erste Version ausgeliefert habe, nicht erst, nachdem ich Falsch-Positive in produktionsnahen Tests gefunden hatte. Es ist gut ausgegangen, weil ich es früh bemerkt habe, aber "einen Schwellenwert wählen, der vernünftig klingt" ist eine Gewohnheit, die ich mir künftig früher abgewöhnen möchte.
Der Blick nach vorn
Die Generierung des Verhaltensprofils läuft noch über die ältere manuelle Aufrufkette und wurde nicht zu structuredGenerate() migriert — nicht weil es nicht ginge, sondern weil bisher nichts die Frage erzwungen hat. Und ich möchte einen Test, der laut fehlschlägt, falls der Evidenzpaket-Deckel jemals versehentlich angehoben wird, statt mich darauf zu verlassen, dass allein die Funktion selbst ihn durchsetzt.
Fazit
Ein Modell überzeugend schreiben zu lassen, war nie der riskante Teil. Das Risiko lag immer darin, es entscheiden zu lassen, was wahr ist, was relevant ist, oder wo die Grenze zwischen "nah genug für eine Beförderung" und "nah genug, um falsch zu sein" verläuft — und am Ende ist jede Korrektur in dieser Pipeline nur dieselbe Grenze, noch einmal an einer etwas anderen Stelle gezogen.