Zurück zum Katalog
Season 48 20 Episoden 1h 21m 2026

LangChain v1.0 Orchestration Framework

v1.2 — 2026 Edition. Ein ausführlicher Audiokurs über das LangChain v1.0 Orchestration Framework. Baue zuverlässige Multi-Agenten-KI-Anwendungen mit standardisiertem Tool Calling, Structured Outputs, Human-in-the-Loop-Validierung und fortschrittlichem Context Engineering.

LLM-Orchestrierung AI/ML-Frameworks Multi-Agenten-Systeme
LangChain v1.0 Orchestration Framework
Aktuelle Wiedergabe
Click play to start
0:00
0:00
1
Die Ära der Orchestrierung
Wir untersuchen, warum sich LangChain von einem Wrapper zu einem vollständigen Orchestration Framework entwickelt hat. Du erfährst mehr über die Geschichte der LLM-Anwendungsentwicklung und wie das Release von v1.0 die Modellinteraktionen standardisiert.
3m 54s
2
Die vereinheitlichte Agenten-Abstraktion
Wir tauchen in die zentrale create_agent-Funktion ein, die die bisherigen Abstraktionen von LangChain vereint. Du lernst, wie der ReAct-Loop im Hintergrund arbeitet, um das Reasoning des Modells und die Tool-Ausführung zu steuern.
3m 47s
3
Das Chaos standardisieren
Wir untersuchen, wie LangChain Modellinteraktionen über verschiedene Provider hinweg standardisiert. Du lernst, wie man Chat-Modelle initialisiert und nahtlos zwischen OpenAI, Anthropic und Google wechselt.
3m 55s
4
Die universelle Sprache der LLMs
Wir zerlegen die grundlegende Kontexteinheit in LangChain: Messages. Du lernst, wie man System-, Human-, AI- und Tool-Messages strukturiert, um robuste Konversationsverläufe aufzubauen.
4m 06s
5
Agenten mit Tools ausstatten
Wir untersuchen, wie du deinen Modellen mithilfe des @tool-Decorators Aktionen beibringst. Du lernst, wie Type Hints und Docstrings automatisch in präzise JSON-Schemas für das Modell umgewandelt werden.
4m 14s
6
Tool-Kontext injizieren
Wir befassen uns damit, wie man Laufzeitinformationen direkt an Tools übergibt, ohne sie dem LLM preiszugeben. Du lernst, wie du den ToolRuntime-Parameter für sichere, per Dependency Injection bereitgestellte Konfigurationen nutzt.
3m 53s
7
Thread-Level-Persistenz
Wir behandeln das Kurzzeitgedächtnis und wie man den Konversationsverlauf beibehält. Du lernst, wie du Checkpointer an deinen Agenten anbindest, damit Konversationen pausiert, fortgesetzt und gespeichert werden können.
4m 15s
8
Kontext mit Middleware komprimieren
Wir untersuchen, wie du verhinderst, dass lange Konversationen dein Modell zum Absturz bringen. Du lernst, wie du die SummarizationMiddleware nutzt, um alte Nachrichten automatisch zu komprimieren und Token zu sparen.
3m 53s
9
Garantierte Datenformate
Wir besprechen, wie man Sprachmodelle dazu zwingt, strikte, vorhersehbare Datenstrukturen zurückzugeben. Du lernst den Unterschied zwischen ProviderStrategy und ToolStrategy zur Generierung von Pydantic-Modellen kennen.
3m 56s
10
Den Agent-Loop abfangen
Wir stellen das Middleware-Paradigma vor, das dir chirurgische Kontrolle über die Ausführung deines Agenten gibt. Du lernst, wie du wrap-style und node-style Hooks verwendest, um Modellaufrufe abzufangen.
3m 25s
11
Dynamisches Context Engineering
Wir tauchen in das Context Engineering ein, indem wir System-Prompts dynamisch generieren. Du lernst, wie du Middleware nutzt, um Anweisungen basierend auf der Rolle und Umgebung des aktuellen Benutzers zu ändern.
4m 04s
12
Sichere KI mit deterministischen Guardrails
Wir sichern unsere Agenten mit integrierter Middleware gegen Datenlecks ab. Du lernst, wie du die PIIMiddleware anwendest, um sensible Informationen automatisch zu schwärzen, bevor sie das Modell erreichen.
3m 49s
13
Pausieren für menschliche Freigabe
Wir untersuchen die Ausführung von Tools mit hohem Risiko, indem wir einen Menschen in den Prozess einbinden. Du lernst, wie du die Ausführung eines Agenten anhältst, um sensible Aktionen zu genehmigen, zu bearbeiten oder abzulehnen.
4m 33s
14
Echtzeit-Feedback von Agenten
Wir beschäftigen uns mit Streaming, um die User Experience drastisch zu verbessern. Du lernst, wie du Stream-Modi interpretierst, um Live-LLM-Tokens zusammen mit benutzerdefinierten Updates zur Tool-Ausführung anzuzeigen.
3m 43s
15
Sitzungsübergreifende Persistenz
Wir erforschen das Long-Term Memory, um Agenten zu bauen, die ihre Nutzer wirklich kennen. Du lernst, wie du LangGraph-Stores nutzt, um JSON-Dokumente über völlig unterschiedliche Konversationen hinweg zu speichern.
3m 40s
16
Das Multi-Agenten-Paradigma
Wir erklären, warum einzelne Agenten scheitern, und stellen die Subagents-Architektur vor. Du lernst, wie ein Haupt-Supervisor-Agent Subagents als isolierte Context Windows koordiniert, um Token-Bloat zu verhindern.
4m 18s
17
Zustandsgesteuerte Agenten
Wir untersuchen, wie Agenten ihr Verhalten dynamisch ändern können. Du lernst das Handoffs-Pattern zur Übergabe der Kontrolle und das Skills-Pattern zum bedarfsgesteuerten Laden spezialisierter Prompts kennen.
4m 04s
18
Benutzerdefinierte Workflows und Router
Wir verlassen den Standard-Agent-Loop. Du lernst, wie du LangGraph nutzt, um benutzerdefinierte Routing-Architekturen zu erstellen, die deterministische Logik mit nicht-deterministischem agentischem Reasoning mischen.
4m 25s
19
Agent-zu-Agent-Kommunikation
Wir erkunden den LangSmith A2A-Endpunkt. Du lernst, wie verteilte Agenten, die auf völlig unterschiedlichen Servern bereitgestellt sind, nativ über das A2A RPC-Protokoll von Google kommunizieren können.
4m 38s
20
Die Zukunft ist MCP
Wir blicken mit dem Model Context Protocol in die Zukunft, das den Zugriff von Agenten auf externe Tools standardisiert. Du lernst, wie du Remote-MCP-Server über Standard-Transports mit deinem Agenten verbindest.
5m 03s

Episoden

1

Die Ära der Orchestrierung

3m 54s

Wir untersuchen, warum sich LangChain von einem Wrapper zu einem vollständigen Orchestration Framework entwickelt hat. Du erfährst mehr über die Geschichte der LLM-Anwendungsentwicklung und wie das Release von v1.0 die Modellinteraktionen standardisiert.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 1 von 20. Es ist unglaublich einfach, einen Prototyp eines AI-Agenten zu bauen, aber bekanntermaßen schwierig, ihn so zuverlässig zu machen, dass man ihn in Production bringen kann. Die Kluft zwischen einer coolen Wochenend-Demo und einer Enterprise-Anwendung ist riesig. Die Lösung, um diese Lücke zu schließen, nennen wir die Orchestration Era. Lass uns zuerst ein sehr häufiges Missverständnis ausräumen. Leute verwechseln LangChain oft mit einem Model Provider. LangChain trainiert oder hostet keine Large Language Models und stellt sie auch nicht bereit. Es ist der Orchestration Layer, der direkt über diesen Models sitzt. Stell es dir als Kontrollzentrum vor, das steuert, wie deine Application mit dem Model interagiert, für das du dich entscheidest. Um zu verstehen, warum ein Orchestration Layer nötig ist, müssen wir uns ansehen, wie sich die Technologie entwickelt hat. Damals im Jahr 2022 war die Interaktion mit einem Language Model noch ganz einfach. Du hast einen String geschickt und als Antwort einen String zurückbekommen. Einfache Prompt Chains haben völlig ausgereicht, um den Job zu erledigen. Du brauchtest kein schwerfälliges Framework, um einen simplen Text-in, Text-out Workflow zu managen. Du konntest einfach ein Skript schreiben, bei dem der Output von Prompt A direkt in Prompt B gepackt wurde. Aber jetzt, wo wir uns durch 2025 bewegen und auf 2026 schauen, sieht die Landschaft völlig anders aus. Models verarbeiten nicht mehr nur Plain Text. Sie verarbeiten und generieren komplexe multimodale Blöcke. Eine einzige Interaktion kann das Routing eines User Prompts, das Triggern eines externen Tool Calls, das Verarbeiten eines Bildes und die Rückgabe eines strukturierten Datenblocks beinhalten. Ein Model liefert vielleicht die Anfrage für einen Database Lookup direkt zusammen mit einer Textzusammenfassung zurück. Wenn dein Application Code jede einzelne Response manuell prüfen muss, um herauszufinden, ob es ein String, ein Tool Call oder eine Bilddatei ist, wird deine Codebase schnell zu einem fragilen, unwartbaren Chaos. Hier ist die entscheidende Erkenntnis. Einem Model genau zur richtigen Zeit den exakt richtigen Context zu übergeben, ist viel schwieriger, als einfach das stärkste Model auf dem Markt auszuwählen. Du kannst die schlauste Reasoning Engine einbauen, die es gibt, aber wenn sie unsaubere, nicht standardisierte Daten bekommt, wird die komplette Interaktion fehlschlagen. Deshalb hat sich LangChain für das 1.0 Release von einer simplen Chaining Library zu einem standardisierten Orchestration Layer entwickelt. Es bietet ein Standard-Message-Format, das konsistent über alle großen Model Provider hinweg funktioniert. Anstatt für jede unterschiedliche API eine eigene Parsing-Logik zu schreiben, nutzt du eine einheitliche Struktur. Durch die Standardisierung des Message-Formats stellt LangChain sicher, dass ein Tool Call von einem Provider in deinem Code exakt genauso aussieht wie ein Tool Call von einem konkurrierenden Provider. Du definierst eine Sequenz, in die eine User Message reingeht. Der Orchestration Layer normalisiert sie, schickt sie an das Model, fängt die multimodale Response ab und übersetzt diese Response zurück in ein Standardformat, das deine Application auch wirklich nutzen kann. Du schreibst deine Application Logic nur einmal, und der Orchestration Layer übernimmt die Übersetzung. Das Model selbst ist nicht mehr die komplette Application, es ist lediglich die Reasoning Engine. Und der Orchestration Layer bestimmt, ob diese Engine dein Business-Problem auch wirklich löst. Wenn du uns dabei helfen möchtest, weiterhin diese Episoden zu machen, kannst du die Show unterstützen, indem du auf Patreon nach DevStoriesEU suchst. Das war's für diese Folge. Danke fürs Zuhören und keep building!
2

Die vereinheitlichte Agenten-Abstraktion

3m 47s

