LangChain Best Practices

Vertiefung für Teilnehmende, die nach dem Einsteiger-Guide belastbare LangChain-Muster nachschlagen möchten.

Diese Seite ist keine erste Einführung in LangChain. Sie dient als Referenz für saubere, moderne Patterns, wenn die Grundlagen bereits klar sind. Für den ersten Zugang empfiehlt sich zuerst LangChain Einsteiger.

Im Projektkontext werden einige dieser Patterns als Standard behandelt. Für Teilnehmende im Kurs ist wichtiger, die Unterschiede zwischen älteren und robusteren Mustern zu verstehen, nicht alle Punkte sofort auswendig zu beherrschen.

Typischer Fehler: Diese Seite wie eine lineare Einführung zu lesen. Als Lernpfad ist sie zu dicht. Als Nachschlagewerk bei konkreten Umsetzungsfragen ist sie deutlich nützlicher.


Inhaltsverzeichnis

  1. Überblick der wichtigsten LangChain-Standards
  2. 🆕 What’s New in LangChain v1.2.0 (December 15, 2025)
  3. 1️⃣ init_chat_model() - Unified Model Initialization
    1. ❌ ALT (nicht mehr verwenden)
    2. ✅ NEU (PFLICHT) - Kurznotation “provider:model”
    3. 🎯 Vorteile
    4. 🆕 NEU in v1.1.0: Model Profile System
  4. 2️⃣ with_structured_output() - Native Structured Outputs
    1. ❌ ALT (nicht mehr verwenden)
    2. ✅ NEU (PFLICHT)
    3. 🎯 Vorteile
    4. 🆕 NEU in v1.1.0: Auto-Inference von ProviderStrategy
  5. 3️⃣ @tool Decorator - Tool Definitions
    1. ❌ ALT (nicht mehr verwenden)
    2. ✅ NEU (PFLICHT)
    3. 🎯 Vorteile
    4. 🆕 NEU in v1.2.0: Tool Extras für Provider-spezifische Features
  6. 4️⃣ create_agent() - Modern Agent API
    1. ❌ ALT (nicht mehr verwenden)
    2. ✅ NEU (PFLICHT)
    3. 🎯 Vorteile
    4. 🆕 NEU in v1.1.0: SystemMessage Support
    5. 🆕 NEU in v1.2.0: Strict Schema für Agent-Responses
  7. 5️⃣ LCEL | Chains - Expression Language
    1. ❌ ALT (vermeiden)
    2. ✅ NEU (PFLICHT)
    3. 🎯 Vorteile
  8. 6️⃣ Middleware für Agents - Production-Ready Features
    1. ❌ ALT (deprecated)
    2. ✅ NEU (PFLICHT)
    3. 🎯 Vorteile
    4. 📦 Built-in Middleware
    5. 🆕 NEU in v1.1.0: Erweiterte Middleware
      1. ModelRetryMiddleware (NEU!)
      2. HumanInTheLoopMiddleware respond()-Decision (NEU in v1.2.17)
      3. ContentModerationMiddleware (NEU!)
      4. Verbesserter SummarizationMiddleware
      5. 🆕 ContextOverflowError (v1.2.1+, Januar 2026)
      6. 🆕 Automatic Server-Side Compaction (langchain-openai 1.1.10, Feb 2026)
  9. 7️⃣ Standard Message Content Blocks - Multimodal Support
    1. ❌ ALT (provider-spezifisch)
    2. ✅ NEU (PFLICHT)
    3. 🎯 Vorteile
    4. 📦 Unterstützte Content-Typen
    5. 🎨 Anwendungsfälle
    6. 🧠 Thinking-Formate parsen mit extract_thinking()
  10. 8️⃣ .with_retry() und .with_fallbacks() - Robuste Chains
    1. .with_retry() – Fehlertolerante Ausführung
      1. ❌ ALT (manuell)
      2. ✅ NEU (EMPFOHLEN)
      3. Auf LCEL-Chains anwenden
      4. 🎯 Vorteile
      5. Wann verwenden?
    2. .with_fallbacks() – Ausfallsichere Chains
      1. ✅ Verwendung
      2. Mehrere Fallbacks (Kaskade)
      3. Kombination mit .with_retry()
      4. Auf structured output anwenden
      5. 🎯 Vorteile
      6. Wann verwenden?
  11. 🚀 Quick Start: Komplettes Beispiel
  12. 📚 Import-Cheatsheet
  13. ⚠️ Breaking Changes von 0.x zu 1.0+
  14. 🎯 Migration-Checkliste
  15. 📖 Weitere Ressourcen
  16. Abgrenzung zu verwandten Dokumenten
  17. 📝 Changelog
    1. Version 1.7 (Mai 2026)

Überblick der wichtigsten LangChain-Standards

# Feature Priorität Ersetzt Hauptvorteil
1 init_chat_model() Kernstandard ChatOpenAI() direkt Provider-Unabhängigkeit
2 with_structured_output() Kernstandard PydanticOutputParser Garantierte Schema-Konformität
3 @tool Decorator Kernstandard Tool() wrapper Automatische Schema-Generierung
4 create_agent() Kernstandard initialize_agent() + AgentExecutor Moderne Agenten-Erstellung
5 LCEL \| Chains Kernstandard Legacy Chain-Syntax Moderne Pipe-Operator-Syntax
6 Middleware für Agents Vertiefung Hook-Pattern Robusteres Laufzeitverhalten
7 Standard Content Blocks Vertiefung Provider-spezifische Formate Multimodal-Support
8 .with_retry() / .with_fallbacks() Empfehlung Manuelle try/except-Blöcke Robustere Chains

