12-Factor Agents: Muster für zuverlässige LLM-Anwendungen
(github.com/humanlayer)- 12-Factor Agents ist ein öffentlicher Leitfaden, der 12 Prinzipien für den Bau von LLM-basierter Software zusammenfasst, die zuverlässig genug ist, um sie Produktionskunden bereitzustellen
- Gute Agents seien weniger ein Muster nach dem Motto „Prompt und Tool-Bündel geben und bis zum Ziel iterieren“, sondern eher eine Struktur, bei der in überwiegend deterministische Software an den nötigen Stellen LLM-Schritte eingefügt werden
- Eine typische Agent-Schleife lässt das LLM den nächsten Schritt als strukturierten JSON-Tool-Call bestimmen; deterministischer Code führt ihn aus, fügt das Ergebnis dem Kontextfenster hinzu und wiederholt dies bis zum Abschluss
- Viele SaaS-Builder starten schnell mit einem Framework und erreichen 70–80 % Qualität, was für kundenorientierte Funktionen aber nicht ausreicht; daher müssten sie Framework, Prompts und Flows reverse-engineeren oder wieder von vorn beginnen
- Der schnellste Weg, hochwertige AI-Software zu Kunden zu bringen, bestehe darin, statt eines kompletten Agent-Frameworks kleine, modularisierte Agent-Baukonzepte in bestehende Produkte zu integrieren
Problemstellung des Projekts
- 12-Factor Agents ist ein öffentliches Projekt, das den Geist von 12 Factor Apps auf Prinzipien für den Bau von LLM-Anwendungen übertragen will
- Die Kernfrage lautet: „Welche Prinzipien können wir nutzen, um LLM-basierte Software zu entwickeln, die wirklich gut genug ist, um sie Produktionskunden anzuvertrauen?“
- Ausgangspunkt sind Erfahrungen mit verschiedenen Agent-Frameworks sowie Gespräche mit technischen Gründern innerhalb und außerhalb von YC
- Viele Gründer bauen für produktive, kundenorientierte Agents eher ihren eigenen Stack, statt stark auf Frameworks zu setzen
- Viele Produkte, die als „AI Agent“ bezeichnet werden, seien nicht vollständig agentisch, sondern überwiegend deterministischer Code, in den LLM-Schritte passend eingemischt werden
Grundlegende Sicht auf Agents
- Gute Agents bestehen nicht allein aus dem Muster „Prompt, Tool-Sammlung, Iteration bis zur Zielerreichung“
- Software lässt sich als gerichteter Graph (DG) betrachten; auch deshalb wurden Programme früher als Flussdiagramme dargestellt
- Seit etwa 20 Jahren sind DAG-Orchestratoren weit verbreitet
- Das Versprechen von Agents ist, dass Ingenieure nicht jeden Schritt und jede Ausnahme codieren müssen, sondern nur Ziel und Übergänge bereitstellen, während das LLM in Echtzeit den Pfad bestimmt
- Dieser Ansatz weckt die Erwartung, weniger Code zu schreiben, sich von Fehlern zu erholen und dem LLM neue Lösungswege zu ermöglichen
- In der Praxis funktioniere dieser Ansatz jedoch nicht so gut wie erhofft
Ausführungsmodell der Agent-Schleife
- Die grundlegende Agent-Schleife besteht aus LLM-Entscheidung → Tool-Ausführung → Ergebnis zum Kontext hinzufügen → Wiederholen
- Der Ablauf sieht so aus:
- Der initiale Kontext ist ein Startereignis wie eine Nutzernachricht, ein cron-Lauf oder ein Webhook
- Das LLM entscheidet über den nächsten Schritt oder darüber, ob der Vorgang abgeschlossen ist
- Der nächste Schritt wird als Tool-Call in strukturierter JSON-Form ausgegeben
- Deterministischer Code führt den Tool-Call aus
- Das Ausführungsergebnis wird dem Kontextfenster hinzugefügt
- Wenn der nächste Schritt
doneist, wird die finale Antwort zurückgegeben
- Das Beispiel im README zeigt eine Schleife, die mit
llm.determine_next_step(context)den nächsten Schritt bestimmt, ihn mitexecute_step(next_step)ausführt und das Ergebnis an den Kontext anhängt
Warum 12 Prinzipien nötig sind
- Beim Aufbau von HumanLayer wurden mit mindestens 100 SaaS-Buildern gesprochen, meist technische Gründer, die bestehende Produkte agentischer machen wollten
- Die typische Reise sieht so aus:
- Man entscheidet sich, einen Agent zu bauen
- Produktdesign und UX werden abgebildet, das zu lösende Problem wird festgelegt
- Um schnell voranzukommen, wird ein bestimmtes Framework gewählt
- Man erreicht ein Qualitätsniveau von 70–80 %
- Man erkennt, dass 80 % Qualität für die meisten kundenorientierten Funktionen nicht ausreichen
- Um über 80 % hinauszukommen, müssen Framework, Prompts, Flow usw. reverse-engineered werden
- Am Ende beginnt man wieder von vorn
- Diese Kritik soll weder Frameworks noch deren Entwickler angreifen; Frameworks hätten das AI-Ökosystem beschleunigt
- MCP wird nicht behandelt; die Beispiele verwenden überwiegend TypeScript, seien aber auch auf Python und andere Sprachen anwendbar
Die 12 Faktoren
- Auch wenn LLMs immer leistungsfähiger werden, blieben zentrale Engineering-Techniken bestehen, die LLM-basierte Software zuverlässiger, skalierbarer und wartbarer machen
- Die 12 Faktoren sind:
- Factor 1: Natural Language to Tool Calls: Natürliche Sprache in Tool-Calls umwandeln
- Factor 2: Own your prompts: Die eigenen Prompts selbst kontrollieren
- Factor 3: Own your context window: Das eigene Kontextfenster selbst kontrollieren
- Factor 4: Tools are just structured outputs: Tools sind lediglich strukturierte Ausgaben
- Factor 5: Unify execution state and business state: Ausführungszustand und Business-Zustand vereinheitlichen
- Factor 6: Launch/Pause/Resume with simple APIs: Mit einfachen APIs starten, pausieren und fortsetzen
- Factor 7: Contact humans with tool calls: Menschen per Tool-Call kontaktieren
- Factor 8: Own your control flow: Den eigenen Control Flow selbst kontrollieren
- Factor 9: Compact Errors into Context Window: Fehler komprimiert ins Kontextfenster einfügen
- Factor 10: Small, Focused Agents: Kleine, fokussierte Agents
- Factor 11: Trigger from anywhere, meet users where they are: Von überall aus triggern und Nutzer dort abholen, wo sie sind
- Factor 12: Make your agent a stateless reducer: Den Agent zu einem zustandslosen Reducer machen
- Als zusätzlicher Rat ist Factor 13: Pre-fetch all the context you might need enthalten
Anwendung und verwandte Materialien
- Die Einführung eines gesamten Frameworks, die faktisch auf ein Greenfield-Rewrite hinausläuft, könne kontraproduktiv sein
- Die Kernprinzipien, die Agents gut machen, könne man zwar größtenteils auch durch die Einführung eines Frameworks erhalten; der schnellere Weg, hochwertige AI-Software zu Kunden zu bringen, sei jedoch, kleinere, modularisierte Konzepte in bestehende Produkte zu integrieren
- Diese modularen Konzepte könnten auch erfahrene Software Engineers ohne AI-Hintergrund definieren und anwenden
- Als verwandte Materialien werden unter anderem Anthropics Building Effective Agents, Prompts are Functions, Library patterns: Why frameworks are evil und The Wrong Abstraction verlinkt
- Inhalte und Bilder stehen unter der Lizenz CC BY-SA 4.0, Code unter Apache 2.0
1 Kommentare
Kommentare auf Hacker News
Die Punkte in diesem Beitrag sind hervorragend. Ich habe auch eine Liste mit Erkenntnissen, die ich über mehrere Jahre praktischer Arbeit gesammelt habe: https://mg.dev/lessons-learned-building-ai-agents/
Wenn ich heute etwas Wichtiges ergänzen würde, dann: Besitze selbst den Planungs-Loop auf der niedrigsten Ebene. Dynamische Planung ist in Ordnung, aber man sollte den Beobachten–Orientieren–Entscheiden–Handeln-Loop (OODA) selbst kontrollieren und Heuristiken haben, um zu beurteilen, ob man auf eine Lösung konvergiert (z. B. Scoring), sowie Abbruchbedingungen (z. B. maximale Anzahl von Iterationen).
Außerdem lohnt es sich, über eine Workflow-Engine nachzudenken. Statt das Modell über mehrere Turns hinweg einen impliziten Workflow aufrechterhalten und vorantreiben zu lassen, ist es besser, das Modell eine Workflow-Spezifikation erzeugen zu lassen, die in dieser Engine ausgeführt wird, und bei Bedarf in jedem Schritt erneut das Modell aufzurufen.
Ich frage mich, wie Bibliotheken wie DSPY zu Factor 2 passen: https://dspy.ai/, https://github.com/humanlayer/12-factor-agents/blob/main/con...
Beim Lesen bin ich auf die Stelle gestoßen, dass Prompts mit BAML erzeugt werden. Persönlich fand ich es nicht einfach, Prompts von Hand zu schreiben, um aus unstrukturierten Daten strukturierte Informationen zu extrahieren, und mit DSPY habe ich bisher ziemlich gute Erfahrungen gemacht.
Wenn man die rohen Prompts von BAML verwendet: Wie sieht man dann den Ansatz, die rohen Prompts von DSPY zu verwenden? https://dspy.ai/tutorials/observability/#using-inspect_histo...
https://www.chrismdp.com/beyond-prompting/ Diesem Beitrag stimme ich nicht vollständig zu, aber der Vergleich Lochkarten → Assembly → C → Hochsprachen ist hier ziemlich nützlich.
Ich weiß noch nicht, wann die passende Abstraktion auftauchen wird, und ich glaube nicht, dass LangChain oder DSPY schon die „Programmiersprache C“ der KI sind. Eines Tages könnten sie es werden.
Im Moment würde ich eine Low-Level-Werkbank nutzen, mit der ich Tokens inspizieren, die Reihenfolge spezieller Tokens wie system/user/JSON ändern und mich schnell an Eigenheiten neuer Modelle anpassen kann, ohne festzustecken und auf Library-Support warten zu müssen.
Ein älterer, wenig bekannter Beitrag über Framework-Patterns hat mich meine ganze Karriere über begleitet, und ich denke, er gilt auch hier: https://tomasp.net/blog/2015/library-frameworks/
Aus den im Artikel beschriebenen Gründen und darüber hinaus sollte man LLMs, besonders in einer Phase wie jetzt, in der sich alles schnell verändert, eher wie Bibliotheken als wie Frameworks verwenden. Allerdings sind Frameworks sexier und leichter zu verkaufen und führen zu Lock-in und Zusatzdiensten, weshalb sie stärker beworben werden.
Ich habe unser eigenes „AI-Agent-Framework“ SecAI auf Basis des Actor Model, Zustandsmaschinen und aspektorientierter Programmierung gebaut und gerade veröffentlicht: https://github.com/pancsta/secai
Besonders Nr. 5 „Ausführungszustand und Business-Zustand zusammenführen“ und Nr. 8 „Den Kontrollfluss selbst besitzen“ gefallen mir. Der Kern von SecAI ist eine Graph-Control-Flow-Bibliothek; sie nutzt keinen DAG, sondern einen Multigraphen, und LLM-Aufrufe sind in Graphknoten eingebettet.
Der Flow wird durch Verhandlung, Abbruch und zustandsbehaftete Beziehungen erweitert und verhält sich dadurch organischer. Enthalten sind außerdem dedizierte Entwicklertools, die in anderen Frameworks häufig fehlen (dbg, repl, svg), Programmierung unter der Annahme von Fehlern, detaillierte Inspektion aller Schritte, automatischer Datenexport (Metriken, Traces, Logs, SQL) sowie einfache Integration (bash).
Die erste technische Demo ist ebenfalls veröffentlicht; sie zeigt die Entwicklertools anhand einer von AtomicAgents portierten deepresearch-Referenzimplementierung: https://youtu.be/0VJzO1S-gV0
Die Buttons Send/Stop sind im Grunde „Factor 6. Start/Pause/Fortsetzen über einfache APIs“, und durch Netzwerktransparenz ist es auch skalierbar.
Wenn man noch etwas hinzufügen wollte: Man sollte die Kosten bei Skalierung einplanen.
Solche Systeme sind bei größerem Maßstab nicht billig; wenn sich eine Aufgabe also mit deterministischen Komponenten erledigen lässt, sollte man das zuerst versuchen. Das reduziert nicht nur Halluzinationen und Latenz, sondern kann auch unterm Strich einen großen Unterschied machen.
Damit man den einzelnen Prinzipien leichter folgen kann, wäre eine konsistente Erzählung über mehrere Factors hinweg hilfreich. Wenn durchgehend ein möglichst realitätsnahes Beispielsystem verwendet würde, wäre es wahrscheinlich leichter zu verstehen.
Ich möchte das gemeinsam mit der Community offen weiterentwickeln.
Hervorragend. 80 % habe ich schon auf die harte Tour gelernt, und die restlichen 20 % dürften die Lektüre wert sein
Persönlich hatte ich mit der Kombination aus LangGraph + pydantic-Schema Erfolg. Mich würde auch interessieren, welche Tools andere nützlich eingesetzt haben
Das kommt genau zum richtigen Zeitpunkt
Ich experimentiere gerade mit einer audiovisuellen Sandbox-Idee. So etwas wie vvvv, aber viel einfacher und mit nur minimalem Funktionsumfang: https://kfs.mkj.lt/#audiovisllm, https://vvvv.org/
Die Idee ist, LM- oder einfache lokale neuronale Netzwerk-„Nodes“ einzufügen, die eine bestimmte Aufgabe übernehmen und deren Ausgabe stark eingeschränkt ist. Deshalb ist ein Beispiel wie „question -> answer: float“ sehr reizvoll. In meinem Fall können einige der Fragen ziemlich abstrakt sein, aber auch mehrstufige Pipelines finde ich interessant
Ich habe es nicht im Detail gelesen, aber ich möchte so viel deterministischen Code wie möglich schreiben und LLMs so wenig wie möglich einsetzen
So bekommt man meiner Ansicht nach vorhersehbare Ergebnisse, niedrige Betriebskosten und ein Signal, dass andere dieselbe App nicht so schnell nachbauen können. Statt modischen Klebstoff direkt zu übernehmen, um LLMs mit anderen Systemen zu verbinden, baue ich die Tools lieber selbst
Wenn diese Bedingungen nicht erfüllt sind oder nicht gebraucht werden, kann meiner Meinung nach jemand dieselbe Lösung im Handumdrehen per Vibe Coding nachbauen. Man muss die Kontrolle behalten. Ich bin bereit, auf diesem Hügel der Kontrolle zu sterben. Das heißt aber nicht, dass ich von LLMs nicht beeindruckt bin; ganz im Gegenteil