POC, wenn du kannst. LLM, wenn du musst: Architektur für KI-Systeme

Von hyretic

Die naheliegendste Architektur für ein System mit Sprachmodell ist, das Modell die Fäden ziehen zu lassen: Es soll den Ablauf planen, die Verzweigungen entscheiden und die Werkzeuge selbst wählen. Die Regel, die ein KI-System stattdessen trägt, ist kürzer und unbequemer, weil sie jede Zuweisung einzeln beantwortet: Code, wenn du angeben kannst, wie das Ergebnis entsteht. LLM, wenn du nur beschreiben kannst, wie ein gutes Ergebnis aussieht.

Key Takeaways (TL;DR)

  • Vor dem Modell zerlegen: Zerlege das Problem rekursiv in Verantwortlichkeiten, Orchestrierung ausdrücklich inklusive, und entscheide erst danach über die Implementierung.
  • Die Berechenbarkeitsfrage stellen: Lässt sich angeben, wie das Ergebnis berechnet wird, gehört deterministischer Code dahinter. Ein LLM bekommt nur Zuständigkeiten ohne definierbares Regelwerk.
  • Agenten-Runs klein halten: Ein Run, der viele Verantwortlichkeiten abdeckt, bricht mittendrin ab und verbrennt Tokens für Arbeit, die Code nahezu gratis erledigt.
  • Aktionen als Tools definieren: Alles, was auf die Welt einwirkt, bekommt der Agent als Tool mit wohldefiniertem Verhalten, vom Testlauf bis zum Commit.
  • Entscheidungen revidierbar halten: Prüfe vor jedem Wechsel beide Implementierungen gegen dieselben repräsentativen Inputs und dieselben Akzeptanzkriterien.

Basiert auf “Architecting with LLMs: use plain old code when you can, LLMs when you must” von Chris Richardson. Das Original findest du hier: https://microservices.io/post/architecture/2026/09/29/architecting-with-llms.html

Der goldene Hammer trifft jedes Problem

Um jede neue Technologie entsteht Hype, und Hype erzeugt ein bekanntes Anti-Pattern: den Golden Hammer, die Tendenz, ein glänzendes Werkzeug auf jedes Problem anzuwenden, egal ob es passt. GenAI-Agenten haben dieses Muster in Reinform durchlaufen, und je mehr sich der Hype legt, desto klarer wird, wo Agenten hingehören und wo gewöhnlicher Code die bessere Wahl ist.

Chris Richardson, Softwarearchitekt, Autor von Microservices Patterns und Betreiber von microservices.io, hat die Regel in seiner Artikelserie zum Coding agent sandwich formuliert, einer Architektur für Coding-Agenten aus einer Füllung von LLM-Aufrufen zwischen zwei Scheiben plain old code:

“Its practical rule is: use POC when you can, LLMs when you must.”

POC steht dabei für plain old code, nicht für Proof of Concept. Es meint schlicht deterministischen Code. POC ist die richtige Wahl, wenn sich angeben lässt, wie das Ergebnis berechnet wird: wenn die Regeln bekannt sind und sich Korrektheit präzise definieren lässt. Wer für ein solches Problem ein LLM bemüht, verschwendet Zeit, obwohl eine weit einfachere Lösung existiert.

Über die Passgenauigkeit hinaus bringt POC Wiederholbarkeit mit. Bei gleichen Eingaben und gleichem Zustand verhält es sich jedes Mal gleich, während ein LLM probabilistisch ist. Wiederholbarkeit macht POC auch leichter zu entwickeln und zu debuggen, weil Fehler reproduzierbar sind, und zur Laufzeit ist POC typischerweise deutlich schneller und günstiger als ein LLM-Aufruf.

Das LLM bekommt nur die Verantwortlichkeiten ohne Regelwerk