🆕 What’s New in LangChain v1.2.0 (December 15, 2025)

Hinweis für Einsteiger: Diese Versionssektion ist nur dann wichtig, wenn bestehender Code modernisiert oder Unterschiede zwischen älteren und neueren Beispielen verstanden werden sollen. Für die ersten Kursmodule kann sie zunächst übersprungen werden.

LangChain v1.2.0 erweitert 3 von 7 Must-Haves mit production-ready Features:

Feature Update Impact
#2 with_structured_output() 🆕 Strict Schema für Agents response_format in create_agent
#3 @tool Decorator 🆕 Tool Extras Provider-spezifische Tool-Parameter
#4 create_agent() 🆕 response_format Strikte Agent-Response-Validierung

Wichtigste Neuerungen v1.2.0:

  • Tool Extras: Provider-native Features (Anthropic programmatic tool calling, OpenAI strict mode)
  • Strict Schema Adherence: response_format für garantierte Agent-Output-Konformität
  • Built-in Client-Side Tools: Anthropic, OpenAI, und weitere Provider

Wichtigste Neuerungen v1.1.0 (bereits integriert):

  • Model Profiles (.profile Attribut): Chat-Modelle exposieren ihre Capabilities
  • Smart Structured Output: ProviderStrategy wird automatisch aus Profiles abgeleitet
  • SystemMessage in create_agent: Cache-Control für Anthropic Claude
  • ModelRetryMiddleware: Automatische Retries mit exponential backoff
  • ContentModerationMiddleware: OpenAI Moderation für User/Model/Tool-Outputs
  • Verbesserter SummarizationMiddleware: Nutzt Model Profiles für intelligente Zusammenfassungen

Wichtigste Neuerungen v1.2.1-v1.2.10 (Januar/Februar 2026):

  • ContextOverflowError: Neuer Fehlertyp in langchain-core - wird von langchain-openai und langchain-anthropic ausgelöst, wenn das Context-Window überschritten wird. SummarizationMiddleware triggert automatisch bei diesem Fehler.
  • Token-Zählung für Tool-Schemas: count_tokens_approximately() zählt jetzt auch Tokens aus Tool-Schemas für genauere Budgetierung.

Wichtigste Neuerungen v1.1.10 (langchain-openai) (Februar 2026):

  • Automatic Server-Side Compaction: context_management=[{"type": "compaction", "compact_threshold": N}] — OpenAI komprimiert Konversationshistorie serverseitig, keine SummarizationMiddleware nötig.

Wichtigste Neuerungen v1.2.17 (Mai 2026):

  • **: Middleware kann jetzt direkt antworten und den Agent-Loop beenden.
  • Content-Block-Centric Streaming v2 ( 1.3.2): Streaming liefert strukturierte Content-Block-Events. enthält Block-Dicts mit , und .

Breaking Changes: Keine! v1.2.x ist vollständig rückwärtskompatibel mit v1.0+


1️⃣ init_chat_model() - Unified Model Initialization

❌ ALT (nicht mehr verwenden)

from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

# Auch veraltet: Langnotation mit separaten Variablen
model_provider = "openai"
model_name = "gpt-4o-mini"
llm = init_chat_model(model_name, model_provider=model_provider, temperature=0)

✅ NEU (PFLICHT) - Kurznotation “provider:model”

from langchain.chat_models import init_chat_model

# ✨ Kurznotation: "provider:model" (STANDARD seit Dezember 2025)
llm = init_chat_model("openai:gpt-4o-mini", temperature=0.0)

# Weitere Beispiele:
llm = init_chat_model("anthropic:claude-3-sonnet", temperature=0.3)
llm = init_chat_model("groq:llama-3.1-70b", temperature=0.7)
llm = init_chat_model("google:gemini-pro", temperature=0.5)

# Mit zusätzlichen Parametern:
llm = init_chat_model("openai:gpt-4o-mini", temperature=0.0, max_tokens=1000)

🎯 Vorteile

  • ✅ Kompakte, lesbare Syntax
  • ✅ Provider-übergreifende Kompatibilität
  • ✅ Einfacher Modell-Wechsel
  • ✅ Zukunftssichere API

🆕 NEU in v1.1.0: Model Profile System

Chat-Modelle exposieren jetzt ihre Capabilities über das .profile Attribut:

from langchain.chat_models import init_chat_model

# Kurznotation verwenden
llm = init_chat_model("openai:gpt-4o-mini", temperature=0.0)

# ✨ NEU: Model Profiles (sourced from models.dev)
print(llm.profile.supports_structured_output)  # True (deprecated: use 'structured_output')
print(llm.profile.supports_function_calling)   # True (deprecated: use 'tool_calling')
print(llm.profile.supports_vision)             # True (deprecated: use 'image_inputs')
print(llm.profile.supports_json_mode)          # True (deprecated: use JSON Mode check)

# ✨ Moderne Attribute (v1.1.0+)
print(llm.profile['structured_output'])  # True
print(llm.profile['tool_calling'])       # True
print(llm.profile['image_inputs'])       # True
print(llm.profile['max_input_tokens'])   # 128000