Wir tauchen in die zentrale create_agent-Funktion ein, die die bisherigen Abstraktionen von LangChain vereint. Du lernst, wie der ReAct-Loop im Hintergrund arbeitet, um das Reasoning des Modells und die Tool-Ausführung zu steuern.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 2 von 20. Was wäre, wenn du deinen gesamten komplexen Reasoning Loop durch einen einzigen, zehnzeiligen Function Call ersetzen könntest? Du verbringst Stunden damit, Custom Parser und While-Loops zu schreiben, nur damit ein Language Model zuverlässig eine Funktion auslöst. Die Unified Agent Abstraction ist die Architektur, die dir diese Arbeit abnimmt. Um zu verstehen, warum das wichtig ist, müssen wir ein häufiges Missverständnis bezüglich älterer Versionen des Frameworks ausräumen. In Version null Punkt x mussten Entwickler sich durch ein Labyrinth spezifischer Agent Classes navigieren. Du hattest Conversational Agents, Zero-Shot Agents und komplexe Custom Chains. Wenn du deinen Code upgradest, kannst du all das vergessen. Die Unified Agent Abstraction ersetzt alle alten Chains und Legacy Agents vollständig. Sie bietet einen klaren, standardisierten Entry Point über eine Funktion, die einfach create agent heißt. Diese Funktion existiert, um den ReAct Loop zu managen. ReAct steht für Reason and Act. Wenn ein User eine komplexe Frage stellt, kann ein Language Model nicht einfach Code ausführen. Es muss über das Problem nachdenken, sich für eine Action entscheiden, Text ausgeben, der diese Action anfordert, und dann auf eine Observation warten, bevor es wieder nachdenken kann. Diesen Cycle manuell zu handhaben, ist mühsam. Du musst den vom Model generierten Text parsen, ihn auf eine lokale Funktion mappen, diese Funktion ausführen, den Output formatieren, ihn wieder in das Model einspeisen und evaluieren, ob der Task abgeschlossen ist. Die create agent Funktion abstrahiert diesen gesamten Orchestration Process. Lass uns eine einfache Implementation mit einem Weather-Checking Tool durchgehen. Zuerst definierst du dein spezifisches Tool, vielleicht eine Funktion namens get weather, die einen Stadtnamen entgegennimmt. Als Nächstes initialisierst du dein gewähltes Language Model. Dann kommt die Abstraction. Du rufst die create agent Funktion auf und übergibst ihr drei Argumente. Du übergibst dein Language Model, eine Liste, die dein get weather Tool enthält, und einen System Prompt, der die Regeln für den Agent diktiert. Dieser einzelne Call gibt ein ausführbares Agent Object zurück. Schließlich rufst du dieses Object mit einer User Query auf und fragst nach dem aktuellen Wetter in London. Hier ist die wichtigste Erkenntnis über den Execution Flow. Wenn du den Agent aufrufst, startest du den ReAct Loop. Der Agent sendet die Query und die Tool Descriptions an das Model. Das Model entscheidet, dass es Echtzeitdaten braucht, und gibt einen standardisierten Tool Call aus. Die Agent Abstraction fängt diesen Call automatisch ab. Sie führt dein get weather Tool mit dem Argument London aus, nimmt die resultierenden Temperaturdaten und gibt sie als neue Observation an das Model zurück. Das Model evaluiert diese Daten, erkennt, dass es die Antwort auf die User Query hat, und generiert eine finale Response. Du hast keinen einzigen Loop und keinen Output Parser geschrieben. Du hast nur die Tools, das Model und die Instructions bereitgestellt. Die Power der Unified Agent Abstraction liegt in der Etablierung einer strikten Architectural Boundary. Sie isoliert die Mechanik des Reasoning Cycles vollständig, sodass du deinen gesamten Engineering Effort darauf verwenden kannst, die Qualität deiner Tools und die Klarheit deiner Prompts zu verfeinern. Das war es für diese Folge. Danke fürs Zuhören und keep building!
3

Das Chaos standardisieren

3m 55s

Wir untersuchen, wie LangChain Modellinteraktionen über verschiedene Provider hinweg standardisiert. Du lernst, wie man Chat-Modelle initialisiert und nahtlos zwischen OpenAI, Anthropic und Google wechselt.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 3 von 20. Unterschiedliche Model Provider haben extrem unterschiedliche APIs. Das bedeutet, dass du beim Ausprobieren eines neuen Models meistens die Hälfte deiner Application neu schreiben musst. Du bleibst dann bei einem Vendor hängen, nur weil der technische Aufwand für einen Wechsel zu hoch ist. Genau darum geht es in dieser Folge: dieses Chaos zu standardisieren. Bevor wir uns ansehen, wie LangChain das Ganze löst, sollten wir ein häufiges Missverständnis ausräumen. Wenn du mit frühen Language Models gearbeitet hast, kennst du wahrscheinlich noch die Legacy LLM Classes, die einen einzelnen, rohen Text-String als Input akzeptieren. Moderne Chat Models sind da anders. Sie erfordern zwingend eine strukturierte Sequence von Messages, wobei jeder Message eine bestimmte Role zugeordnet ist, wie zum Beispiel System, Human oder AI. Alles, was wir jetzt besprechen, bezieht sich auf diese modernen Chat Models, nicht auf die Legacy Text Completion Models. Wenn du eine Application baust, führt das Hardcoding eines bestimmten Providers sofort zu einem Vendor Lock-in. Um diese Dependency aufzubrechen, führt LangChain eine einzige Factory Function namens init chat model ein. Stell dir das wie einen universellen Übersetzer für die Initialisierung von AI Clients vor. Anstatt eine eigene Class für OpenAI, eine andere für Anthropic und noch eine für Google zu importieren, verlässt du dich ausschließlich auf diese eine Function. Hier ist der entscheidende Punkt. Die init chat model Function nutzt eine einfache String Syntax, um zu wissen, was sie bauen soll. Du übergibst einen String, der aus dem Provider-Namen, gefolgt von einem Doppelpunkt und der spezifischen Model-Version besteht. Stell dir einen Agent vor, der aktuell auf OpenAIs GPT-5 läuft. Du initialisierst dein Model einfach, indem du den String openai Doppelpunkt gpt-5 übergibst. Angenommen, Anthropic veröffentlicht ein neues Model, das Code Generation besser beherrscht, und du möchtest es testen. Weil du die init chat model Function verwendet hast, fasst du deine Agent Logic gar nicht erst an. Du importierst kein neues Client Package. Du änderst einfach nur diesen einen Initialization String in anthropic Doppelpunkt claude-sonnet-4-6. LangChain löst den String dynamisch auf und lädt die korrekte zugrundeliegende Integration Class. Damit wäre das Model selbst abgedeckt, aber die Provider sind sich auch bei den Configuration Settings uneinig. Eine API erwartet vielleicht einen Parameter namens max sampled tokens, während eine andere max length erwartet. Die init chat model Function löst das, indem sie Standard-Parameter akzeptiert. Wenn du dein Model initialisierst, kannst du Arguments wie temperature oder max tokens direkt an die Function übergeben. Wenn du deine temperature auf null Komma zwei und max tokens auf eintausend setzt, mappt LangChain diese generischen Begriffe auf die exakten Payload Keys, die von dem Provider verlangt werden, den du in deinem String angegeben hast. Du konfigurierst dein Model ein einziges Mal mit der Standard-Terminologie, und das Framework übersetzt es für die Ziel-API. Indem du deinen Application Code von Vendor-spezifischen Implementation Details trennst, gewinnst du architektonische Agilität und kannst konkurrierende Models in Sekunden statt in Tagen evaluieren. Das war's für diese Folge. Danke fürs Zuhören und keep building!
4

Die universelle Sprache der LLMs

4m 06s

Wir zerlegen die grundlegende Kontexteinheit in LangChain: Messages. Du lernst, wie man System-, Human-, AI- und Tool-Messages strukturiert, um robuste Konversationsverläufe aufzubauen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 4 von 20. Wenn du deinen Sprachmodellen immer noch einfache Plain-Text-Strings übergibst, schränkst du deine Applications stark ein. Plain Strings verlieren den Kontext. Sie können Image-Referenzen, Tool-Execution-Results oder verschiedene Interaktionsrollen nicht sicher speichern. Um das zu lösen, verwendet LangChain standardisierte Message-Objekte, die als universelle Sprache für LLMs fungieren. Eine Message in LangChain ist eine Datenstruktur, die eine spezifische Rolle, den Payload und optionale Metadaten enthält. Verschiedene API-Provider handhaben Conversation-Rollen und multimodale Inputs in ihren Raw-APIs unterschiedlich. LangChain abstrahiert diese Komplexität in vier verschiedene Klassen. Die erste ist die SystemMessage. Dieses Objekt legt die Hintergrundregeln, die Persona oder strenge Constraints für die Interaktion fest. Als Nächstes kommt die HumanMessage, die den Prompt des Users oder hochgeladene Files repräsentiert. Dann haben wir die AIMessage, die die vom Modell generierte Response erfasst. Und schließlich gibt es noch die ToolMessage. Dieses Objekt überträgt speziell das Ergebnis einer externen Function Execution zurück an das Modell und trennt so den rohen User-Input sauber von systemgenerierten, faktischen Daten. Du orchestrierst Conversations, indem du dem Modell ein Array dieser Message-Objekte übergibst. Du kannst dieses Array manuell zusammenbauen, um den Output zu formen. Zuerst erstellst du eine Liste und fügst eine SystemMessage ein, die dem Modell die Rolle eines streng formatierten Poesie-Experten zuweist. Als Zweites hängst du eine HumanMessage an, die nach einem Haiku über Database-Migrations fragt. Hier ist die entscheidende Erkenntnis: Du musst nicht warten, bis das Modell die nächste Response generiert. Du kannst manuell eine AIMessage instanziieren und sie direkt nach dem Human Prompt in das Array einfügen, versehen mit einer bestimmten Einleitungszeile. Wenn du dieses gesamte Array an das Modell übergibst, interpretiert es deine eingefügte AIMessage als sein eigenes bisheriges Verhalten. Es wird das Haiku nahtlos genau an deinem Startpunkt fortsetzen und sich an die Struktur halten, die du ihm aufgezwungen hast. Wenn du schließlich eine AIMessage vom Modell zurückbekommst, musst du extrahieren, was es tatsächlich produziert hat. Developer verwechseln häufig das raw content Attribut mit dem geparsten Payload. Jedes Message-Objekt hat eine content Property. Dieses raw content Attribut spiegelt jedoch direkt wider, was auch immer der jeweilige LLM-Provider zurückgegeben hat. Je nach Model-Provider und Prompt kann das ein einfacher Text-String sein, oder eine stark verschachtelte Liste von Dictionaries, die gemischte Text-Chunks, Image-URLs und Tool-Identifier enthalten. Das manuell zu parsen, macht deinen Code unglaublich fragil. Anstatt den raw content zu lesen, solltest du die content blocks Property verwenden. Die content blocks Property ist LangChains streng typisierte, standardisierte Repräsentation des Message-Payloads. Wenn du aus content blocks liest, übersetzt LangChain die Provider-spezifische Response in eine einheitliche Liste von Block-Objekten. Du kannst sicher über diese Liste iterieren. Zuerst prüfst du, ob ein Block ein Text-Block ist, und wenn ja, extrahierst du den Text-Payload. Als Nächstes prüfst du, ob es ein Tool-Call-Block ist, und extrahierst die Argumente. Deine Parsing-Logik um die standardisierte content blocks Property herum aufzubauen, ist der einzige Weg, um sicherzustellen, dass deine Application vollständig von den wechselnden Response-Formaten einzelner Model-Provider entkoppelt bleibt. Das war's für diese Folge. Danke fürs Zuhören, und keep building!
5

Agenten mit Tools ausstatten

4m 14s