Ein LLM ist der Kandidat, wenn du angeben kannst, wie ein gutes Ergebnis aussieht, aber nicht, wie es zu berechnen ist. Das ist der Fall, wenn die Eingabe mehrdeutig oder unstrukturiert ist, wenn natürliches Sprachverständnis gefragt ist oder wenn das Ergebnis Urteil oder Interpretation verlangt. Für solche Probleme lassen sich deterministische Regeln nicht sinnvoll aufzählen. Richardson nennt fünf Fälle aus der Praxis: eine mehrdeutige operative Supportanfrage interpretieren, die Business-Intention eines Nutzers in eine Enterprise-Transaction übersetzen, komplexe vertragliche oder technische Anforderungen interpretieren, eine Software-Änderung aus einer natürlichsprachlichen Spezifikation implementieren und einen unbekannten Produktionsausfall diagnostizieren.

Diese Fähigkeiten haben einen Preis. Ein LLM-Aufruf ist im Vergleich zur Code-Ausführung langsam und teuer, und weil das Modell probabilistisch ist, verhält es sich bei wiederholten Aufrufen mit derselben Eingabe unterschiedlich. Bevor du dich festlegst, testest du das Modell deshalb gegen repräsentative Beispiele und prüfst Fehlerrate, Kosten und Latenz.

Erst zerlegen, dann zuweisen

Der Entwurf eines Systems mit LLMs beginnt mit rekursiver funktionaler Zerlegung. Du identifizierst die Zuständigkeiten, die das Problem lösen, und die Orchestrierung gehört ausdrücklich dazu: der Kontrollfluss, der entscheidet, welche Verantwortlichkeit als Nächstes ausgeführt wird. Die Zerlegung ist hierarchisch: Eine Verantwortlichkeit X zerfällt in X1 und X2 plus eine Koordinationsschicht, die beide orchestriert.

Das durchgespielte Beispiel ist der implement plan workflow: Er macht aus jedem Task eines Entwicklungsplans einen Git-Commit. Die Zerlegung identifiziert sieben Verantwortlichkeiten: den nächsten Task aus dem Plan holen, den Task implementieren, das Ergebnis validieren, den Commit pushen und einen Pull Request anlegen, auf den CI-Build warten, den CI-Build reparieren, falls er fehlschlägt, und Feedback aus dem Pull-Request-Review adressieren. Das Implementieren eines Tasks zerfällt weiter in Test schreiben, Code schreiben, Tests ausführen, Task als erledigt markieren und Änderungen committen. Die Orchestrierung ist die Schleife, die diese Schritte für jeden Task wiederholt, bis keiner übrig ist.

Erst danach wird pro Verantwortlichkeit entschieden: POC oder LLM. Eine Zuweisung ans LLM hältst du dabei eng umrissen. Der implement plan workflow ruft für jeden Task im Plan einen eigenen Coding-Agenten auf, statt einen einzigen Agenten-Run den ganzen Plan abarbeiten zu lassen.

Auch die Orchestrierung ist nur eine Verantwortlichkeit

Wenn ein System ein LLM enthält, liegt die Annahme nahe, das Modell solle es orchestrieren. Orchestrierung ist aber selbst eine Verantwortlichkeit, und dieselbe Entscheidung gilt für sie. POC-Orchestrierung passt, wenn sich die Schritte und die Verzweigungen dazwischen im Voraus definieren lassen. Der Orchestrator entscheidet, was als Nächstes ausgeführt wird, und ruft für eine Verzweigung, die Urteil verlangt, ein LLM auf, das einen der vordefinierten Zweige wählt. LLM-basierte Orchestrierung passt, wenn sich die Schritte nicht im Voraus definieren lassen. Das Modell entscheidet dann anhand von Zustand und bisherigen Ergebnissen, was es als Nächstes aufruft. Der implement plan workflow nutzt POC-Orchestrierung, die obere Brotscheibe des Sandwichs.