# Dynamische Feature-Detection statt hartcodierter Provider-Logik!
if llm.profile['image_inputs']:
    # Bild-Verarbeitung möglich
    response = llm.invoke([HumanMessage(content=[
        {"type": "text", "text": "Was siehst du?"},
        {"type": "image", "url": "..."}
    ])])

🆕 Utility-Funktion: get_model_profile()

Für einfachere Nutzung gibt es in genai_lib.utilities eine Hilfsfunktion:

from genai_lib.utilities import get_model_profile

# Formatierte Ausgabe aller wichtigen Capabilities
profile = get_model_profile("openai:gpt-4o-mini")

# Output:
# 🔍 Model Profile: openai:gpt-4o-mini
# ============================================================
#
# 📋 Core Capabilities:
#   ✓ Structured Output:  True
#   ✓ Function Calling:   True
#   ✓ JSON Mode:          True
#   ✓ Reasoning:          False
#
# 🎨 Multimodal Capabilities:
#   ✓ Input:  📝 Text, 🖼️ Image
#   ✓ Output: 📝 Text
#
# 📊 Token Limits:
#   ✓ Max Input Tokens:   128000
#   ✓ Max Output Tokens:  16384
#
# ⚙️ Model Configuration:
#   ✓ Temperature:        Yes
#   ✓ Knowledge Cutoff:   2023-10
#
# 🔧 Additional Features:
#   ✓ Streaming:          True
#   ✓ Async:              True
# ============================================================

# Ohne Ausgabe (nur Profile-Dict zurückgeben)
profile = get_model_profile("anthropic:claude-3-sonnet", print_profile=False)

# Verschiedene Models vergleichen (mit Fehlerbehandlung)
for model in ["openai:gpt-4o-mini", "anthropic:claude-3-sonnet", "google:gemini-pro"]:
    print(f"\n{model}:")
    profile = get_model_profile(model, print_profile=False)

    if profile:  # Nur verarbeiten, wenn Model erfolgreich initialisiert
        print(f"  Context: {profile['max_input_tokens']} tokens")
        print(f"  Vision: {profile['image_inputs']}")
        print(f"  Reasoning: {profile.get('reasoning', False)}")
        print(f"  Knowledge: {profile.get('knowledge_cutoff', 'N/A')}")
    else:
        print(f"  ⚠️  Model konnte nicht initialisiert werden (Provider-Bibliothek fehlt?)")

Vorteile:

  • ✅ Automatische Capability-Detection
  • ✅ Keine hardcoded Provider-Checks mehr
  • ✅ Quelle: models.dev (Open-Source Model-Index)
  • ✅ Basis für intelligente Middleware (z.B. SummarizationMiddleware)
  • get_model_profile() für formatierte Ausgabe und Modellvergleiche

2️⃣ with_structured_output() - Native Structured Outputs

❌ ALT (nicht mehr verwenden)

from langchain.output_parsers import PydanticOutputParser

parser = PydanticOutputParser(pydantic_object=Person)
prompt = PromptTemplate(
    template="...\n{format_instructions}",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)

✅ NEU (PFLICHT)

from pydantic import BaseModel, Field

class Person(BaseModel):
    name: str = Field(description="Name der Person")
    age: int = Field(description="Alter in Jahren")

# Direkt strukturierte Ausgabe
structured_llm = llm.with_structured_output(Person)
result = structured_llm.invoke("Max ist 25 Jahre alt")
# result ist direkt ein Person-Objekt!

🎯 Vorteile

  • ✅ Garantierte Schema-Konformität (nutzt OpenAI’s Native API)
  • ✅ Keine manuelle format_instructions mehr
  • ✅ Robuster und weniger fehleranfällig
  • ✅ Kein JSON-Parsing mehr nötig

🆕 NEU in v1.1.0: Auto-Inference von ProviderStrategy

ProviderStrategy wird jetzt automatisch aus Model Profiles abgeleitet:

from pydantic import BaseModel, Field

class MovieRecommendation(BaseModel):
    title: str = Field(description="Filmtitel")
    genre: str = Field(description="Genre")
    rating: float = Field(description="Bewertung 1-10")

# ✨ NEU in v1.1.0: Automatische Provider-Detection
structured_llm = llm.with_structured_output(MovieRecommendation)
# Nutzt automatisch native API wenn verfügbar (z.B. OpenAI's Structured Output)
# Basiert auf llm.profile.supports_structured_output

# Optional: Explizite Strategie (wie vorher)
structured_llm = llm.with_structured_output(
    MovieRecommendation,
    provider_strategy="native"  # Wird automatisch aus Profile erkannt!
)

Vorteile:

  • ✅ Intelligente Defaults basierend auf Model Capabilities
  • ✅ Weniger manuelle Konfiguration
  • ✅ Optimale Strategie pro Provider (OpenAI native vs. fallback)

3️⃣ @tool Decorator - Tool Definitions

❌ ALT (nicht mehr verwenden)

from langchain.agents import Tool

multiply_tool = Tool(
    name="multiply",
    func=lambda a, b: a * b,
    description="Multipliziert zwei Zahlen"
)

✅ NEU (PFLICHT)

from langchain_core.tools import tool

@tool
def multiply(a: int, b: int) -> int:
    """Multipliziert zwei Zahlen."""
    return a * b