Wir untersuchen, wie du deinen Modellen mithilfe des @tool-Decorators Aktionen beibringst. Du lernst, wie Type Hints und Docstrings automatisch in präzise JSON-Schemas für das Modell umgewandelt werden.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 5 von 20. Ein AI-Agent ohne Zugriff auf die Außenwelt ist nur ein Textgenerator. Um ihn in ein System zu verwandeln, das tatsächlich Arbeit erledigt, musst du ihm Hände geben. Heute sprechen wir darüber, wie wir Agents mit Tools ausstatten, genauer gesagt mit dem at-tool Decorator. Ein Tool in LangChain ist eine Brücke zwischen der Reasoning Engine eines Sprachmodells und deinen externen Systemen. Aber hier gibt es ein weit verbreitetes Missverständnis. Viele Entwickler gehen davon aus, dass das Sprachmodell irgendwie die Logik in ihrer Python-Funktion analysiert, um herauszufinden, wie es sie nutzen kann. Das tut es nicht. Das Sprachmodell sieht deinen Python-Code nie. Es sieht nur ein Schema, das die Funktion beschreibt. Um ein Tool zu erstellen, schreibst du eine Standard-Python-Funktion und setzt den at-tool Decorator direkt darüber. Dieser Decorator macht etwas Entscheidendes. Er analysiert deine Function Signature, extrahiert den Namen der Funktion, liest die Type Hints für jeden Parameter und parst den Docstring. Er nimmt all diese Metadaten und bündelt sie in einem strukturierten Format, das das Sprachmodell auch wirklich lesen kann. Weil das Modell nur dieses generierte Schema liest, ist Präzision in deinem Code extrem wichtig. Schauen wir uns ein Szenario an. Angenommen, du schreibst eine Funktion namens search database. Wenn du ihr einen schwachen Docstring gibst, der einfach nur sagt, durchsucht die Datenbank, und du die Type Hints komplett weglässt, ist das Sprachmodell im Blindflug unterwegs. Es weiß nicht, was für eine Art von Datenbank das ist, und es weiß nicht, welche Argumente es übergeben soll. Es könnte versuchen, einen kompletten, umgangssprachlichen Satz als Search Query zu übergeben, was dazu führt, dass deine Python-Funktion bei der Ausführung abstürzt. Hier ist die wichtigste Erkenntnis: Wenn du den at-tool Decorator verwendest, musst du deine Docstrings für das Sprachmodell schreiben, nicht für den menschlichen Entwickler. Statt einer vagen Beschreibung schreibst du eine klare Anweisung, wie zum Beispiel: Durchsucht die Kundendatenbank nach E-Mail-Adresse, um die bisherige Rechnungshistorie abzurufen. Als Nächstes wendest du strikte Type Hints auf deine Input-Parameter an. Du legst fest, dass das email Argument ein String sein muss. Du könntest dem Argument selbst sogar eine Beschreibung hinzufügen. Jede Type-Information, die du hinzufügst, gibt dem Sprachmodell engere Grenzen für das, was es generieren darf. Wenn du dieses neu dekorierte Tool an einen Agenten übergibst, liest der Agent das detaillierte Schema, bevor er irgendetwas anderes tut. Wenn ein User nach einer Kundenrückerstattung fragt, scannt der Agent seine verfügbaren Tools und erkennt anhand deines präzisen Docstrings, dass das search database Tool genau das Richtige ist. Wegen deines strikten Type Hints weiß er genau, wie er das Argument formatieren muss. Er extrahiert den email String aus dem User Prompt, stoppt seine Textgenerierung und gibt einen Tool Call aus. LangChain fängt diesen Tool Call ab. Es nimmt den vom Modell generierten email String, übergibt ihn an deine zugrundeliegende Python-Funktion und führt den Code aus. Deine Funktion kommuniziert mit der Datenbank, holt die Rechnungshistorie und gibt die Rohdaten direkt an LangChain zurück. LangChain füttert diese Daten dann als Observation zurück an den Agenten. Der Agent setzt seinen Denkprozess fort, aber jetzt hat er die echten Daten, die du gerade bereitgestellt hast. Die Handlungsfähigkeit des Sprachmodells ist komplett an die Qualität deiner Function Signature gebunden. Behandle deine Docstrings und Type Hints als strikte Engineering Constraints, denn für das Sprachmodell sind sie die einzigen Anweisungen, die existieren. Das war's für diese Folge. Danke fürs Zuhören und keep building!
6

Tool-Kontext injizieren

3m 53s

Wir befassen uns damit, wie man Laufzeitinformationen direkt an Tools übergibt, ohne sie dem LLM preiszugeben. Du lernst, wie du den ToolRuntime-Parameter für sichere, per Dependency Injection bereitgestellte Konfigurationen nutzt.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 6 von 20. Wenn du dich darauf verlässt, dass ein Language Model ein Authentication Token oder eine User Identity korrekt an ein Database Tool übergibt, riskierst du ein massives Sicherheitsrisiko. Das Modell weiß nicht, wer der aktuelle User ist, und man sollte ihm definitiv nicht vertrauen, das zu erraten. Du brauchst eine Möglichkeit, sensible Backend-Daten direkt an deine Tools zu übergeben und das Modell dabei komplett zu umgehen. Genau das löst Injecting Tool Context. Wenn du ein Tool baust, sind einige Argumente dafür gedacht, vom Modell generiert zu werden, wie ein Search String oder ein Date Range. Andere Argumente sind ausschließlich für deine Backend-Infrastruktur gedacht. Hier kommt das ToolRuntime Objekt ins Spiel. Es erlaubt dir, eine statische Configuration genau zum Zeitpunkt der Ausführung in ein Tool zu injecten. Du denkst vielleicht, du könntest einfach ein Configuration Dictionary als normales Tool-Argument übergeben und dem Prompt sagen, dass er es ignorieren soll. Mach das nicht. Wenn du in deiner Tool-Funktion einen Parameter namens config oder runtime definierst, behandelt LangChain diese als reservierte Keywords. Es versteckt sie absichtlich vor dem Tool Schema, das an das Language Model gesendet wird. Das Modell sieht sie niemals. Es sieht nur die Argumente, für die es selbst verantwortlich ist. Das bedeutet, das Modell kann keine Fake-Konfiguration halluzinieren oder versuchen, deine Security Boundaries zu umgehen. Stell dir ein konkretes Szenario vor. Du baust ein get account info Tool für eine Banking-Applikation. Das Tool braucht eine User ID, um die richtigen Datenbankeinträge abzurufen. Wenn das Modell diese ID bereitstellt, könnte eine clevere Prompt Injection das Modell austricksen, sodass es Daten für einen völlig anderen Kunden anfordert. Stattdessen designst du deine Tool-Funktion so, dass sie zwei Argumente akzeptiert. Das erste ist der Account Type, den das Modell bereitstellt. Das zweite ist ein Argument namens runtime. In deinem Main Application Code, bevor das Tool aufgerufen wird, befüllst du dieses runtime Objekt. Genauer gesagt nutzt du die runtime dot context Property. Du packst die tatsächliche, authentifizierte User ID der Person, die den Request macht, direkt in diesen Context. Du könntest dort auch eine aktive Database Connection oder eine regionale Endpoint-Adresse ablegen. Das Modell wertet den User Request aus und entscheidet sich, das get account info Tool aufzurufen. Es schaut sich das Schema an, sieht, dass es einen Account Type übergeben muss, und gibt das Wort savings aus. Es gibt sonst nichts aus. LangChain fängt diesen Execution Call ab. Es nimmt den Account Type vom Modell, kombiniert ihn nahtlos mit dem Runtime Context aus deinem Backend und führt die Python-Funktion aus. Innerhalb der Funktion extrahierst du die User ID aus dem Context und führst deine Database Query sicher aus. Dieser Mechanismus gibt dir sichere Dependency Injection. Du kannst alles injecten, was dein Tool zum Funktionieren braucht und was das Modell absolut nichts angeht. API Keys für Third-Party Billing Services, File System Paths oder Tenant Identifiers in einer Multi-Tenant-Architektur gehören alle in den Runtime Context. Hier ist die entscheidende Erkenntnis. Das Verstecken von Configuration Arguments hinter dem Runtime Context stellt sicher, dass dein Modell rein als Logic Router fungiert, während dein Application Code die absolute, uneingeschränkte Kontrolle über Data Access und Execution Security behält. Danke, dass du dir ein paar Minuten für mich Zeit genommen hast. Bis zum nächsten Mal, mach's gut.
7

Thread-Level-Persistenz

4m 15s

Wir behandeln das Kurzzeitgedächtnis und wie man den Konversationsverlauf beibehält. Du lernst, wie du Checkpointer an deinen Agenten anbindest, damit Konversationen pausiert, fortgesetzt und gespeichert werden können.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 7 von 20. Ohne Memory fühlt sich jede Interaktion mit deinem AI Agent an wie eine Szene aus 50 erste Dates. Das Model fängt komplett bei null an und vergisst alles, was du Sekunden vorher besprochen hast. Die Lösung ist Thread-Level Persistence. Large Language Models sind komplett stateless. Sie verarbeiten Text und geben Text zurück, ohne zwischen den Requests auch nur irgendwas zu behalten. Um eine Conversation zu führen, braucht ein Agent eine Möglichkeit, vergangene Interaktionen zu speichern und wieder abzurufen. Im Kontext einer einzelnen aktiven Session lösen wir das über Short-Term Memory, das als Teil des Agent State verwaltet und mithilfe von Checkpointern persisted wird. Leute denken oft, Memory in der AI wäre irgendeine interne Model Capability, bei der sich das neuronale Netz auf magische Weise an dich erinnert. Ist es aber nicht. Memory ist einfach nur Message History. Thread-Level Persistence bedeutet einfach nur, dass man die fortlaufende Liste von Messages nimmt, sie nach jedem Step in einer Database speichert und sie wieder in den Prompt einspeist, bevor das Model den nächsten Input sieht. Der Checkpointer managt das automatisch, sodass du die Storage- und Retrieval-Logik nicht manuell schreiben musst. In LangGraph wird der State pro Thread gespeichert. Ein Thread repräsentiert eine zusammenhängende Session. Um das zu aktivieren, brauchst du einen Checkpointer. Für Development und Testing kannst du den In Memory Saver verwenden. Wenn du deinen Agent Graph kompilierst, übergibst du dieses Saver-Objekt als Checkpointer-Argument. Diese Integration sagt dem Agent, dass er am Ende jeder Node Execution einen Snapshot von seinem aktuellen State machen und ihn an den Saver übergeben muss. Der State beinhaltet alles, was du in deinem Graph definiert hast, was typischerweise eine fortlaufende Liste von Messages ist. Schauen wir uns ein konkretes Szenario an. Du kompilierst deinen Agent mit einem In Memory Saver. Jetzt willst du den Agent invoken. Anstatt nur eine User Message zu übergeben, übergibst du auch ein Config-Objekt, das eine spezifische Thread-ID enthält. Nehmen wir den String-Wert conversation one. Du sendest die Message: Mein Name ist Bob. Der Agent empfängt das, generiert eine höfliche Begrüßung und ist fertig. Im Hintergrund speichert der Checkpointer den aktualisierten State, der jetzt die Message enthält, dass dein Name Bob ist, indexiert unter conversation one. Später invokest du den Agent ein zweites Mal. Du sendest eine neue Message und fragst: Was ist mein Name? Ganz wichtig: Du übergibst exakt dasselbe Config-Objekt mit der Thread-ID conversation one. Hier ist der entscheidende Punkt. Bevor der Agent deine neue Frage an das Model routet, fängt der Checkpointer den Prozess ab. Er sucht conversation one im In Memory Saver. Er holt sich den State Snapshot von deinem vorherigen Turn, lädt die gespeicherte Message History und hängt deine neue Frage ans Ende an. Das Language Model erhält den kompletten historischen Kontext, sieht die vorherige Message, in der du dich vorgestellt hast, und antwortet erfolgreich, dass dein Name Bob ist. Wenn du die Thread-ID auf conversation two ändern und nach deinem Namen fragen würdest, würde der Checkpointer nach dieser neuen ID suchen, keinen existierenden State finden und eine frische, leere Message-Liste initialisieren. Der Agent hätte keine Ahnung, wer du bist. Die Thread-ID ist der einzige Key, der eine Sequenz von isolierten, stateless Model Calls zu einer zusammenhängenden Short-Term Memory Session verbindet. Der Checkpointer abstrahiert die repetitive Arbeit, Message Arrays zu managen und Databases zu queryen, und garantiert so, dass dein Agent seine Arbeit genau dort fortsetzen kann, wo er aufgehört hat – solange du die richtige Thread-ID übergibst. Danke fürs Zuhören – bis zum nächsten Mal.
8