Wenn ein LLM jede nächste Aktion erst nach dem Ergebnis der vorherigen entscheidet, ist die Verantwortlichkeit als Agent implementiert: ein LLM, ein Harness und ein Satz Tools. Der Harness, etwa Claude Code, ist POC, der die Schleife fährt: Er ruft das LLM auf, führt jeden angeforderten Tool-Call aus und reicht das Ergebnis zurück. Das LLM entscheidet auch, wann es fertig ist, orchestriert aber nicht nur. Es erledigt einen Teil der Verantwortlichkeiten selbst und delegiert den Rest an Tools: Der Coding-Agent schreibt Tests und Code selbst und führt die Tests über Gradle aus. Der zuverlässige Agent sieht in Wahrheit nach überwiegend deterministischem Code aus, wie die Analyse zu Agent gleich Model plus Harness zeigt.

Dasselbe gilt für jede Aktion auf die Welt: Tests ausführen, Datenbank abfragen, API aufrufen. Jede Aktion ist eine Sub-Verantwortlichkeit mit bekannten Regeln und wird als POC-Tool mit wohldefiniertem Verhalten implementiert, das das LLM aufruft. Der Coding-Agent bedient sich Gradle für die Tests und Git für den Commit und entscheidet anhand der echten Testergebnisse, was als Nächstes passiert. Das ist die untere Brotscheibe des Sandwichs.

An der Grenze interpretieren, im Inneren ausführen

Angewandt auf jede Verantwortlichkeit tendiert die Regel dazu, LLMs an die Systemgrenzen zu setzen. Dort empfängt das System unstrukturierte, mehrdeutige Eingaben aus der realen Welt, die interpretiert werden müssen. Danach entsteht strukturierter Zustand, auf dem wohldefinierte Operationen arbeiten, und die sind POC.

Das Beispiel ist ein System für operative Supportanfragen. Jede Anfrage ist in natürlicher Sprache geschrieben und oft mehrdeutig. Ein LLM interpretiert sie und wandelt sie in ein strukturiertes Ticket um, das Kategorie, Priorität und betroffenen Service festlegt. POC validiert das Ticket, etwa ob der betroffene Service existiert, leitet ungültige Tickets an einen Menschen und routet die gültigen weiter ins Ticketsystem. Die Grenze dieser Validierung ist der eigentliche Punkt: Sie fängt ein Ticket, das einen nicht existierenden Service nennt. Sie fängt kein Ticket, das den falschen existierenden nennt. Genau deshalb bleibt der Mensch in der Kette, und genau deshalb braucht eine probabilistische Ausgabe deterministische Härtung, wie sie der Artikel zu härterem Engineering für probabilistische Systeme einfordert.

Nicht jede LLM-Verantwortlichkeit liegt an einer Grenze. Die LLM-Zuständigkeiten des implement plan workflow interpretieren Eingaben wie eine Task-Beschreibung, die Logs eines fehlgeschlagenen Builds oder Review-Kommentare. Aber ihr Hauptanteil ist Code schreiben, und der verlangt Urteil.

Ein Agent für den ganzen Plan wäre einfacher

Das stärkste Gegenargument gegen die ganze Konstruktion: Warum sieben Verantwortlichkeiten, kleine Agenten-Runs und ein POC-Gerüst, wenn ein einziger Run den kompletten Plan abarbeiten könnte und die Modelle ohnehin besser werden? Die Antwort ist empirisch, nicht ideologisch. Ein Aufruf oder Run, der viele Verantwortlichkeiten abdeckt, ist weniger zuverlässig, weil das Modell mittendrin abbrechen kann. Und er ist verschwenderisch, weil ein teures LLM Arbeit erledigt, die Code nahezu gratis erledigt.

Die Entscheidung ist dazu keine Einbahnstraße, sondern in beide Richtungen revidierbar. Beim ersten Implementieren fehlt oft noch das Verständnis, um die Berechnung anzugeben, also übernimmt das LLM. Wächst das Verständnis und lässt sich die Berechnung doch spezifizieren, macht die Reimplementierung in POC die Verantwortlichkeit schneller, günstiger und wiederholbar. Umgekehrt kann sich eine POC-Zuständigkeit als urteilsintensiv entpuppen: Die Eingaben sind vielfältiger als erwartet, und du addierst Regel um Regel für neue Fälle. Dann ist das LLM die einfachere Implementierung. Vor jedem Wechsel laufen beide Implementierungen gegen dieselben repräsentativen Inputs, und Ergebnisse, Kosten und Latenz werden an denselben Akzeptanzkriterien gemessen.

