🔗 LangChain LCEL
🤖 Agents vs. Chains
🛠 Custom Tools
💾 Memory
🕸 LangGraph
🔭 LangSmith
LangChain ist 2026 das meistgenutzte Python-Framework für produktionsreife KI-Agenten. In Kombination mit Claude Code — Anthropics autonomem Coding-Assistenten — entstehen Systeme, die Recherche, Codegeneration, Datenbankabfragen und externe APIs in einem einzigen kontrollierten Workflow verbinden. Dieser Guide zeigt dir, wie du das gesamte LangChain-Ökosystem produktiv einsetzt.
LangChain Expression Language (LCEL): Chains bauen
LCEL ist die deklarative Kompositions-API von LangChain. Statt imperativem Callback-Spaghetti verbindest du Komponenten mit dem |-Operator — ähnlich wie Unix-Pipes. Jede Komponente ist ein Runnable: gleiche Schnittstelle, beliebig austauschbar.
LCEL Grundprinzip
input | prompt | llm | output_parser — jede Stufe transformiert den Output der vorherigen.
Alle Runnables unterstützen .invoke(), .stream(), .batch() und async-Varianten out of the box.
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
# Modell initialisieren
llm = ChatAnthropic(model="claude-opus-4-5", max_tokens=2048)
# Prompt-Template
prompt = ChatPromptTemplate.from_messages([
("system", "Du bist ein erfahrener Python-Entwickler. Antworte präzise auf Deutsch."),
("human", "{question}")
])
# LCEL Chain zusammenstellen
chain = prompt | llm | StrOutputParser()
# Synchron aufrufen
result = chain.invoke({"question": "Erkläre async/await in Python"})
# Streaming (Token-für-Token)
for chunk in chain.stream({"question": "Erkläre async/await in Python"}):
print(chunk, end="", flush=True)
Parallele Chains mit RunnableParallel
Mit RunnableParallel führst du mehrere Branches gleichzeitig aus — ideal für Analysen, die unabhängige Sub-Tasks kombinieren:
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
summary_chain = prompt_summary | llm | StrOutputParser()
sentiment_chain = prompt_sentiment | llm | StrOutputParser()
parallel = RunnableParallel(
zusammenfassung=summary_chain,
stimmung=sentiment_chain,
original=RunnablePassthrough()
)
output = parallel.invoke({"text": "Langer Kundenbericht..."})
# output = {"zusammenfassung": "...", "stimmung": "positiv", "original": {...}}
Agents vs. Chains: Wann welches Pattern?
Die häufigste Architektur-Frage: Reicht eine Chain, oder brauche ich einen vollwertigen Agent? Die Antwort hängt davon ab, ob der Ablauf zur Laufzeit entschieden werden muss.
| Kriterium |
Chain |
Agent |
| Ablauf | Fest vordefiniert | Dynamisch, LLM entscheidet |
| Tool-Nutzung | Optional, statisch eingebaut | Beliebige Tools, zur Laufzeit gewählt |
| Latenz | Niedrig (1–3 LLM-Calls) | Höher (ReAct-Loop, N Calls) |
| Kosten | Besser kontrollierbar | Variabel, Token-Budget nötig |
| Debugging | Einfach | Komplex (LangSmith empfohlen) |
| Anwendungsfall | RAG, Summarization, ETL | Recherche, Code-Ausführung, Multi-Step |
Faustregel: Beginne immer mit einer Chain. Wenn du merkst, dass das LLM entscheiden muss welche Tools es in welcher Reihenfolge aufruft — wechsle zum Agent-Pattern.
LangChain Tools: Eigene Tools definieren
Tools sind das Herzstück von LangChain-Agenten. Mit dem @tool-Decorator oder der StructuredTool-Klasse bindest du beliebige Python-Funktionen als abrufbare Fähigkeiten ein.
from langchain_core.tools import tool
from pydantic import BaseModel, Field
import httpx
# Einfaches Tool mit @tool Decorator
@tool
def get_current_weather(city: str) -> str:
"""Gibt das aktuelle Wetter für eine Stadt zurück.
Nutze dieses Tool wenn der Nutzer nach dem aktuellen Wetter fragt."""
resp = httpx.get(f"https://api.weather.example.com/?q={city}")
return resp.text
# Tool mit strukturiertem Input-Schema
class SearchInput(BaseModel):
query: str = Field(description="Die Suchanfrage")
max_results: int = Field(default=5, description="Anzahl der Ergebnisse")
@tool(args_schema=SearchInput)
def web_search(query: str, max_results: int = 5) -> str:
"""Durchsucht das Internet nach aktuellen Informationen."""
# Integration mit Tavily, SerpAPI, etc.
return perform_search(query, max_results)
# Agent mit Tools erstellen
from langchain.agents import create_tool_calling_agent, AgentExecutor
tools = [get_current_weather, web_search]
agent = create_tool_calling_agent(llm, tools, agent_prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
Best Practice: Definiere jeden Tool-Docstring mit Beispiel-Triggern. Das LLM wählt das richtige Tool nur dann zuverlässig, wenn es versteht, wann es aufgerufen werden soll — nicht nur was es tut.
Memory: ConversationBufferMemory & VectorStore Memory
Ohne Memory ist jeder LLM-Call zustandslos. LangChain bietet mehrere Memory-Strategien — von einfachem Buffer bis zu semantisch durchsuchbarem Langzeit-Speicher.
Memory-Typen im Überblick
- ConversationBufferMemory — alle Nachrichten im Kontext (einfach, aber teuer)
- ConversationSummaryMemory — fasst alte Turns zusammen, spart Tokens
- ConversationBufferWindowMemory — nur letzte N Nachrichten
- VectorStoreRetrieverMemory — semantische Suche über Langzeit-Konversationen
from langchain.memory import ConversationBufferMemory
from langchain_community.vectorstores import Chroma
from langchain_anthropic import AnthropicEmbeddings
from langchain.memory import VectorStoreRetrieverMemory
# Einfacher Buffer (Short-Term Memory)
buffer_memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True,
output_key="output"
)
# VectorStore Memory (Long-Term Memory)
embeddings = AnthropicEmbeddings()
vectorstore = Chroma(
collection_name="agent_memory",
embedding_function=embeddings,
persist_directory="./chroma_db"
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
vs_memory = VectorStoreRetrieverMemory(retriever=retriever)
# Memory in Chain einbinden
from langchain.chains import ConversationChain
conv_chain = ConversationChain(
llm=llm,
memory=buffer_memory,
verbose=True
)
response1 = conv_chain.predict(input="Mein Name ist Klaus.")
response2 = conv_chain.predict(input="Wie heißt du nochmal mein Name?")
# → "Du hast mir gesagt, dass du Klaus heißt."
Praxis-Tipp: Kombiniere beide Strategien: ConversationBufferWindowMemory (k=10) für den aktiven Kontext + VectorStoreRetrieverMemory für Langzeit-Fakten. So bleiben Tokens kontrollierbar und trotzdem kein Wissen verloren.
LangGraph: State-Machines für komplexe Agent-Flows
LangGraph ist die Antwort auf die Grenzen einfacher ReAct-Agenten. Statt linearer Loops modellierst du Agent-Verhalten als gerichteten azyklischen Graphen (DAG) — mit Zyklen, bedingten Kanten und persistierendem State.
Wann LangGraph statt AgentExecutor?
- Mehrere spezialisierte Sub-Agenten koordinieren
- Bedingte Verzweigungen basierend auf Agent-Output
- Human-in-the-Loop: Pause & Genehmigung einbauen
- Langer, mehrstufiger Workflow mit persistentem Zustand
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List
import operator
# State-Schema definieren
class ResearchState(TypedDict):
question: str
search_results: List[str]
draft: str
final_answer: str
iteration: int
# Knoten-Funktionen (je ein LLM-Call oder Tool-Aufruf)
def search_node(state: ResearchState) -> ResearchState:
results = web_search.invoke(state["question"])
return {"search_results": [results], "iteration": state["iteration"] + 1}
def draft_node(state: ResearchState) -> ResearchState:
context = "\n".join(state["search_results"])
draft = draft_chain.invoke({"context": context, "question": state["question"]})
return {"draft": draft}
def quality_check(state: ResearchState) -> str:
# Bedingte Kante: ausreichend oder nochmal suchen?
if state["iteration"] >= 3 or is_sufficient(state["draft"]):
return "finalize"
return "search"
# Graph zusammenstellen
workflow = StateGraph(ResearchState)
workflow.add_node("search", search_node)
workflow.add_node("draft", draft_node)
workflow.add_node("finalize", finalize_node)
workflow.set_entry_point("search")
workflow.add_edge("search", "draft")
workflow.add_conditional_edges("draft", quality_check, {"search": "search", "finalize": "finalize"})
workflow.add_edge("finalize", END)
app = workflow.compile()
result = app.invoke({"question": "Beste LLM-Frameworks 2026?", "iteration": 0, "search_results": []})
LangGraph Checkpointing — Workflows pausieren
Mit dem integrierten Checkpointer kannst du Workflows unterbrechen, menschliche Genehmigung einholen und dann weitermachen — ohne den gesamten State neu aufzubauen:
from langgraph.checkpoint.sqlite import SqliteSaver
memory = SqliteSaver.from_conn_string(":memory:")
app = workflow.compile(
checkpointer=memory,
interrupt_before=["finalize"] # Pause vor dem finalen Schritt
)
config = {"configurable": {"thread_id": "research-42"}}
app.invoke({"question": "..."}, config) # Läuft bis "finalize"-Pause
# → Menschliche Prüfung hier einfügen
app.invoke(None, config) # Weiter vom Checkpoint
LangSmith: Debugging und Monitoring von Agents
LangSmith ist das Observability-Layer für LangChain. Jeder LLM-Call, jeder Tool-Aufruf, jede Chain-Ausführung wird als Trace erfasst — mit voller Sichtbarkeit auf Input, Output, Latenz und Token-Verbrauch.
LangSmith Setup (2 Minuten)
# .env Datei
LANGCHAIN_TRACING_V2=true
LANGCHAIN_ENDPOINT="https://api.smith.langchain.com"
LANGCHAIN_API_KEY="ls__dein_api_key"
LANGCHAIN_PROJECT="claude-code-agents"
import os
from dotenv import load_dotenv
load_dotenv()
# Ab hier werden ALLE LangChain-Calls automatisch getraced
result = chain.invoke({"question": "..."})
# → Sichtbar in smith.langchain.com unter Projekt "claude-code-agents"
# Manuelle Traces mit @traceable
from langsmith import traceable
@traceable(name="preprocessing_step")
def preprocess_data(raw_text: str) -> str:
# Diese Funktion erscheint als eigener Span im Trace
return raw_text.strip().lower()
# Evaluierungen erstellen
from langsmith.evaluation import evaluate
results = evaluate(
lambda inputs: chain.invoke(inputs),
data="mein-test-dataset",
evaluators=["correctness", "relevance"]
)
LangSmith-Workflow mit Claude Code: Lass Claude Code deine Chains implementieren, dann öffne LangSmith und schau dir die Traces an. Häufigste Bugs: falsches Prompt-Format, fehlende Tool-Descriptions, Memory-Key-Konflikte — alles sofort im Trace sichtbar.
Datasets & Regression Testing
LangSmith ermöglicht es, aus echten Produktions-Runs automatisch Test-Datasets zu erstellen. So merkst du sofort, wenn ein Prompt-Update eine Regression verursacht — bevor es in Produktion geht.
from langsmith import Client
client = Client()
# Dataset aus Produktion erstellen
dataset = client.create_dataset(
dataset_name="production-edge-cases",
description="Schwierige Anfragen aus Produktion"
)
# Testfälle hinzufügen
client.create_examples(
inputs=[{"question": "Komplexe Anfrage 1"}],
outputs=[{"answer": "Erwartete Antwort"}],
dataset_id=dataset.id
)
Bereit für produktionsreife LangChain-Agenten?
Starte kostenlos und lass Claude Code deine komplexen KI-Workflows bauen — von LCEL Chains bis zu LangGraph State-Machines.
Kostenlos testen →
Fazit: LangChain + Claude Code = Production-Ready AI
Das LangChain-Ökosystem 2026 ist ausgereifte Infrastruktur. LCEL macht Chains komponierbar und testbar. LangGraph löst die Grenzen einfacher ReAct-Loops. LangSmith gibt dir die Sichtbarkeit, die du in Produktion brauchst.
Der entscheidende Vorteil von Claude Code als Entwicklungspartner: Du beschreibst dein Ziel, Claude Code generiert die vollständige Implementierung — inklusive Fehlerbehandlung, Retry-Logik und Tests. Was früher Tage dauerte, entsteht in Stunden.
- LCEL: Starte mit einfachen Chains, komposiere modular
- Agents: Nur wenn dynamische Tool-Auswahl nötig ist
- Memory: Buffer für Kurzzeitgedächtnis, VectorStore für Langzeit
- LangGraph: Für komplexe Multi-Step-Workflows mit Kontrolle
- LangSmith: Immer an — Observability ist kein Optional-Feature