Kontext mit Middleware komprimieren

3m 53s

Wir untersuchen, wie du verhinderst, dass lange Konversationen dein Modell zum Absturz bringen. Du lernst, wie du die SummarizationMiddleware nutzt, um alte Nachrichten automatisch zu komprimieren und Token zu sparen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 8 von 20. Je länger eine Konversation läuft, desto stärker wird ein Large Language Model durch veraltete Informationen abgelenkt. Du verlierst an Genauigkeit, während du für jeden einzelnen Turn höhere Token-Kosten zahlst. Context-Komprimierung mit Middleware behebt genau dieses Problem. Wenn die Chat History wächst, stößt du irgendwann an das Limit des Context Windows von deinem Model. Schon bevor du dieses Hard Limit erreichst, verschlechtert das Füttern von tausenden Tokens aus alten Konversationen die Performance. Die Lösung ist die SummarizationMiddleware in LangChain. Anstatt alte Messages einfach abzuschneiden, komprimiert sie diese in einen einzigen Summary Block. Dadurch bleibt die semantische Bedeutung der Konversation erhalten, ohne den massiven Token Overhead. Es gibt ein weit verbreitetes Missverständnis darüber, wie das abläuft. Leute nehmen oft an, dass der primäre Agent die Summarization selbst durchführen muss. Das tut er nicht, und das sollte er auch wirklich nicht. Du willst, dass dein primärer Agent auf deinem schlausten, fähigsten Model läuft, um komplexe Logik zu verarbeiten. Summarization ist ein viel einfacherer Task. Du weist der SummarizationMiddleware exklusiv für diesen Job ein kleineres, günstigeres Model zu. Um die Middleware zu konfigurieren, musst du zwei Hauptparameter definieren. Der erste ist der Trigger. Der Trigger sagt der Middleware, wann sie eingreifen soll. Du könntest den Trigger so einstellen, dass er aktiviert wird, sobald der gesamte Token Count der Konversation 4000 Tokens erreicht. Der zweite Parameter ist die Keep Condition. Diese sagt der Middleware, wie viel vom aktuellen Context sie komplett in Ruhe lassen soll. Du könntest den Keep Value auf 20 setzen, was bedeutet, dass die 20 neuesten Messages unberührt bleiben. Hier ist der Logic Flow in der Praxis. Dein User chattet mit dem Main Agent. Die Konversation wächst. Beim nächsten Turn überschreitet die gesamte Message History die Grenze von 4000 Tokens. Noch bevor der primäre Agent den neuen User Input überhaupt sieht, fängt die SummarizationMiddleware den Request ab. Sie scannt die History und identifiziert alles, was älter als die 20 neuesten Messages ist. Sie nimmt diesen älteren Chunk der Konversation und übergibt ihn an dein dafür vorgesehenes kleineres Model. Sagen wir, du hast die Middleware so konfiguriert, dass sie gpt-4.1-mini nutzt. Dieses kleinere Model liest die alten Messages und generiert einen knappen Absatz, der zusammenfasst, was besprochen wurde. Die Middleware schreibt dann das History Array neu. Sie ersetzt all diese alten, einzelnen Messages durch eine einzige System Message, die die neue Summary enthält. Wenn es bereits eine ältere Summary aus einem vorherigen Compression Cycle gab, packt die Middleware diese mit in den Prompt, sodass die neue Summary das laufende Narrativ aktualisiert. Das finale Paket, das an deinen primären Agent gesendet wird, ist hochoptimiert. Es enthält die neue Summary Message, gefolgt von den 20 unkomprimierten aktuellen Messages, gefolgt vom neuesten User Input. Hier ist die wichtigste Erkenntnis. Der primäre Agent merkt nie, dass die History hinter den Kulissen komprimiert wurde. Er erhält einfach ein sauberes, hochrelevantes Context Window. Du bewahrst die langfristige semantische Bedeutung des Chats, hältst das Model fokussiert und senkst deine Token-Kosten bei jedem folgenden Turn drastisch. Wenn du diese Episoden hilfreich findest und die Show unterstützen willst, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören, und keep building!
9

Garantierte Datenformate

3m 56s

Wir besprechen, wie man Sprachmodelle dazu zwingt, strikte, vorhersehbare Datenstrukturen zurückzugeben. Du lernst den Unterschied zwischen ProviderStrategy und ToolStrategy zur Generierung von Pydantic-Modellen kennen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 9 von 20. Software zu bauen, die darauf basiert, Natural Language Responses mit Regular Expressions zu parsen, ist eine tickende Zeitbombe. Du fragst ein Language Model nach einem simplen Data Object, und es liefert dir perfekte Daten – allerdings packt es noch eine höfliche Begrüßung an den Anfang und wrappt das Ganze in Markdown-Formatierung. Dein Parser crasht sofort. Guaranteed Data Formats sind die dauerhafte Lösung dafür. Structured Output zwingt das Language Model, Informationen genau so zurückzugeben, wie deine Application sie erwartet. Es verwandelt unvorhersehbare Textgenerierung in zuverlässige Software Objects. Stell dir ein System vor, das eingehende Customer-Support-Nachrichten verarbeitet. Ein User schickt einen chaotischen, unstrukturierten Absatz, in dem er sich über ein Login-Problem beschwert, aber seinen Namen, seine E-Mail-Adresse und seine Telefonnummer irgendwo im Text vergräbt. Du brauchst genau diese drei Daten, um einen Database Lookup zu triggern. Anstatt einen komplexen Prompt zu schreiben und das Model anzuflehen, seine Response richtig zu formatieren, definierst du ein Standard-Pydantic-Model. Du erstellst eine Class namens ContactInfo und definierst Name, E-Mail und Telefon als Required Fields. Dann übergibst du dieses Pydantic-Schema einfach an den Response-Format-Parameter deiner Language-Model-Configuration. Du musst keine Beispiele mitgeben oder Custom Validation Scripts schreiben. Und jetzt kommt der entscheidende Teil. Wenn du dieses Pydantic-Schema übergibst, ermittelt LangChain automatisch den zuverlässigsten Weg, es zu enforcen. Das macht es, indem es im Hintergrund still und heimlich zwischen zwei verschiedenen Execution Paths wählt. Zuerst checkt es, ob dein gewähltes Language Model ein offizielles Structured-Output-Feature in seiner API eingebaut hat. Wenn ja, wählt LangChain automatisch die Provider Strategy. Diese Strategy pusht dein Schema direkt zum Provider und nutzt dessen native, serverseitige Constraints, um das Output-Format zu garantieren. Aber Hardware ändert sich und Models werden ausgetauscht. Wenn du dich entscheidest, ein anderes Model zu nutzen, dem nativer Structured Output fehlt, erkennt LangChain diese Capability Gap. Es macht automatisch einen Fallback auf die Tool Strategy. Under the hood übersetzt es dein ContactInfo-Schema in eine Function Signature. Es erzählt dem Model von einem Fake-Tool, das exakt einen Namen, eine E-Mail-Adresse und eine Telefonnummer braucht, um zu laufen. Das Model versucht, dieses Tool aufzurufen, und generiert dabei exakt die strukturierten Argumente, die du brauchst. Dein Application-Code muss sich nie ändern, um diesen Swap mitzumachen. Wenn die Operation abgeschlossen ist, suchen Developer oft an der falschen Stelle nach ihren Daten. Du nimmst vielleicht an, dass der Output als Raw Text zurückkommt, den du noch parsen musst. Es ist kein Raw Text. LangChain fängt die Payload ab und instanziiert das Pydantic-Object für dich. Es packt dieses vollständig validierte Python-Object direkt in deinen Application State. Du findest es im structured response Key deines State Dictionarys. Du referenzierst einfach diesen Key, und schon hast du dein ContactInfo-Object mit typsicheren Fields, bereit, um es an den Rest deiner Application weiterzugeben. Indem die Last der Schema Validation von der Custom Parsing Logic in den Framework Layer verlagert wird, werden deine Language-Model-Integrations so vorhersehbar wie ein Standard-API-Call. Danke fürs Zuhören – bis zum nächsten Mal.
10

Den Agent-Loop abfangen

3m 25s

Wir stellen das Middleware-Paradigma vor, das dir chirurgische Kontrolle über die Ausführung deines Agenten gibt. Du lernst, wie du wrap-style und node-style Hooks verwendest, um Modellaufrufe abzufangen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 10 von 20. Wenn dein Agent in Production ohne Fehlermeldung fehlschlägt, liegt das oft daran, dass du nicht überwachst, was zwischen den Schritten seiner Reasoning Loop passiert. Das Modell stürzt ab, die Loop bricht ab, und du starrst auf einen unvollständigen Run. Indem du die Agent Loop mit Custom Middleware abfängst, holst du dir die Kontrolle zurück. Wenn ein Agent einen ReAct-Zyklus ausführt, gibt er die Kontrolle ständig an das Language Model und wieder zurück. Middleware bietet Hooks, um deine Logik genau dann auszuführen, wenn du sie während dieses Austauschs brauchst. Es gibt zwei Hauptarten von Hooks, die du nutzen wirst: Node-Style Hooks und Wrap-Style Hooks. Ein häufiger Fehler ist, sie als austauschbar zu betrachten. Node-Style Hooks laufen sequenziell ab. Wrap-Style Hooks umschließen die Ausführung komplett und können Exceptions abfangen. Node-Style Hooks nutzen Decorators namens before model und after model. Wenn du einen before model Hook an eine Funktion hängst, führt das Framework deine Logik komplett aus und triggert erst danach die Language Model API. Wenn das Modell antwortet, läuft ein after model Hook. Diese Hooks sind super, um den exakten Prompt zu loggen, der an die API geschickt wird, um Context zu injecten oder um fehlerhafte Zeichen aus dem finalen Text-Output zu entfernen. Aber weil sie strikt nacheinander laufen, bieten sie keinen Schutz vor Fehlern. Wenn die Language Model API in einen Timeout läuft, wird dein after model Hook niemals ausgeführt. Der Fehler bubbelt nach oben und lässt die komplette Agent Loop abstürzen. Und jetzt kommt der wichtige Teil. Wenn du Instabilität abfangen musst, nutzt du einen Wrap-Style Hook. Der Decorator dafür ist wrap model call. Ein Wrap Hook legt sich komplett um die Modellausführung. Deine Funktion läuft, macht ein bisschen Setup und gibt dann die Kontrolle explizit an das Modell ab. Weil dein Custom Code den eigentlichen Network Call wrappt, kannst du diese Ausführung in Standard-Error-Handling-Strukturen packen. Stell dir vor, du baust eine wrap model call Middleware, um API Rate Limits mit einer Exponential Backoff Retry Loop abzufangen. Du schreibst eine Funktion, die mit wrap model call dekoriert ist. Innerhalb dieser Funktion erstellst du eine Retry Loop. Du packst den Befehl, der die Kontrolle an das Modell übergibt, in einen Try Block. Wenn das Modell erfolgreich ist, fängst du die Response ab, gibst sie zurück und die Loop ist beendet. Wenn das Modell einen Error wirft, fängt dein Catch Block ihn ab. Anstatt den Agent fehlschlagen zu lassen, triggert dein Catch Block eine Pause. Du berechnest ein kurzes Delay, wartest und lässt die Loop den Call dann erneut versuchen, wobei sich das Delay jedes Mal verdoppelt. Der Agent Orchestrator bekommt von den Fehlern gar nichts mit. Die Middleware fängt die Exceptions ab, managt die Retry-Logik komplett isoliert und übergibt eine erfolgreiche Response sauber an die Haupt-ReAct-Loop, wenn es am Ende klappt. Node-Style Hooks bereiten die Inputs vor und formatieren die Outputs, aber Wrap-Style Hooks schützen die Ausführung. Das war's für diese Folge. Bis zum nächsten Mal!
11