4 Schritte zur Umsetzung

  1. Verantwortlichkeiten inklusive Orchestrierung aufschreiben: Zerlege das Problem rekursiv, führe die Orchestrierung als eigene Verantwortlichkeit und kläre erst danach die Zuweisung an Code oder Modell.
  2. Pro Verantwortlichkeit die Berechenbarkeitsfrage beantworten: Lässt sich angeben, wie das Ergebnis berechnet wird, implementierst du Code. Lässt sich nur ein gutes Ergebnis beschreiben, testest du das LLM vorher gegen repräsentative Beispiele und prüfst Fehlerrate, Kosten und Latenz.
  3. Agenten-Runs klein halten und Aktionen als Tools definieren: Eine Verantwortlichkeit pro Run, jede Aktion auf die Welt als POC-Tool mit wohldefiniertem Verhalten, vom Testlauf bis zum Commit.
  4. Interpretationen an der Grenze validieren: Jede LLM-Ausgabe wird zu strukturiertem Zustand, Code validiert den Zustand, und ungültige Ergebnisse gehen an einen Menschen.

Die spannende Frage einer KI-Architektur ist nicht, wo das LLM sitzt. Es ist, wo keins sitzt.

Häufig gestellte Fragen (FAQ)

Was bedeutet POC in der Architektur mit LLMs? ↓

POC steht für plain old code, nicht für Proof of Concept. Es bezeichnet gewöhnlichen deterministischen Code, dessen Regeln bekannt sind und dessen Korrektheit sich präzise definieren lässt. POC ist wiederholbar, produziert reproduzierbare Fehler, ist leichter zu entwickeln und zu debuggen und zur Laufzeit schneller und günstiger als ein LLM-Aufruf.

Wann gehört eine Verantwortlichkeit zum Code und wann zum LLM? ↓

Code, wenn du angeben kannst, wie das Ergebnis berechnet wird. Ein LLM, wenn du nur beschreiben kannst, wie ein gutes Ergebnis aussieht, etwa bei mehrdeutigen oder unstrukturierten Eingaben, natürlichem Sprachverständnis oder Interpretation. Beispiele sind das Interpretieren einer Supportanfrage, das Übersetzen einer Business-Intention in eine Enterprise-Transaction oder das Diagnostizieren eines unbekannten Produktionsausfalls.

Soll das LLM die Orchestrierung des Systems übernehmen? ↓

Nicht automatisch. Orchestrierung ist selbst eine Verantwortlichkeit. POC-Orchestrierung passt, wenn sich die Schritte und Verzweigungen im Voraus definieren lassen; der Orchestrator kann dann ein LLM aufrufen, um einen der vordefinierten Zweige zu wählen. LLM-basierte Orchestrierung passt, wenn sich die Schritte nicht im Voraus definieren lassen.

Warum liegen LLMs oft an den Systemgrenzen? ↓

An einer Grenze empfängt ein System unstrukturierte, mehrdeutige Eingaben aus der realen Welt, die Interpretation verlangen. Danach entsteht strukturierter Zustand, auf dem wohldefinierte Operationen arbeiten, die als Code implementiert werden. Die Code-Validierung der LLM-Ausgabe fängt strukturelle Fehler, aber keine inhaltlichen, deshalb bleibt ein Mensch in der Kette.

Autor hyretic

Senior Full-Stack Developer mit Fokus auf stabiler Software-Architektur, pragmatischem Engineering und der Realität von KI im Entwickler-Alltag. Seine Wurzeln liegen im praktischen Lösen komplexer Probleme unter realen Bedingungen.

github.com/hyretic-dev

Ähnliche Artikel