🎯 Vorteile

  • ✅ Automatische Schema-Generierung aus Docstring
  • ✅ Type-Safety durch Python Type Hints
  • ✅ Weniger Boilerplate-Code
  • ✅ Bessere IDE-Unterstützung

🆕 NEU in v1.2.0: Tool Extras für Provider-spezifische Features

Tools unterstützen jetzt extras für provider-native Konfigurationen:

from langchain_core.tools import tool

# ✨ NEU: Provider-spezifische Tool-Parameter
@tool(extras={
    "anthropic": {
        "cache_control": {"type": "ephemeral"},  # Anthropic Prompt Caching
        "disable_parallel_tool_use": False
    },
    "openai": {
        "strict": True  # OpenAI Strict Mode (garantierte Schema-Konformität)
    }
})
def search_database(query: str, limit: int = 10) -> str:
    """Durchsucht die Datenbank nach relevanten Informationen.

    Args:
        query: Suchanfrage
        limit: Maximale Anzahl Ergebnisse
    """
    return f"Gefunden: {limit} Ergebnisse für '{query}'"

# Tool mit Anthropic programmatic tool calling
@tool(extras={
    "anthropic": {
        "type": "computer_20241022",  # Anthropic Computer Use
        "display_width_px": 1024,
        "display_height_px": 768
    }
})
def take_screenshot() -> str:
    """Erstellt einen Screenshot des Bildschirms."""
    return "screenshot.png"

Vorteile:

  • Provider-native Features nutzen (Caching, Strict Mode, Computer Use)
  • Built-in Client-Side Tools für Anthropic, OpenAI
  • Optimierte Performance durch provider-spezifische Optimierungen
  • Backwards-compatible: Tools ohne extras funktionieren weiterhin

Use Cases:

  • Anthropic Prompt Caching für häufig verwendete Tools
  • OpenAI Strict Mode für garantierte Schema-Konformität
  • Anthropic Computer Use für Browser-Automation
  • Provider-spezifische Tool-Konfigurationen

4️⃣ create_agent() - Modern Agent API

❌ ALT (nicht mehr verwenden)

from langchain.agents import initialize_agent, AgentType

agent = initialize_agent(
    tools,
    llm,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)

✅ NEU (PFLICHT)

from langchain.agents import create_agent

agent = create_agent(
    model=llm,  # oder "openai:gpt-4"
    tools=[tool1, tool2],
    system_prompt="You are a helpful assistant",
    debug=True  # Zeigt Denkprozess (= verbose=True)
)

# Agent aufrufen (gibt CompiledStateGraph zurück)
response = agent.invoke({
    "messages": [{"role": "user", "content": "your question"}]
})