Dynamisches Context Engineering

4m 04s

Wir tauchen in das Context Engineering ein, indem wir System-Prompts dynamisch generieren. Du lernst, wie du Middleware nutzt, um Anweisungen basierend auf der Rolle und Umgebung des aktuellen Benutzers zu ändern.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 11 von 20. Der Hauptgrund, warum dein Agent scheitert, ist nicht, dass das zugrundeliegende Model dumm ist. Es liegt daran, dass du ihm den falschen Kontext für den Job gegeben hast. Wenn dein System einen Superuser und einen Gast exakt gleich behandelt, ist deine Application blind für die Realität. Um das zu fixen, nutzen wir Dynamic Context Engineering. Lass uns zuerst ein weit verbreitetes Missverständnis darüber aufklären, wie Prompts gebaut werden. Dynamic Context ist nicht der Base System Prompt, den du schreibst, wenn du deinen Agent anfangs im Code definierst. Dieser anfängliche System Prompt ist komplett statisch. Dynamic Context Engineering ist der Prozess, diesen Prompt on the fly anzupassen, nur Millisekunden bevor das Model tatsächlich aufgerufen wird. Beim Context Engineering geht es darum, dem Language Model genau die Regeln zu geben, die es für einen bestimmten User in einem bestimmten Moment braucht – und nicht mehr. Wenn du versuchst, jede mögliche Regel in einen einzigen riesigen statischen Prompt zu stopfen – und dem Model sagst, wie es sich verhalten soll, wenn der User ein Admin ist, und wie, wenn er ein Viewer ist, und wie, wenn heute Dienstag ist –, verschwendest du Tokens und verwirrst das Model. Stattdessen willst du dynamisch nur die Regeln injecten, die genau jetzt wichtig sind. In LangChain wird das über einen speziellen Decorator namens dynamic underscore prompt gelöst. Du platzierst diesen Decorator über einer Python-Funktion, die du definierst. Wenn deine Application eine Query empfängt und die Chain triggert, pausiert LangChain. Es sucht nach jeder Funktion, die mit diesem Decorator gewrappt ist, und führt sie aus, bevor es mit dem Model spricht. Innerhalb deiner dekorierten Funktion brauchst du einen Weg, um zu wissen, was gerade passiert. Hier liest du aus request dot runtime dot context. Dieses Context-Objekt ist im Grunde ein Dictionary. Es enthält alle Live-Metadaten, die in die Chain übergeben wurden, als du sie invoked hast. Du kannst dort alles aus deinem Application Backend reinpacken, was du willst, wie zum Beispiel User IDs, Session States, Feature Flags oder Access Levels. Lass uns ein konkretes Szenario anschauen. Du schreibst eine Funktion namens context aware prompt und wrappst sie mit dem dynamic prompt Decorator. Innerhalb dieser Funktion liest du die User Role aus dem Runtime Context. Du checkst die Rolle. Wenn der User ein Admin ist, hängt deine Funktion einen bestimmten Textblock an den System Prompt an, der dem Language Model sagt, dass es die volle Erlaubnis hat, destruktive Commands zurückzugeben. Wenn der User ein Viewer ist, hängt deine Funktion einen anderen Textblock an, der dem Model strikte Anweisungen gibt, dass es nur Read-Only Summaries zurückgeben darf und niemals Configuration Changes vorschlagen darf. Jetzt ziehst du dir eine zweite Information aus dem Runtime Context, nämlich den Environment State. Du checkst, ob das Environment auf Production gesetzt ist. Wenn das der Fall ist, hängt deine Funktion eine strenge Sicherheitswarnung ganz ans Ende vom System Prompt an, die vom Model verlangt, seinen Output auf Sicherheit zu double-checken. Wenn das Environment nur Staging ist, überspringst du das Anhängen dieser Warnung komplett. Hier ist die wichtigste Erkenntnis. Deine Funktion nimmt den statischen Base Prompt, klebt die Admin- oder Viewer-Regeln dran, hängt bei Bedarf die Production-Warnung an und gibt den finalen String zurück. LangChain nimmt diesen fertig zusammengebauten String und sendet ihn an das Language Model. Das Language Model weiß nie, dass der Prompt zusammengebastelt wurde. Es sieht einfach nur ein hochspezifisches, perfekt zugeschnittenes Set an Anweisungen. Dadurch hältst du deine System Prompts schlank, präzise und absolut relevant für den unmittelbaren Request. Du hörst auf zu hoffen, dass das Model errät, welche Regeln gelten, und fängst an, exakt die Regeln durchzusetzen, die für den aktuellen State deiner Application erforderlich sind. Ich möchte mir kurz die Zeit nehmen, dir fürs Zuhören zu danken – das hilft uns sehr. Mach's gut!
12

Sichere KI mit deterministischen Guardrails

3m 49s

Wir sichern unsere Agenten mit integrierter Middleware gegen Datenlecks ab. Du lernst, wie du die PIIMiddleware anwendest, um sensible Informationen automatisch zu schwärzen, bevor sie das Modell erreichen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 12 von 20. Ein einziges Chat Log mit einer ungeschwärzten Kreditkartennummer kann die Compliance deiner gesamten Application sofort gefährden. Du kannst dich nicht darauf verlassen, dass ein Language Model sensible Daten höflich ignoriert, und das Model zu bitten, sich selbst zu zensieren, ist langsam und unvorhersehbar. Hier kommt Safe AI mit Deterministic Guardrails ins Spiel. Deterministic Guardrails sind hardcodierte, regelbasierte Checks. Sie basieren auf vorhersehbaren Patterns und Logik, wie Regular Expressions oder festen Algorithmen, anstatt ein anderes Language Model mit der Textauswertung zu beauftragen. Weil sie den Network Call an eine AI umgehen, werden sie in Millisekunden ausgeführt und kosten praktisch nichts. Wenn du für Production baust, ist dieser deterministische Layer für die Security absolut Pflicht. Im Framework implementierst du das mit der PII Middleware. Ein häufiger Fehler von Developern ist der Versuch, sensible Informationen nachträglich zu filtern, indem sie den Output des Models scannen. Aber um die User Privacy zu schützen, ist die PII Middleware so designt, dass sie die rohe Message abfängt, genau in dem Moment, in dem der User auf Senden klickt. Sie verarbeitet den Text, bevor der Model Call überhaupt initiiert wird. Du konfigurierst dieses Verhalten explizit, indem du den Parameter apply to input auf true setzt. Gehen wir mal ein Customer Service Agent Szenario durch. Ein gestresster User schickt eine Message, dass sein Account gesperrt ist, inklusive seiner persönlichen E-Mail-Adresse, und dann fügt er seine komplette sechzehnstellige Kreditkartennummer ein, um seinen Kauf zu verifizieren. Wenn dein Code diesen rohen String an einen Third-Party AI Provider weitergibt, hast du gegen grundlegende Data Compliance verstoßen. Du brauchst eine Strategie, um den Text zu neutralisieren, und die Middleware gibt dir drei Built-in Actions: block, redact und mask. Wenn du die block Strategie nutzt, fungiert die Middleware als harte Wand. In dem Moment, in dem sie das Kreditkartenformat erkennt, wirft sie einen strikten Error und beendet die Chain komplett. Der Request wird direkt abgelehnt. Wenn du die redact Strategie wählst, entfernt die Middleware die spezifischen Daten chirurgisch und setzt einen sauberen Placeholder ein. Die persönliche E-Mail-Adresse wird komplett aus dem String gelöscht und durch das Wort email in Klammern ersetzt. Das Language Model liest immer noch einen zusammenhängenden Satz und versteht, dass eine E-Mail angegeben wurde, aber die eigentlichen Daten sind weg. Die dritte Strategie ist mask. Masking behält einen sicheren Teil der Originaldaten bei. Die Middleware ersetzt die ersten zwölf Ziffern der Kreditkarte durch Sternchen und lässt nur die letzten vier Zahlen sichtbar. Das ist extrem effektiv, wenn dein Backend-System einen Account verifizieren muss, ohne den kompletten Financial Record offenzulegen. Um das zu implementieren, musst du die Middleware konfigurieren, bevor deine Chain läuft. Du instanziierst die PII Middleware und übergibst ihr eine Liste von Target Entities. In diesem Fall gibst du email und credit card an. Dann weist du diesen Entities deine gewählten Strategien zu, vielleicht wählst du redact für die E-Mail und mask für die Karte. Zum Schluss hängst du diese Middleware-Komponente an deine Main Chain an und stellst sicher, dass du den Parameter setzt, um sie auf den Input anzuwenden. In dem Moment, in dem der User seine Message abschickt, bereinigen die deterministischen Regeln den Text, und die AI erhält nur einen bereinigten Prompt. Hier ist die entscheidende Erkenntnis. Der sicherste Weg, sensible persönliche Informationen in einer generativen AI-Architektur zu handhaben, ist zu garantieren, dass das Language Model sie gar nicht erst zu Gesicht bekommt. Das war's für diese Folge. Danke fürs Zuhören und keep building!
13

Pausieren für menschliche Freigabe

4m 33s

Wir untersuchen die Ausführung von Tools mit hohem Risiko, indem wir einen Menschen in den Prozess einbinden. Du lernst, wie du die Ausführung eines Agenten anhältst, um sensible Aktionen zu genehmigen, zu bearbeiten oder abzulehnen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 13 von 20. Ein autonomer Agent ist unglaublich leistungsstark – bis zu dem Moment, in dem er völlig autonom einen Entwurf deiner Finanzdaten an den falschen Kunden mailt. Manche Aktionen sind einfach zu riskant, um sie auszuführen, ohne dass ein Mensch noch mal drüberschaut. Genau deshalb nutzen wir Pausing for Human Approval. Agents führen Tools automatisch basierend auf User Prompts aus. Dieses Verhalten ist ideal, um Daten zu lesen, aber es ist gefährlich bei destruktiven oder irreversiblen Aktionen. Wir brauchen eine Möglichkeit, die Execution zu pausieren, einen Menschen zu fragen, ob eine Aktion sicher ist, und sie dann fortzusetzen oder abzubrechen. Bevor wir über die Mechanik sprechen, müssen wir eine häufige Fehlerquelle aus dem Weg räumen. Engineers konfigurieren manchmal Interrupts und wundern sich dann, warum der Agent einfach crasht oder neu startet. Du musst einen Checkpointer aktiviert haben. Du kannst einen Agenten nicht pausieren, wenn er sich nicht merken kann, wo er stehen geblieben ist. Das komplette Memory des Agenten und sein aktueller Fortschritt müssen im Persistence Layer gespeichert werden, während er auf die Antwort eines Menschen wartet. Kein Checkpointer bedeutet keine Pause. Wenn die Persistence aktiv ist, kannst du die Tool Execution mit der Human In The Loop Middleware sicher handhaben. Stell dir ein Setup vor, in dem dein Agent zwei Tools hat: ein Search Tool und ein Delete Database Tool. Du willst, dass der Agent frei suchen kann, aber du willst absolut nicht, dass er ohne Erlaubnis Tabellen droppt. Wenn du diese Middleware konfigurierst, setzt du ein Argument namens interrupt on. Du übergibst ihm die genauen Namen der Tools, die überwacht werden müssen. In unserem Szenario konfigurierst du interrupt on so, dass es nur auf das Delete Database Tool achtet. Das Search Tool wird von der Middleware ignoriert und sofort ausgeführt, wann immer der Agent es aufruft. Wenn der Agent jedoch entscheidet, dass er das Delete Database Tool nutzen muss, fängt die Middleware den Request ab. Sie pausiert den Graph, speichert den aktuellen State in deinem Checkpointer und hält die Execution komplett an. Der Graph ist nun im Persistence Layer suspendiert und wartet auf menschliches Eingreifen. Der menschliche Operator überprüft den ausstehenden Tool Call und hat drei Möglichkeiten, auf die Middleware zu antworten. Die erste Entscheidungsmöglichkeit ist Approve. Der Mensch schaut sich die Parameter an, die der Agent generiert hat, stimmt zu, dass sie korrekt sind, und sendet einen Approve-Befehl. Der Graph wacht auf und führt die Löschung exakt so aus, wie der Agent es ursprünglich geplant hat. Die zweite Entscheidungsart ist Reject. Der Operator sieht, dass der Agent versucht, das falsche Target zu löschen, und sendet einen Reject. Das Tool wird nicht ausgeführt. Stattdessen erhält der Agent eine Observation, die anzeigt, dass die Aktion von einem Menschen blockiert wurde. Der Agent verarbeitet dieses Feedback dann und kann entweder einen anderen Ansatz versuchen oder den User um Klärung bitten. Hier ist die wichtigste Erkenntnis. Die dritte Option ist Edit. Manchmal liegt der Agent größtenteils richtig, macht aber einen kleinen Fehler, wie zum Beispiel Production anstelle von Staging als Target Environment zu setzen. Anstatt die Aktion komplett zu rejecten und den Agenten zu zwingen, das Problem erneut zu durchdenken, kann der Operator die Tool Input Parameter direkt modifizieren. Der Mensch ändert das Target Environment auf Staging und schickt den korrigierten Call ab. Der Agent macht weiter und führt die Aktion mit den modifizierten Parametern aus, sodass es reibungslos vorangeht. Indem du diese Middleware nutzt, schützt du dein System vor gefährlichen Fehlern. Pausing for Human Approval verhindert nicht nur Katastrophen, es verwandelt deinen Agenten von einer unberechenbaren Entität in einen überwachten Collaborator, der auch High-Stakes-Operationen sicher handhaben kann. Das war's für diese Folge. Danke fürs Zuhören und keep building!
14

Echtzeit-Feedback von Agenten

3m 43s

Wir beschäftigen uns mit Streaming, um die User Experience drastisch zu verbessern. Du lernst, wie du Stream-Modi interpretierst, um Live-LLM-Tokens zusammen mit benutzerdefinierten Updates zur Tool-Ausführung anzuzeigen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 14 von 20. Nutzer haben nichts dagegen, zehn Sekunden auf eine komplexe Antwort zu warten, solange du ihnen zeigst, was das Gehirn in diesen zehn Sekunden macht. Ein leerer Bildschirm fühlt sich an wie eine kaputte Application. Die Lösung für diese gefühlte Latenz ist Real-Time Agent Feedback. Um den leeren Bildschirm zu fixen, stellt LangChain einen Parameter namens stream mode bereit, wenn du deinen Agent oder Graph ausführst. Er steuert genau, welche Art von Daten der Agent über die Connection zurücksendet, während er läuft. Der erste Modus, den du kennen musst, ist der messages mode. Dieser kümmert sich um den klassischen Typing-Effekt. Er streamt die raw Tokens vom Language Model, während sie generiert werden. Wenn das Model einen Absatz schreibt, empfängt deine Application die Text Chunks nacheinander. So kann sich dein User Interface flüssig updaten, anstatt auf den kompletten Textblock zu warten. Leute verwechseln oft das Streamen von final answer Tokens mit dem Streamen von intermediate reasoning. Das sind zwei völlig verschiedene Dinge. Wenn dein Agent entscheidet, ein Search Tool aufzurufen, stoppt die Token-Generierung. Das Language Model wartet darauf, dass das Tool fertig wird. Wenn dieses Tool fünf Sekunden braucht, friert dein User Interface für fünf Sekunden ein. Der messages mode allein verrät dem User nicht, was der Agent im Hintergrund eigentlich macht. Er zeigt nur, was das Language Model gerade sagt. Um das Problem der stillen Tools zu lösen, nutzt du den custom mode. Der custom mode erlaubt es deinen Tools und internen Nodes, ihre eigenen Real-Time Status Updates direkt in den Stream zu senden. Um das zu implementieren, nutzt du eine LangChain Utility namens get stream writer. Du rufst diese Funktion innerhalb deines Tool-Codes auf. Sie gibt dir ein writer object, mit dem du an jedem Punkt während der Tool-Ausführung custom events zurück an den Client senden kannst. Stell dir ein langsames Wetter-Tool vor. Dein Agent empfängt einen Prompt, der nach der Vorhersage fragt, und entscheidet sich, das Wetter-Tool aufzurufen. Innerhalb der Python-Funktion für dieses Tool schnappst du dir den stream writer. Wenn das Tool anfängt, eine langsame remote API abzufragen, nutzt du den writer, um ein custom event mit einem Status wie Acquired data zu senden. Dein Frontend empfängt dieses custom event sofort und zeigt einen Loading Spinner mit diesem Text an. Der User weiß, dass der Agent arbeitet. Sobald die remote API die Daten zurückgibt, ist das Tool fertig und das Language Model übernimmt wieder die Kontrolle. Es nimmt die raw Wetterdaten, formuliert eine menschenfreundliche Response, und der messages stream schaltet sich wieder ein, um die finale Vorhersage auf den Bildschirm zu tippen. Hier ist der entscheidende Punkt. Du musst dich nicht für nur einen Modus entscheiden. Du kannst eine Liste, die sowohl messages als auch custom enthält, an den stream mode Parameter übergeben. LangChain führt die Language Model Tokens und deine custom Tool Logs automatisch zu einem einzigen, kontinuierlichen Feed zusammen. Dein Frontend checkt einfach den event type, wenn er ankommt. Ist es ein custom event, aktualisierst du den Status Indicator. Ist es ein message event, hängst du das Token an die Chat Bubble an. Die gefühlte Latenz sinkt auf null, weil das System ständig mit dem User spricht. Wenn du helfen willst, dass weitere Episoden kommen, kannst du die Show unterstützen, indem du auf Patreon nach DevStoriesEU suchst. Danke fürs Zuhören und happy coding zusammen!
15

Sitzungsübergreifende Persistenz

3m 40s

Wir erforschen das Long-Term Memory, um Agenten zu bauen, die ihre Nutzer wirklich kennen. Du lernst, wie du LangGraph-Stores nutzt, um JSON-Dokumente über völlig unterschiedliche Konversationen hinweg zu speichern.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 15 von 20. Um einen wirklich personalisierten Assistenten zu bauen, muss er sich merken, dass du kurze Antworten bevorzugst – selbst wenn du ihm das vor drei Wochen in einem komplett anderen Chat gesagt hast. Wenn du dich ausschließlich auf das Standard-Conversation-Memory verlässt, verschwindet diese Präferenz in dem Moment, in dem du einen neuen Thread startest. Der Mechanismus, der diese Amnesie verhindert, ist Cross-Session Persistence über das Store-Paradigma. Viele Entwickler verwechseln den Checkpointer mit dem Store. Hier ist der Unterschied. Ein Checkpointer verwaltet den kurzfristigen State. Er merkt sich einen einzelnen Conversation Thread. Wenn der User einen neuen Chat erstellt, fängt der Checkpointer bei null an. Der Store überwindet diese Thread-Grenzen. Er erlaubt es deinen Agents, Informationen global zu persistieren und abzurufen, über alle Interaktionen mit einem bestimmten User hinweg. Im Kern ist das Long-Term Memory in LangChain einfach nur ein hierarchischer Key-Value Store. Er persistiert JSON-Dokumente. Die Hierarchie basiert auf Namespaces. Ein Namespace ist eine Sequenz von Strings, die sich exakt wie ein Ordnerpfad auf deinem Computer verhält. Wenn du Profildaten speichern willst, nutzt du vielleicht einen Namespace, der den String users enthält, gefolgt von der User ID. Innerhalb dieses Namespaces speicherst du Items. Jedes Item braucht einen eindeutigen String Key und ein Dictionary, das den JSON-Wert repräsentiert. Hier wird es interessant. Tools interagieren mit diesem Store direkt über den Runtime Context. Du übergibst den Store niemals manuell über deinen Graph State. Stell dir ein Custom Tool namens save user info vor. Seine Aufgabe ist es, eine gesprochene Sprachpräferenz zu erfassen. Beim Setup initialisierst du deine Applikation mit einem Store Backing, zum Beispiel einem In-Memory Store für lokales Testing. Innerhalb deiner Tool-Logik greifst du direkt aus der injizierten Runtime Configuration auf die Store-Instanz zu. Du extrahierst die User ID aus dem aktuellen Context. Dann rufst du die put-Methode auf dem Store auf. Du übergibst das Namespace-Tuple, das das Wort users und die User ID enthält. Du definierst einen Key, wie language preference, und übergibst schließlich das JSON Dictionary mit dem Wert, vielleicht Spanisch. Der Store persistiert dieses Dokument. Wochen später startet der User eine komplett neue Conversation. Der Thread State ist leer. Aber weil der Agent Zugriff auf ein Retrieval Tool hat, kann er die get-Methode auf dem Runtime Store mit genau demselben Namespace und Key aufrufen. Er zieht sich das JSON-Dokument, liest die Präferenz und antwortet sofort auf Spanisch. Die Trennung von kurzfristigem Conversational Context und langfristigem Factual Memory hält deine Applikation schlank. Der Checkpointer bläht sich nicht mit jahrelanger User History auf, und der State bleibt sauber. Der Store lädt nur die spezifischen JSON-Dokumente, die der Agent explizit abrufen will. Context und Persistence als zwei völlig getrennte Systeme zu behandeln, ist der einzige Weg, einen Agent zuverlässig zu skalieren. Der Checkpointer speichert die Gegenwart, der Store die Vergangenheit. Das war's für heute. Danke fürs Zuhören – und jetzt bau etwas Cooles.
16

Das Multi-Agenten-Paradigma

4m 18s