🎯 Vorteile

  • ✅ Basiert auf LangGraph (State Machine)
  • ✅ Kein AgentExecutor mehr nötig
  • ✅ Besseres Debugging mit debug=True
  • ✅ Middleware-Support (siehe Feature #6)

🆕 NEU in v1.1.0: SystemMessage Support

system_prompt akzeptiert jetzt SystemMessage mit erweiterten Features:

from langchain.agents import create_agent
from langchain_core.messages import SystemMessage

# ❌ ALT: Nur String
agent = create_agent(
    model=llm,
    tools=tools,
    system_prompt="You are a helpful assistant"
)

# ✅ NEU in v1.1.0: SystemMessage mit Cache-Control
agent = create_agent(
    model=llm,
    tools=tools,
    system_prompt=SystemMessage(
        content="You are a helpful research assistant with access to web search and databases.",
        cache_control={"type": "ephemeral"}  # Anthropic Cache-Control
    )
)

# ✅ NEU: SystemMessage mit strukturierten Content Blocks
agent = create_agent(
    model=llm,
    tools=tools,
    system_prompt=SystemMessage(
        content=[
            {"type": "text", "text": "You are a helpful assistant."},
            {"type": "text", "text": "Important guidelines:", "cache_control": {"type": "ephemeral"}}
        ]
    )
)

Vorteile:

  • Cache-Control für Anthropic Claude (schneller + günstiger)
  • Strukturierte Content Blocks im System-Prompt
  • Richer System-Level Instructions mit Metadata
  • Backwards-compatible: String-Prompts funktionieren weiterhin

🆕 NEU in v1.2.0: Strict Schema für Agent-Responses

Agents unterstützen jetzt response_format für strikte Validierung von Agent-Outputs:

from langchain.agents import create_agent
from pydantic import BaseModel, Field

# Definiere strukturiertes Response-Schema
class AgentResponse(BaseModel):
    """Strukturierte Agent-Antwort mit Reasoning."""
    reasoning: str = Field(description="Denkprozess des Agents")
    action: str = Field(description="Geplante Aktion")
    tool_to_use: str | None = Field(description="Zu verwendendes Tool (optional)")
    confidence: float = Field(description="Konfidenz 0-1", ge=0, le=1)

# ✨ NEU in v1.2.0: response_format für garantierte Schema-Konformität
agent = create_agent(
    model=llm,
    tools=[search_tool, calculator_tool],
    system_prompt="You are a helpful research assistant",
    response_format=AgentResponse,  # Strikte Validierung!
    provider_strategy="strict"  # Nutzt OpenAI Structured Output (wenn verfügbar)
)

# Agent-Response ist garantiert schema-konform
response = agent.invoke({
    "messages": [{"role": "user", "content": "Recherchiere die Bevölkerung von Berlin"}]
})

# Typsicherer Zugriff auf strukturierte Felder
print(response.reasoning)  # str
print(response.confidence)  # float (0-1)

Vorteile:

  • Garantierte Schema-Konformität für Agent-Outputs (keine JSON-Parsing-Fehler)
  • Type-Safety mit Pydantic-Validierung
  • Bessere Fehlerbehandlung durch strukturierte Responses
  • Strikte Provider-Integration (OpenAI Structured Output, Anthropic Tool Use)
  • Predictable Agent-Behavior für Production-Systeme

Use Cases:

  • Production-Agents mit garantierten Output-Formaten
  • Multi-Step-Reasoning mit strukturierten Zwischenschritten
  • Agent-Monitoring mit standardisierten Response-Metriken
  • Integration in typsichere Workflows

Kombination mit Structured Output:

# response_format arbeitet nahtlos mit with_structured_output()
structured_llm = llm.with_structured_output(AgentResponse)

agent = create_agent(
    model=structured_llm,
    tools=tools,
    response_format=AgentResponse,  # Doppelte Validierung (LLM + Agent-Level)
    provider_strategy="strict"
)

5️⃣ LCEL | Chains - Expression Language

❌ ALT (vermeiden)

from langchain.chains import LLMChain

chain = LLMChain(llm=llm, prompt=prompt)
result = chain.run(input="text")

✅ NEU (PFLICHT)

from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# Pipe-Operator für Chain-Komposition
chain = prompt | llm | StrOutputParser()

# Aufruf
result = chain.invoke({"input": "text"})

# Asynchrone Unterstützung
result = await chain.ainvoke({"input": "text"})

🎯 Vorteile

  • ✅ Moderne, lesbare Syntax
  • ✅ Automatisches Streaming-Support
  • ✅ Parallele Ausführung wo möglich
  • ✅ Native async/await-Unterstützung

6️⃣ Middleware für Agents - Production-Ready Features

❌ ALT (deprecated)

# Hooks sind in 1.0+ deprecated
agent_executor.register_hook("before_agent", my_hook)

✅ NEU (PFLICHT)

from langchain.agents import create_agent
from langchain.agents.middleware import (
    HumanInTheLoopMiddleware,
    SummarizationMiddleware,
    PIIMiddleware
)

middleware = [
    HumanInTheLoopMiddleware(
        tool_names=["delete_file", "execute_command"]  # Genehmigung erforderlich
    ),
    SummarizationMiddleware(
        max_tokens=1000  # Automatische Kontext-Zusammenfassung
    ),
    PIIMiddleware(
        patterns=["email", "phone"]  # PII-Redaktion
    )
]

agent = create_agent(
    model=llm,
    tools=tools,
    system_prompt="You are a helpful assistant",
    middleware=middleware  # Middleware hinzufügen
)

🎯 Vorteile

  • Human-in-the-Loop für sensible Operationen (Essential für Production!)
  • Automatische Kontextverwaltung bei langen Sessions (verhindert Token-Overflow)
  • PII-Redaktion für Datenschutz (DSGVO-konform)
  • Custom Middleware für spezifische Anforderungen

📦 Built-in Middleware

Middleware Zweck Wann verwenden?
HumanInTheLoopMiddleware Manuelle Genehmigung vor Tool-Ausführung Dateioperationen, API-Calls, kritische Aktionen
SummarizationMiddleware Automatische Zusammenfassung langer Konversationen Chat-Apps, lange Sessions
PIIMiddleware Datenschutz durch Mustererkennung DSGVO-Compliance, sensible Daten
ModelRetryMiddleware 🆕 Automatische Retries mit exponential backoff Flaky APIs, Rate Limits
ContentModerationMiddleware 🆕 OpenAI Moderation für User/Model/Tool-Outputs Safety-Layer, Content-Filter

🆕 NEU in v1.1.0: Erweiterte Middleware

ModelRetryMiddleware (NEU!)

Automatische Retries bei API-Fehlern mit konfigurierbarem exponential backoff:

from langchain.agents import create_agent
from langchain.agents.middleware import ModelRetryMiddleware

agent = create_agent(
    model=llm,
    tools=tools,
    middleware=[
        ModelRetryMiddleware(
            max_retries=3,
            backoff_factor=2.0,  # Exponential Backoff (2s, 4s, 8s)
            retry_on=["rate_limit_error", "timeout", "server_error"],
            jitter=True  # Randomized delay
        )
    ]
)

Use Cases:

  • ✅ Rate-Limiting von API-Providern
  • ✅ Transiente Netzwerkfehler
  • ✅ Server-Timeouts
  • ✅ Production-Resilience

HumanInTheLoopMiddleware respond()-Decision (NEU in v1.2.17)

Was neu ist: beendet den Agent-Loop sofort mit einer direkten Antwort.

In der Praxis relevant wenn: Guardrails sollen dem Nutzer eine klare Fehlermeldung liefern, die das LLM nicht nochmals umformulieren muss.


ContentModerationMiddleware (NEU!)

OpenAI Moderation API für konsistente Safety-Layer:

from langchain.agents.middleware import ContentModerationMiddleware

agent = create_agent(
    model=llm,
    tools=tools,
    middleware=[
        ContentModerationMiddleware(
            provider="openai",  # Nutzt OpenAI Moderation API
            check_user_input=True,      # Filter User-Inputs
            check_model_output=True,    # Filter Model-Responses
            check_tool_output=True,     # Filter Tool-Results
            block_on_violation=True,    # Workflow stoppen bei Violation
            categories=["hate", "violence", "sexual"]  # Spezifische Kategorien
        )
    ]
)

Use Cases:

  • ✅ User-Generated Content-Filter
  • ✅ DSGVO-Compliance & Safety
  • ✅ Brand-Safety für Production-Apps
  • ✅ Multi-Layer-Content-Moderation

Verbesserter SummarizationMiddleware

Nutzt jetzt Model Profiles für intelligente Zusammenfassungen:

from langchain.agents.middleware import SummarizationMiddleware

# ✅ v1.1.0: Context-aware Summarization
middleware = SummarizationMiddleware(
    max_tokens=1000,
    # NEU: Automatische Detection von Summarization-Capabilities via llm.profile
    # Provider-spezifische Optimierungen (GPT-4 vs Claude vs Gemini)
    trigger_strategy="flexible"  # Intelligente Trigger-Points basierend auf Model
)

Verbesserungen:

  • ✅ Nutzt llm.profile für optimale Summarization-Strategie
  • ✅ Provider-spezifische Optimierungen
  • ✅ Flexible Trigger-Points (nicht nur hard limit)
  • ✅ Bessere Performance auf langen Sessions

🆕 ContextOverflowError (v1.2.1+, Januar 2026)

Neuer Fehlertyp für automatisches Context-Window-Management:

from langchain_core.exceptions import ContextOverflowError
from langchain.agents.middleware import SummarizationMiddleware

# SummarizationMiddleware fängt ContextOverflowError automatisch ab
# und fasst die bisherige Konversation zusammen, bevor der Aufruf wiederholt wird
middleware = SummarizationMiddleware(
    max_tokens=1000,
    # NEU: Automatischer Trigger bei ContextOverflowError
    # Kein manuelles Token-Zählen mehr nötig!
)

Vorteile:

  • ✅ Wird von langchain-openai und langchain-anthropic nativ ausgelöst
  • SummarizationMiddleware reagiert automatisch darauf
  • ✅ Kein manuelles Context-Window-Management mehr nötig
  • count_tokens_approximately() zählt jetzt auch Tool-Schema-Tokens

🆕 Automatic Server-Side Compaction (langchain-openai 1.1.10, Feb 2026)

Alternative zu SummarizationMiddleware: OpenAI komprimiert die Konversationshistorie serverseitig – kein extra Middleware-Layer nötig.

from langchain.chat_models import init_chat_model

# OpenAI komprimiert automatisch bei langen Konversationen
llm = init_chat_model(
    "openai:gpt-4o",
    context_management=[{"type": "compaction", "compact_threshold": 10_000}]
    # compact_threshold: Token-Schwellenwert, ab dem komprimiert wird
)

Vergleich: Server-Side vs. Client-Side Context-Management:

Ansatz Wie Provider Kosten
SummarizationMiddleware Client: LLM fasst zusammen Alle Zusätzliche LLM-Kosten
context_management (neu) Server: OpenAI komprimiert Nur OpenAI In API-Kosten enthalten

Wann welchen Ansatz wählen:

  • context_management → OpenAI-Apps, einfachste Lösung
  • SummarizationMiddleware → Provider-unabhängig, mehr Kontrolle

7️⃣ Standard Message Content Blocks - Multimodal Support

❌ ALT (provider-spezifisch)

# OpenAI-spezifisch
message.additional_kwargs["image_url"]

# Anthropic-spezifisch
message.additional_kwargs["content"]

✅ NEU (PFLICHT)

from langchain_core.messages import AIMessage, HumanMessage

# Standardisierte content_blocks
message = AIMessage(
    content=[
        {"type": "text", "text": "Here's the image analysis:"},
        {"type": "image", "url": "data:image/png;base64,...", "mime_type": "image/png"}
    ]
)

# Provider-agnostischer Zugriff
for block in message.content_blocks:
    if block["type"] == "text":
        print(block["text"])
    elif block["type"] == "image":
        display_image(block["url"])
    elif block["type"] == "audio":
        play_audio(block["url"])

🎯 Vorteile

  • Einheitliches Interface über alle Provider (OpenAI, Anthropic, Google, Cohere)
  • Multimodal-Support: Text, Bilder, Audio, Video
  • Reasoning Traces & Citations für transparente KI-Entscheidungen
  • Einfacher Provider-Wechsel ohne Code-Änderungen

📦 Unterstützte Content-Typen

# Text
{"type": "text", "text": "..."}

# Bild
{"type": "image", "url": "...", "mime_type": "image/png"}

# Audio
{"type": "audio", "url": "...", "mime_type": "audio/mp3"}

# Video
{"type": "video", "url": "...", "mime_type": "video/mp4"}

# Reasoning Trace (für erklärbare KI)
{"type": "reasoning", "text": "...", "confidence": 0.95}

# Citation (Quellenangaben)
{"type": "citation", "text": "...", "source": "..."}

🎨 Anwendungsfälle

  • ✅ Multimodale RAG-Systeme (perfekt für 04_modul/genai_lib/multimodal_rag.py)
  • ✅ Bild-zu-Text und Text-zu-Bild Pipelines
  • ✅ Audio/Video-Analyse mit LLMs
  • ✅ Provider-unabhängige Chatbots

🧠 Thinking-Formate parsen mit extract_thinking()

Verschiedene LLMs liefern “Thinking” (Denkprozess) in unterschiedlichen Formaten. Die Utility-Funktion extract_thinking() aus genai_lib.utilities bietet einen universellen Parser:

from genai_lib.utilities import extract_thinking

# Response von beliebigem LLM
response = llm.invoke("Erkläre Schritt für Schritt...")

# Universeller Parser für alle Formate
thinking, answer = extract_thinking(response)

print(f"Denkprozess: {thinking[:200]}...")
print(f"Antwort: {answer}")

Unterstützte Formate:

Provider/Modell Format Beispiel
Claude (Extended Thinking) Liste mit {"type": "thinking"} Blöcken content = [{"type": "thinking", "thinking": "..."}]
Gemini Liste mit {"type": "thinking"} Blöcken content = [{"type": "thinking", "thinking": "..."}]
Qwen3, DeepSeek R1 String mit <think> Tags "<think>Denkprozess</think>Antwort"
DeepSeek additional_kwargs["reasoning_content"] Separates Feld im Response

Vorteile:

  • Provider-agnostisch: Ein Parser für alle LLMs
  • Fallback-Logik: Prüft alle bekannten Formate
  • Robust: Gibt leeren Thinking-String zurück, wenn kein Denkprozess vorhanden

8️⃣ .with_retry() und .with_fallbacks() - Robuste Chains

Beide Methoden gehören zum Runnable-Interface (LCEL) und lassen sich auf jede Chain, jedes LLM oder jeden OutputParser anwenden.


.with_retry() – Fehlertolerante Ausführung

Wiederholt einen Runnable automatisch bei definierten Fehlern (z. B. Rate Limits, Timeouts).

❌ ALT (manuell)

import time

for attempt in range(3):
    try:
        result = llm.invoke("...")
        break
    except RateLimitError:
        time.sleep(2 ** attempt)

✅ NEU (EMPFOHLEN)

# Einfachste Form: 3 Versuche bei allen Fehlern
robust_llm = llm.with_retry(stop_after_attempt=3)

# Gezielt: nur bei Rate-Limit- und Timeout-Fehlern
from langchain_openai.exceptions import RateLimitError
import httpx

robust_llm = llm.with_retry(
    retry_if_exception_type=(RateLimitError, httpx.TimeoutException),
    stop_after_attempt=3,
    wait_exponential_jitter=True   # Exponential Backoff + Jitter
)

result = robust_llm.invoke("Wie ist das Wetter?")

Auf LCEL-Chains anwenden

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

chain = (
    ChatPromptTemplate.from_template("Beantworte: {frage}")
    | llm
    | StrOutputParser()
).with_retry(stop_after_attempt=3)

result = chain.invoke({"frage": "Was ist LangChain?"})

🎯 Vorteile

  • ✅ Kein Boilerplate-Code für Retry-Logik
  • ✅ Konfigurierbare Fehlertypen (nur relevante Exceptions)
  • ✅ Exponential Backoff mit Jitter verhindert API-Überlastung
  • ✅ Gilt für LLMs, Chains, Tools – jeden Runnable

Wann verwenden?

  • ✅ Rate-Limit-Fehler (OpenAI, Anthropic)
  • ✅ Transiente Netzwerkfehler / Timeouts
  • ✅ Flaky externe APIs in Tools
  • Nicht bei Validierungs- oder Logikfehlern (die sind nicht transient)

.with_fallbacks() – Ausfallsichere Chains

Schaltet automatisch auf ein Fallback-LLM oder eine alternative Chain um, wenn der primäre Runnable fehlschlägt.

✅ Verwendung

from langchain.chat_models import init_chat_model

primary_llm   = init_chat_model("openai:gpt-4o",      temperature=0.0)
fallback_llm  = init_chat_model("openai:gpt-4o-mini",  temperature=0.0)

# Bei Fehler des primären LLMs → automatisch gpt-4o-mini
safe_llm = primary_llm.with_fallbacks([fallback_llm])

result = safe_llm.invoke("Erkläre Transformer-Modelle.")

Mehrere Fallbacks (Kaskade)

llm_gpt4        = init_chat_model("openai:gpt-4o",       temperature=0.0)
llm_gpt4_mini   = init_chat_model("openai:gpt-4o-mini",  temperature=0.0)
llm_anthropic   = init_chat_model("anthropic:claude-3-haiku", temperature=0.0)

# Kaskade: gpt-4o → gpt-4o-mini → claude-3-haiku
resilient_llm = llm_gpt4.with_fallbacks([llm_gpt4_mini, llm_anthropic])

Kombination mit .with_retry()

# Empfohlenes Pattern für Production:
# 1. Erst 3× Retry auf dem primären LLM
# 2. Dann Fallback auf alternatives Modell
safe_chain = (
    llm_gpt4.with_retry(stop_after_attempt=3)
).with_fallbacks([llm_gpt4_mini])

Auf structured output anwenden

structured_primary  = llm_gpt4.with_structured_output(Person)
structured_fallback = llm_gpt4_mini.with_structured_output(Person)

safe_structured = structured_primary.with_fallbacks([structured_fallback])
result = safe_structured.invoke("Anna Müller ist 32 Jahre alt.")

🎯 Vorteile

  • ✅ Zero-Downtime bei Provider-Ausfällen
  • ✅ Kostenkontrolle (teures Modell → günstiges Fallback)
  • ✅ Provider-Diversität als Resilienz-Strategie
  • ✅ Kombinierbar mit .with_retry() und with_structured_output()

Wann verwenden?

  • ✅ Production-Systeme mit hoher Verfügbarkeitsanforderung
  • ✅ Kostenoptimierung (Primär: leistungsstark, Fallback: günstig)
  • ✅ Multi-Provider-Setups
  • Nicht als Ersatz für Retry (Fallback = anderes Modell, nicht Wiederholung)

🚀 Quick Start: Komplettes Beispiel

# 1. Model Initialization
from langchain.chat_models import init_chat_model

llm = init_chat_model(
    "gpt-4o-mini",
    model_provider="openai",
    temperature=0.0
)

# 2. Structured Output
from pydantic import BaseModel, Field

class MovieRecommendation(BaseModel):
    title: str = Field(description="Filmtitel")
    genre: str = Field(description="Genre")
    rating: float = Field(description="Bewertung 1-10")

structured_llm = llm.with_structured_output(MovieRecommendation)

# 3. Tools mit @tool Decorator
from langchain_core.tools import tool

@tool
def search_movies(query: str) -> str:
    """Sucht nach Filmen in der Datenbank."""
    return f"Ergebnisse für: {query}"

# 4. Agent mit Middleware
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware

agent = create_agent(
    model=llm,
    tools=[search_movies],
    system_prompt="Du bist ein hilfreicher Film-Assistent",
    middleware=[
        HumanInTheLoopMiddleware(tool_names=["search_movies"])
    ],
    debug=True
)

# 5. LCEL Chain
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

prompt = ChatPromptTemplate.from_template("Empfehle einen {genre}-Film")
chain = prompt | llm | StrOutputParser()
result = chain.invoke({"genre": "Sci-Fi"})

# 6. Multimodal Content Blocks
from langchain_core.messages import HumanMessage

message = HumanMessage(
    content=[
        {"type": "text", "text": "Was siehst du auf diesem Bild?"},
        {"type": "image", "url": "data:image/png;base64,...", "mime_type": "image/png"}
    ]
)
response = llm.invoke([message])

📚 Import-Cheatsheet

# Models
from langchain.chat_models import init_chat_model

# Structured Output
from pydantic import BaseModel, Field

# Tools
from langchain_core.tools import tool

# Agents & Middleware
from langchain.agents import create_agent
from langchain.agents.middleware import (
    HumanInTheLoopMiddleware,
    SummarizationMiddleware,
    PIIMiddleware,
    ModelRetryMiddleware,  # 🆕 v1.1.0
    ContentModerationMiddleware  # 🆕 v1.1.0
)

# Chains (LCEL)
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

# Messages & Content Blocks
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage

# Prompts
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate

# Robustheit (with_retry / with_fallbacks sind Methoden auf Runnables,
# kein separater Import nötig – direkt auf llm/chain anwenden)

# Vectorstores & RAG
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter

⚠️ Breaking Changes von 0.x zu 1.0+

Alt (0.x) Neu (1.0+) Status
ChatOpenAI() direkt init_chat_model() ⛔ Deprecated
PydanticOutputParser with_structured_output() ⛔ Deprecated
Tool() wrapper @tool decorator ⛔ Deprecated
initialize_agent() + AgentExecutor create_agent() ⛔ Deprecated
Hook-Pattern Middleware ⛔ Deprecated
Provider-spezifische Content-Formate Standard Content Blocks ⛔ Deprecated

🎯 Migration-Checkliste

Beim Refactoring von altem Code:

  • ChatOpenAI()init_chat_model() ersetzen
  • PydanticOutputParserwith_structured_output() ersetzen
  • Tool() wrapper → @tool decorator ersetzen
  • initialize_agent()create_agent() ersetzen
  • Legacy Chain-Syntax → LCEL | ersetzen
  • Hooks → Middleware ersetzen
  • Provider-spezifische Content → content_blocks ersetzen
  • Python 3.10+ erforderlich (3.9 wird nicht mehr unterstützt)
  • Custom State muss TypedDict verwenden (keine Pydantic Models)

📖 Weitere Ressourcen

  • LangChain Docs: https://python.langchain.com/
  • Migration Guide: https://docs.langchain.com/oss/python/migrate/langchain-v1
  • LangChain Blog: https://blog.langchain.com/langchain-langgraph-1dot0/
  • Projekt CLAUDE.md: Vollständige Projektinstruktionen im Repository

Abgrenzung zu verwandten Dokumenten

Dokument Frage
Erste Agenten Wo starte ich als Einsteiger mit LangChain Best Practices?
Qualität und Sicherheit Welche Produktionsstandards gelten für LangChain Best Practices?

📝 Changelog

Version 1.7 (Mai 2026)

  • 🆕 astream_events() v3 Protokollversion="v3" in LangChain v1.3.0 verfügbar (bisher max. v2)
  • 🆕 langchain-core v1.4.0 — Content-Block-Streaming v2 jetzt stabil (war Beta in 1.3.2)
  • 🆕 HumanInTheLoopMiddleware.respond() — direkte Antwort aus Middleware ohne weiteren LLM-Call (v1.2.17)

Version: 1.7
Stand: Mai 2026
Kurs: KI-Agenten. Verstehen. Anwenden. Gestalten.