Wir erklären, warum einzelne Agenten scheitern, und stellen die Subagents-Architektur vor. Du lernst, wie ein Haupt-Supervisor-Agent Subagents als isolierte Context Windows koordiniert, um Token-Bloat zu verhindern.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 16 von 20. Wenn dein einzelner AI Agent aufgrund seiner riesigen Liste an Tools und konkurrierenden Instructions anfängt zu scheitern, bringt es nichts, einfach ein größeres Context Window darauf zu werfen. Es ist an der Zeit, kein monolithisches Script mehr zu bauen, sondern ein Team einzustellen. Genau da kommt das Multi-Agent Paradigm ins Spiel. Wir bauen Multi-Agent Systems, weil Single Agents an eine kognitive Wand stoßen. Gib einem Agent dreißig Tools, fünf Seiten System Prompts und eine lange Conversation History, und er wird den Fokus verlieren. Er wird das falsche Tool aufrufen oder Constraints vergessen. Der Multi-Agent-Ansatz bricht das Ganze herunter. Er ermöglicht Distributed Development, bei dem verschiedene Teams unterschiedliche Agents verwalten. Er erlaubt Parallel Execution. Und am wichtigsten: Er erzwingt eine strikte Context Isolation. Heute konzentrieren wir uns auf eine spezifische Architektur namens Subagents Pattern. Dabei gibt es einen Main Supervisor Agent, der Tasks an spezialisierte Subagents delegiert. Leute verwechseln einen Supervisor oft mit einem simplen Router. Ein Router ist nur eine statische Funktion, die sich eine Query ansieht und sie über einen festen Pfad weiterleitet. Ein Supervisor ist ein aktiver, denkender Agent. Er verwaltet den Conversation State, entscheidet über mehrere Turns hinweg, welche Subagents aufgerufen werden sollen, und synthetisiert ihre Responses. Hier ist die wichtigste Erkenntnis: Subagents bieten perfekte Context Isolation. Wenn der Supervisor einen Subagent bittet, etwas zu tun, bootet der Subagent mit einem komplett sauberen Context Window. Er hat nur die spezifischen Instructions und Tools, die er für genau seinen Job braucht. Der Subagent macht vielleicht Fehler, ruft Tools dreimal auf und füllt sein eigenes Scratchpad, während er die Antwort herausfindet. Der Supervisor sieht dieses Chaos nie. Er empfängt nur das finale, bereinigte Result. Das schützt deinen Main Agent vor Context Bloat und verhindert Hallucination. Um den Supervisor mit den Subagents zu verbinden, wrappst du die Subagents als Tools. Es gibt zwei Wege, das in LangChain zu tun. Die erste Methode ist Tool-per-Agent. Du gibst dem Supervisor ein spezifisches Tool für jeden Subagent. Wenn du fünf Subagents hast, hat der Supervisor fünf Tools. Die zweite Methode ist ein Single-Dispatch Tool. Hier bekommt der Supervisor genau ein Tool, das zum Beispiel Delegate Task heißt. Dieses Tool erfordert zwei Inputs: den Namen des Target Agents und die Task Description. Stell dir ein Single-Dispatch-Szenario vor. Du hast einen Main Agent, einen Research Agent und einen Writer Agent. Ein User fragt nach einem komplexen Market Report. Der Main Agent entscheidet, dass er zuerst Daten braucht. Er ruft das Single-Dispatch Tool auf und übergibt den Research Agent als Target und die Market Query als Payload. Der Research Agent startet in seinem eigenen isolierten Context, durchsucht das Web, parst Dokumente und gibt einen Summary Paragraph zurück. Der Main Agent empfängt diesen Text. Als Nächstes ruft der Main Agent das Dispatch Tool erneut auf, diesmal mit dem Writer Agent als Target, und übergibt die Research Summary und Formatting Instructions. Der Writer Agent entwirft den finalen Report und gibt ihn an den Main Agent zurück, der ihn an den User ausliefert. Du kannst diese Subtasks je nach Bedarf unterschiedlich ausführen. Du kannst Subagents synchron ausführen, wobei der Supervisor darauf wartet, dass der Research Agent fertig wird, bevor er eine andere Action ausführt. Wenn du unabhängige Tasks hast, wie das Recherchieren von drei verschiedenen Konkurrenten, kannst du die Subagents asynchron ausführen. Der Supervisor dispatcht alle drei Tasks auf einmal, sie werden parallel ausgeführt, und der Supervisor wartet darauf, dass alle zurückkommen, bevor er weitermacht. Tasks in Subagents zu gruppieren, dient nicht nur dazu, deinen Code zu organisieren. Es geht darum, strikt zu kontrollieren, was das Language Model zu jedem Zeitpunkt im Memory halten muss. Das war's für diese Folge. Danke fürs Zuhören und keep building!
17

Zustandsgesteuerte Agenten

4m 04s

Wir untersuchen, wie Agenten ihr Verhalten dynamisch ändern können. Du lernst das Handoffs-Pattern zur Übergabe der Kontrolle und das Skills-Pattern zum bedarfsgesteuerten Laden spezialisierter Prompts kennen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 17 von 20. Du musst das Gehirn deines Agents nicht von vornherein mit jedem möglichen Szenario überfrachten. Fünfzig Seiten Anweisungen in einen einzigen System Prompt zu packen, macht dein Model nur verwirrt, langsam und teuer. Du musst ihm lediglich beibringen, zum richtigen Zeitpunkt nach dem passenden Handbuch zu fragen. Das ist der Kernmechanismus hinter State-Driven Agents. State-Driven Agents arbeiten nach einem einfachen Prinzip. Das Verhalten des Agents ändert sich dynamisch, basierend auf dem aktuellen State der Anwendung. Wir lösen das mit zwei Haupt-Patterns: Skills und Handoffs. Beide Patterns nutzen Tools, um State-Variablen zu aktualisieren, die wiederum bestimmen, was als Nächstes im Workflow passiert. Schauen wir uns zuerst das Skills-Pattern an. Bei diesem Pattern geht es um die schrittweise Offenlegung von Wissen. Anstatt einem Agent gleich zu Beginn alle Anweisungen zu geben, gibst du ihm ein Tool. Wenn der Agent entscheidet, dass er mehr Informationen braucht, um ein Problem zu lösen, ruft er dieses Tool auf. Das Tool wird ausgeführt, aber es macht mehr, als nur einen String an das Model zurückzugeben. Es aktualisiert eine bestimmte State-Variable in deiner Anwendung. Deine Orchestration Layer überwacht diesen State. Sobald sie die Änderung erkennt, fügt sie für den nächsten Turn dynamisch neue Anweisungen oder Fähigkeiten in den System Prompt des Agents ein. Nehmen wir einen typischen Customer Support Agent. Am Anfang ist sein einziger Job herauszufinden, was der Kunde will. Ein User fragt nach einem kaputten Produkt. Der Agent ruft ein Tool auf, um eine Garantie-ID zu erfassen. Die Ausführung dieses Tools aktualisiert eine State-Variable, um anzuzeigen, dass ein Garantieanspruch aktiv ist. Die Anwendung liest diesen neuen State und lädt dynamisch einen speziellen Refund-Skill in den Prompt. Dieser Skill enthält vielleicht die spezifischen Regeln für die Bearbeitung von Retouren und den Zugriff auf eine sichere Inventar-Datenbank. Die Fähigkeiten des Agents haben sich mitten in der Konversation weiterentwickelt, komplett gesteuert durch ein State-Update. Was ist nun, wenn die geforderte Aufgabe selbst mit neuen Skills zu komplex für den ursprünglichen Agent ist? Genau da kommt das Handoff-Pattern ins Spiel. Handoffs nutzen ebenfalls Tools, um den State zu aktualisieren, aber anstatt neue Anweisungen in den aktuellen Agent zu laden, überträgt die State-Änderung die Kontrolle an einen völlig anderen Agent. Zurück zu unserem Szenario. Der Support-Agent erfasst die Garantie-ID, aber anstatt die Rückerstattung selbst zu bearbeiten, ruft er ein Handoff-Tool auf. Dieses Tool aktualisiert eine Routing-Variable im State und ändert den aktiven Agent vom Triage-Bot zu einem Specialist-Agent, der ausschließlich für hochwertige Retouren gedacht ist. Die Orchestration Layer sieht diese State-Änderung und leitet den nächsten Schritt des Workflows an den Specialist weiter. An diesem Übergangspunkt bricht oft alles zusammen. Beim Handoff zwischen Agents braucht der neue Agent den Kontext der Konversation. Viele Entwickler versuchen, die History aufzuräumen, indem sie einfach die rohen User-Messages an den neuen Agent übergeben. Mach das nicht. Beim Handoff zwischen Agents musst du die AI-Message mit dem eigentlichen Tool Call, der den Handoff initiiert hat, und die resultierende Tool-Message, die den Handoff bestätigt, mitgeben. Wenn du den Tool Call und die Tool-Message aus dem Message-Array entfernst, bricht die Conversation History. Das neue Model verliert die logische Kette der Ereignisse. Es wird nicht wissen, wie es dorthin gekommen ist, und wahrscheinlich Fragen wiederholen, die der User bereits beantwortet hat. Übergib immer die lückenlose Message-History. Hier ist die entscheidende Erkenntnis. Der State ist nicht nur ein passiver Memory Store, sondern die Control Plane, die genau diktiert, wozu dein System in jeder einzelnen Millisekunde in der Lage ist. Das war's für diese Folge. Danke fürs Zuhören und viel Spaß beim Entwickeln!
18

Benutzerdefinierte Workflows und Router

4m 25s

Wir verlassen den Standard-Agent-Loop. Du lernst, wie du LangGraph nutzt, um benutzerdefinierte Routing-Architekturen zu erstellen, die deterministische Logik mit nicht-deterministischem agentischem Reasoning mischen.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 18 von 20. Manchmal willst du nicht, dass ein AI Agent frei entscheidet, was er als Nächstes tun soll. Du willst einfach, dass er einen strikten, deterministischen Flowchart abarbeitet. Custom Workflows und Router geben dir genau dieses Level an Kontrolle. Wenn du dich ausschließlich auf einen Standard Agent Loop verlässt, vertraust du darauf, dass das Language Model jeden Schritt selbst herausfindet. Es durchsucht vielleicht eine Datenbank, merkt, dass es mehr Daten braucht, sucht nochmal und antwortet schließlich. Das ist zwar mächtig, aber unvorhersehbar und oft langsam. Custom Workflows in LangGraph lassen dich aus diesem Loop ausbrechen. Du kannst die Karte selbst zeichnen. Du kannst deterministische Logik, wie das Ausführen von exakten Data Retrieval Scripts, nahtlos mit nicht-deterministischem Agent Reasoning mischen. Du packst das Language Model in eine strikte Sequence of Events. Bevor wir einen bauen, müssen wir eine häufige Verwechslung zwischen einem Router und einem Supervisor klären. Ein Supervisor orchestriert aktiv eine Multi-Turn Conversation. Er beobachtet die Agents beim Reden, entscheidet, wer als Nächstes spricht, und managt den Dialog über die Zeit. Ein Router ist das nicht. Ein Router ist einfach nur ein Classification Step. Er schaut sich den Input an, entscheidet, welchen Pfad der Workflow nehmen soll, routet die Daten, und sein Job ist erledigt. Er kann stateless oder stateful sein, aber er ist kein Conversational Manager. Schauen wir uns ein konkretes Szenario an. Du baust ein Multi-Source Knowledge Base Tool. Ein User stellt eine Frage, und die Antwort könnte in GitHub Pull Requests, Slack Threads oder in beidem begraben sein. Du willst nicht, dass ein einzelner Agent blind rät, wo er suchen soll. Du willst einen strukturierten Workflow. Zuerst erstellst du eine Routing Node. Du übergibst die User Query an ein Language Model und bittest es, eine einfache Liste von Destinations auszugeben. Wenn es in der Query um einen aktuellen Bugfix geht, gibt das Model vielleicht die Wörter GitHub und Slack aus. Das ist der Teil, auf den es ankommt. Du musst nicht nur einen Pfad auswählen. Du kannst mehrere Agents zur exakt selben Zeit über die Send API ausführen. In LangGraph gibt deine Routing Function, anstatt eines einzelnen nächsten Schritts aus deiner Conditional Logic, eine Liste von Send Commands zurück. Jeder Command verknüpft eine Destination Node mit den spezifischen Daten, die sie braucht. Der Graph sieht mehrere Send Commands und führt automatisch all diese Target Nodes parallel aus. Das nennt man Fanning Out. Beim Fanning Out trifft der Workflow auf deine Agent Nodes. In einem Custom Workflow ist das Invoken eines Agents ziemlich simpel. Ein Agent ist einfach ein Runnable Process, der innerhalb einer Standard Node Function ausgeführt wird. Die Slack Node empfängt die Query, führt einen dedizierten Slack Agent aus, um Channels zu durchsuchen, extrahiert den Context und gibt ihn an den gesamten Graph State zurück. Die GitHub Node macht gleichzeitig dasselbe für Code Repositories. Diese Agents in spezifischen Nodes zu isolieren, stellt sicher, dass sie nur den Job machen, für den sie gebaut wurden. Schließlich müssen all diese parallelen Branches zusammenlaufen. Du machst ein Fan In. Du erstellst eine Synthesizer Node, die darauf wartet, dass die parallelen Agents fertig werden. Sie liest den gesamten Graph State, nimmt den aus Slack gesammelten Context und den aus GitHub gesammelten Context, übergibt beide an ein finales Language Model und generiert eine einzige, saubere Antwort für den User. Die wahre Power von Custom Workflows ist es, die unvorhersehbare Natur von Large Language Models in die vorhersehbare Zuverlässigkeit von Standard Software Routing zu verpacken. Das war's für diese Folge. Bis zum nächsten Mal!
19

Agent-zu-Agent-Kommunikation

4m 38s

Wir erkunden den LangSmith A2A-Endpunkt. Du lernst, wie verteilte Agenten, die auf völlig unterschiedlichen Servern bereitgestellt sind, nativ über das A2A RPC-Protokoll von Google kommunizieren können.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 19 von 20. Was passiert, wenn ein in Python entwickelter Agent nativ mit einem Agenten kommunizieren muss, der von einem völlig anderen Team gebaut wurde und auf einem komplett anderen Server läuft? Wenn du dich auf hardcodierte interne Function Calls verlässt, bricht dein System in dem Moment zusammen, in dem es eine Netzwerkgrenze überschreitet. Die Lösung ist Agent-to-Agent Communication. Agent-to-Agent, oder A2A, ist ein Kommunikationsprotokoll, das wirklich verteilte Multi-Agent-Systeme ermöglicht. Es erlaubt Agenten, die auf völlig unterschiedlichen Servern gehostet werden, eine kontinuierliche Konversation aufrechtzuerhalten, ohne dieselbe zugrunde liegende Codebase oder denselben lokalen Memory Space teilen zu müssen. Anstatt alles in einer einzigen riesigen Application zu wrappen, routest du Requests über das Netzwerk. Die Kommunikation verlässt sich strikt auf ein definiertes Endpoint-Format: Slash a2a Slash, gefolgt von der Assistant ID. Jeder Agent, der an diesem verteilten Netzwerk teilnimmt, exposed genau diesen Endpoint-Pfad. Wenn ein Agent Hilfe von einem anderen braucht, sendet er einen HTTP POST Request dorthin. Der Payload, der an diesen Endpoint gesendet wird, ist als standardmäßige JSON-RPC Message strukturiert. Um die Konversation über mehrere Network Hops und verschiedene Server hinweg kohärent zu halten, verwendet das Protokoll zwei unterschiedliche Identifier in seinem Payload. Entwickler verwechseln diese beiden manchmal, also werden wir ihre Grenzen definieren. Die erste ist die Context ID. Die Context ID ist für die Kontinuität des gesamten Threads verantwortlich. Sie repräsentiert die gesamte übergreifende Conversation History vom ersten Prompt bis zum finalen Output. Die zweite ist die Task ID. Die Task ID identifiziert den spezifischen Request oder Schritt innerhalb dieses einzelnen Turns. Die Context ID umspannt die gesamte Session. Die Task ID ändert sich jedes Mal, wenn ein Agent den anderen bittet, eine neue Action auszuführen. Stell dir ein praktisches Szenario vor, in dem Agent A auf einem Server läuft, der auf Port 2024 lauscht, und Agent B auf einem anderen Server auf Port 2025 läuft. Agent A merkt, dass er Agent B braucht, um einen bestimmten Subtask zu bearbeiten, vielleicht das Überprüfen von externem Inventar. Agent A bereitet eine JSON-RPC Message vor. In dieser Message fügt er die existierende Context ID ein, damit Agent B weiß, zu welcher laufenden Konversation das gehört. Agent A generiert außerdem eine brandneue Task ID für diesen spezifischen Inventory Request. Agent A sendet diesen Payload an den A2A Endpoint auf Port 2025 und fügt die spezifische Assistant ID von Agent B direkt in den URL-Pfad ein. Agent B empfängt den Request. Er liest die Context ID, um jeden nötigen Background State abzurufen, verarbeitet den in den JSON-RPC Parametern angeforderten Task und berechnet das Ergebnis. Agent B baut dann eine JSON-RPC Response zusammen. Diese Response enthält explizit die exakte Task ID, die Agent A ursprünglich mitgegeben hat. Agent B sendet diese Response zurück an Agent A auf Port 2024. Agent A empfängt das Ergebnis, matcht die Task ID mit seinem ausstehenden Request und setzt seine eigene interne Execution fort. Hier ist der entscheidende Punkt. Weil das Protokoll Standard-JSON-RPC erzwingt und das State Tracking in spezifische Context und Task Identifier isoliert, muss keiner der Agenten wissen, wie der andere intern funktioniert. Sie halten keine konstante, offene Socket Connection aufrecht. Sie reichen einfach abwechselnd strukturierte Messages über Standard-HTTP-Grenzen hin und her. Ein Server stellt eine Frage, der andere antwortet, und der übergeordnete Task schreitet voran. Wenn du den langfristigen Conversation Thread von der individuellen kurzfristigen Task Execution trennst, kannst du Multi-Agent-Netzwerke über verschiedene Server und Frameworks hinweg unbegrenzt skalieren. Wenn du diese Episoden hilfreich findest und die Show unterstützen möchtest, kannst du auf Patreon nach DevStoriesEU suchen. Das war's für diese Folge. Danke fürs Zuhören und keep building!
20

Die Zukunft ist MCP

5m 03s

Wir blicken mit dem Model Context Protocol in die Zukunft, das den Zugriff von Agenten auf externe Tools standardisiert. Du lernst, wie du Remote-MCP-Server über Standard-Transports mit deinem Agenten verbindest.

Herunterladen
Hallo, hier ist Alex von DEV STORIES DOT EU. LangChain v1.0 Orchestration Framework, Folge 20 von 20. Jedes Mal, wenn dein Agent mit einer neuen Datenbank oder API kommunizieren soll, schreibst du am Ende einen custom Wrapper. Deine Codebase füllt sich mit fehleranfälligen Integrationen, die bei jeder Änderung einer externen API kaputtgehen. Das schränkt ein, wie schnell du deine Anwendungen skalieren kannst. Die Lösung für diesen Integrations-Engpass ist das Model Context Protocol, kurz MCP. Stell dir MCP wie USB-C für AI Agents vor. Es standardisiert, wie Tools und Context für Large Language Models bereitgestellt werden. Vor diesem Protokoll musstest du – wenn dein Agent eine Datenbank abfragen und einen Wetterdienst checken sollte – spezifische Python-Funktionen für beides schreiben, ihre Input Schemas manuell definieren und sie an dein Model binden. Mit MCP stellt der externe Service selbst ein standardisiertes Interface bereit. Dein Agent klinkt sich einfach dort ein und versteht sofort, welche Tools verfügbar sind, welche Arguments sie benötigen und wie sie ausgeführt werden. Ein häufiges Missverständnis ist, dass die Nutzung eines Remote-MCP-Servers bedeutet, dass deine Agent-Logik über das Netzwerk wandert. Hier ist die wichtigste Erkenntnis: Dein Agent bleibt komplett lokal. Der Remote-Server führt deinen Agent nicht aus und steuert auch nicht sein Reasoning. Er stellt lediglich eine Liste standardisierter JSON Schemas bereit, die die unterstützten Tools repräsentieren. Dein lokaler Agent liest diese Schemas, entscheidet basierend auf dem User Prompt, welches Tool er nutzt, und sendet einen Execution Request zurück an den Server. Die Ausführung passiert dort, und das Raw Result wird an deinen lokalen Agent zurückgegeben. In LangChain verwaltest du diese Verbindungen mit dem MultiServerMCPClient. Diese Component fungiert als zentraler Hub. Sie ermöglicht es einem einzelnen Agent, sich gleichzeitig mit mehreren verschiedenen MCP-Servern zu verbinden und Tools von allen zu sammeln. Der Client übernimmt die zugrundeliegende Kommunikation über verschiedene Transport Layers. Die beiden wichtigsten Transports, die du konfigurieren wirst, sind Standard Input und Output, auch stdio genannt, und HTTP. Gehen wir mal ein konkretes Szenario durch. Du baust einen Agent, der komplexe Berechnungen mit einem lokalen Python-Script durchführen und gleichzeitig Live-Wetterdaten von einem Remote-Service abrufen soll. Anstatt für diese Tasks eigene custom Tool-Wrapper zu schreiben, konfigurierst du den MultiServerMCPClient so, dass er beides übernimmt. Zuerst definierst du deinen lokalen Math-Server über den stdio-Transport. Du konfigurierst den Client mit dem auszuführenden Command, wie zum Beispiel deiner System-Python-Executable, und dem Pfad zu deinem Math-Script. Wenn der Client initialisiert wird, startet er dieses Script als lokalen Background-Prozess. Der LangChain-Client und das Script tauschen Messages direkt über Standard Input und Standard Output Streams aus. Als Nächstes definierst du den Weather-Server über den HTTP-Transport. Dafür gibst du einfach die Endpoint-URL des Remote-Wetterdienstes an. Dieses Setup nutzt typischerweise Server-Sent Events, um eine persistente Verbindung aufrechtzuerhalten. Dadurch kann der Agent Actions anfordern und Responses über das Web streamen. Sobald beide Transports definiert sind, initialisierst du den MultiServerMCPClient. Der Client kontaktiert sofort den lokalen Math-Prozess über stdio und die Remote-Weather-URL über HTTP. Er fordert beide Server auf, ihre Tool-Definitions zu übergeben. Er sammelt die Schemas, mergt sie zu einer durchgehenden Liste zusammen und stellt sie deinem LangChain-Agent zur Verfügung. Für den Agenten sieht das einfach wie eine einheitliche Liste verfügbarer Tools aus. Er bekommt überhaupt nicht mit, dass ein Tool in einem lokalen Binary-Prozess ausgeführt wird und das andere einen HTTP Request an einen Server am anderen Ende der Welt triggert. Der Wechsel zu standardisierten Protokollen bedeutet, dass du deine Zeit in den Bau besserer Agent-Logik investieren kannst, anstatt endlose API-Wrapper zu pflegen. Da dies die letzte Folge der Serie ist, empfehle ich dir wärmstens, die offizielle LangChain-Dokumentation zu lesen und einfach mal hands-on einen lokalen MCP-Server einzurichten. Wenn du Vorschläge für Themen hast, die du in unserer nächsten Serie sehen möchtest, besuche devstories dot eu und schreib uns eine Nachricht. Die wahre Power eines Agenten liegt nicht darin, was er weiß, sondern womit er sich nahtlos verbinden kann. Das war’s für diese Folge. Danke fürs Zuhören und keep building!