LangChain-agents: de complete technische gids voor 2026

Surya Pratap
By Surya Pratap

20 juni 2026

14 min leestijd

AI en technologie
LangChain-agents draaiend in productieLangChain-agentsHover to explore
Een agent is geen prompt maar een loop: waarnemen, redeneren, handelen, herhalen tot het klaar is.

Een LLM die vragen beantwoordt is nuttig. Een LLM die dingen kan doen — je database bevragen, een Slack-bericht sturen, een refund afhandelen en daarna terugkoppelen wat er gebeurd is — is een product. LangChain-agents zijn in 2026 de standaardmanier om die loop te bouwen. Deze gids gaat van het mentale model tot productiecode: de agent-loop, tools schrijven, memory en state, structured output, streaming, foutafhandeling, en wat volgens r/LangChain, r/LocalLLaMA en de AI-hoek van X wel en niet werkt.

Deze gids is gebaseerd op de LangChain v1 agent-documentatie, de LangGraph-documentatie en terugkerende discussies op r/LangChain en @LangChainAI op X.

1. De agent-loop: wat er tijdens runtime echt gebeurt

Elke LangChain-agent draait dezelfde loop, welk model je ook gebruikt:

  1. Waarnemen — het LLM krijgt de gespreksgeschiedenis plus de lijst met beschikbare tools (naam, beschrijving, JSON-schema voor de argumenten).
  2. Redeneren — het model bepaalt of het een tool aanroept of een eindantwoord geeft. Moderne modellen gebruiken native tool calling en parsen geen JSON meer uit vrije tekst.
  3. Handelen — bij een tool-aanroep voert LangChain die uit en hangt het resultaat als ToolMessage aan het gesprek.
  4. Herhalen — de loop draait door tot het model een gewoon antwoord geeft zonder tool-aanroep, of tot de ingestelde max-iteraties bereikt is.

Meer is het niet. De verfijning zit in welke tools je aanbiedt en hoe je de loop begrenst, niet in magie binnen het framework.

2. Je eerste LangChain-agent in 15 regels

Met create_agent uit LangChain v1 blijft er nauwelijks boilerplate over:

from langchain.agents import create_agent
from langchain.tools import tool

@tool
def search_orders(order_id: str) -> str:
    """Look up an order by ID and return its current status."""
    # Replace with your real DB call
    return f"Order {order_id}: Shipped, arriving 2026-06-23."

@tool
def issue_refund(order_id: str, reason: str) -> str:
    """Issue a full refund for an order given a reason."""
    return f"Refund issued for order {order_id}. Reason: {reason}."

agent = create_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[search_orders, issue_refund],
    system_prompt=(
        "You are a helpful customer support agent. "
        "Always look up the order before issuing a refund."
    ),
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "Refund order #4821 — it arrived broken."}]
})
print(result["messages"][-1].content)

Onder water roept de agent search_orders("4821") aan, leest het resultaat, roept dan issue_refund("4821", "arrived broken") aan en geeft ten slotte een bevestiging terug — allemaal binnen één invoke, zonder handmatige orkestratie.

3. Goede tools schrijven: hier gaan de meeste agents onderuit

De grootste hefboom op de kwaliteit van een agent is het ontwerp van je tools, niet de keuze van je model. Het model kiest een tool puur op basis van de functienaam, de docstring en het argumentschema. Zijn die slecht, dan redt geen enkele prompt-truc je nog.

Regels die in de praktijk standhouden:

  • Eén actie per tool. search_and_refund() is een valkuil: splits hem. Het model moet elke stap los kunnen aanroepen.
  • Schrijf de docstring voor het model, niet voor een menselijke lezer. Zet erin wanneer de tool aangeroepen moet worden, wat hij teruggeeft en welke harde voorwaarden gelden ("Roep dit pas aan nadat je hebt bevestigd dat de order bestaat").
  • Geef strings of simpele JSON terug. Het model leest de returnwaarde als tekst. Een diep geneste structuur brengt het in de war; een samenvatting van één zin werkt beter.
  • Vang fouten af in de tool zelf, niet erbuiten. Geef "Error: order not found" terug in plaats van een exception te gooien — dan kan de agent het opnieuw proberen of de fout uitleggen in plaats van om te vallen.
from langchain.tools import tool
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    order_id: str = Field(description="The numeric order ID, e.g. '4821'")
    include_history: bool = Field(
        default=False,
        description="Set True to include the full shipment history"
    )

@tool(args_schema=SearchInput)
def search_orders(order_id: str, include_history: bool = False) -> str:
    """
    Look up an order's current status by order ID.
    Call this FIRST before any action that modifies the order.
    Returns: status string, or an error message if not found.
    """
    try:
        order = db.get_order(order_id)
        if not order:
            return f"Error: order {order_id} not found."
        base = f"Order {order_id}: {order.status}, ETA {order.eta}."
        if include_history:
            base += f" History: {order.shipment_history}"
        return base
    except Exception as e:
        return f"Error fetching order: {str(e)}"

4. Memory en persistente state

Standaard is elke agent.invoke() stateless: de agent vergeet de vorige beurt zodra hij klaar is. Voor gesprekken over meerdere beurten moet je de state expliciet meegeven. LangChain biedt twee patronen:

Patroon A — checkpointing per thread met LangGraph (aanbevolen voor productie)

from langchain.agents import create_agent
from langgraph.checkpoint.memory import MemorySaver

# MemorySaver keeps state in RAM; swap for PostgresSaver in production
checkpointer = MemorySaver()

agent = create_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[search_orders, issue_refund],
    checkpointer=checkpointer,
)

# Same thread_id = same conversation memory
config = {"configurable": {"thread_id": "user-123-session-456"}}

# Turn 1
agent.invoke(
    {"messages": [{"role": "user", "content": "What is the status of order 4821?"}]},
    config=config,
)

# Turn 2 — agent remembers turn 1
agent.invoke(
    {"messages": [{"role": "user", "content": "Go ahead and refund it."}]},
    config=config,
)

Patroon B — samenvatten bij lange contexten

Groeit een thread voorbij het contextvenster van je model, gebruik dan SummarizationMiddleware om oude berichten vóór elke modelaanroep automatisch samen te persen tot een lopende samenvatting. De agent verliest de letterlijke geschiedenis maar houdt de strekking — genoeg voor de meeste support- en assistent-toepassingen.

State-graph van een LangGraph-agentStandaard statefulHover to explore
Het checkpoint-systeem van LangGraph maakt van elke agent een hervatbaar gesprek over meerdere beurten, zelfs na een herstart van de server.

5. Structured output: getypeerde data terugkrijgen

Vaak wil je dat de agent informatie verzamelt en een gevalideerd object teruggeeft in plaats van een lap tekst. Geef een Pydantic-model mee aan response_format en de agent levert binnen dezelfde loop een getypeerd object op, zonder losse parsestap:

from pydantic import BaseModel
from langchain.agents import create_agent

class SupportTicket(BaseModel):
    order_id: str
    issue_type: str          # "refund" | "late_delivery" | "wrong_item"
    recommended_action: str
    confidence: float        # 0.0 – 1.0

agent = create_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[search_orders],
    response_format=SupportTicket,
    system_prompt=(
        "Classify the customer's issue and recommend an action. "
        "Always search the order before classifying."
    ),
)

result = agent.invoke({"messages": [
    {"role": "user", "content": "My order 4821 never arrived — it's been 3 weeks."}
]})

ticket: SupportTicket = result["structured_response"]
print(ticket.issue_type)           # "late_delivery"
print(ticket.recommended_action)   # "escalate to carrier"
print(ticket.confidence)           # 0.92

6. Streaming: de agent snel laten aanvoelen

Het grootste UX-probleem van agents is latency: de gebruiker ziet niets tot de hele loop klaar is. Streaming lost dat op door tokens en tool-events te tonen zodra ze er zijn. LangChain kent twee streaming-modi:

# Mode 1 — stream final output tokens only
for chunk in agent.stream(
    {"messages": [{"role": "user", "content": "Status of order 4821?"}]},
    stream_mode="messages",
):
    if chunk[1].get("langgraph_node") == "agent":
        print(chunk[0].content, end="", flush=True)

# Mode 2 — stream every event (tool calls, results, tokens)
for event in agent.stream(
    {"messages": [{"role": "user", "content": "Status of order 4821?"}]},
    stream_mode="updates",
):
    kind = list(event.keys())[0]
    if kind == "tools":
        print(f"[tool] {event['tools']['messages'][0].name}")
    elif kind == "agent":
        for msg in event["agent"]["messages"]:
            print(msg.content, end="", flush=True)

Gebruik in de praktijk stream_mode="updates" in elke UI met een live "aan het denken"-paneel: zo laat je zien welke tool de agent aanroept zonder op het eindantwoord te wachten.

7. Human-in-the-loop: de enige guardrail die je niet overslaat

Elke agent die geld kan uitgeven, een bericht kan versturen of naar een database kan schrijven, heeft menselijke goedkeuring nodig voor onomkeerbare acties. LangChain v1 geeft je twee opties: middleware voor eenvoudige gevallen, LangGraph-interrupts voor volledige controle.

# Simple approach — middleware
from langchain.agents.middleware import HumanInTheLoopMiddleware

agent = create_agent(
    model="anthropic:claude-sonnet-4-6",
    tools=[search_orders, issue_refund, send_email],
    middleware=[
        HumanInTheLoopMiddleware(
            interrupt_on={"issue_refund": True, "send_email": True}
        )
    ],
)

# Advanced approach — LangGraph interrupt node
from langgraph.types import interrupt

def human_approval_node(state):
    last_tool_call = state["messages"][-1]
    # Pause execution and surface the tool call to your UI
    decision = interrupt({
        "tool": last_tool_call.name,
        "args": last_tool_call.tool_input,
        "prompt": "Approve this action?",
    })
    if decision["approved"]:
        return state  # continue
    # Inject a rejection message back into the graph
    return {"messages": [ToolMessage(content="Action rejected by user.", ...)]}

Middleware heb je sneller draaiend. De LangGraph-interrupt is flexibeler: je kunt argumenten aanpassen in plaats van alleen goedkeuren of afwijzen. In klantprojecten beginnen we vrijwel altijd met middleware en pakken we pas interrupts als gebruikers een tool-aanroep moeten kunnen bewerken voordat die uitgevoerd wordt.

8. ReAct versus tool calling: wat je eigenlijk gebruikt

Dit onderscheid zorgt voor veel verwarring. In LangChain van 2022–2023 was ReAct (Reason + Act) het hoofdpatroon: het model werd gevraagd een "Thought / Action / Observation"-kladblok in platte tekst te produceren, dat LangChain parste om te bepalen wat er aangeroepen moest worden. Het werkte, maar was fragiel — elke afwijking van het formaat brak de parser.

In 2026 gebruikt create_agent native tool calling: het model levert een gestructureerde tool-aanroep in de API-response in plaats van in vrije tekst. Dat is betrouwbaarder, goedkoper (geen dubbele prompt) en wordt door elke grote provider ondersteund. ReAct is nu een terugvaloptie voor modellen zonder native tool calling, niet meer de standaardroute.

KenmerkReAct (legacy)Native tool calling (standaard in v1)
FormaatKladblok in vrije tekstGestructureerde API-response
BetrouwbaarheidGevoelig voor formaatGevalideerd tegen schema
Parallelle tool-aanroepenNeeJa (waar ondersteund)
Geschikt voorLokale modellen zonder tool callingAl het andere

9. Productiechecklist voordat je live gaat

  1. Zet LangSmith er vanaf dag nul in. Stel LANGSMITH_API_KEY en LANGSMITH_TRACING=true in. Elke invoke, elke tool-aanroep en elke token wordt automatisch getraceerd. Daar ben je om twee uur 's nachts blij mee als er iets omvalt in productie.
  2. Stel max_iterations in. Een agent zonder limiet kan eindeloos blijven loopen op een slecht beschreven tool. Begin bij 10 en stel bij zodra je je gebruikelijke loop-diepte kent.
  3. Zet human-in-the-loop op alle destructieve tools. Zonder uitzondering. Eén verkeerd uitgevoerde refund in productie kost meer dan een week engineering.
  4. Test tools eerst afzonderlijk. Schrijf unit tests voor elke toolfunctie met gemockte input. Agent-gedrag is lastig te voorspellen, de correctheid van een tool niet.
  5. Maak een eval-set. Met LangSmith Datasets leg je echte input en verwachte output vast en draai je regressie-evaluaties bij elke modelupgrade. Zonder dat vlieg je blind bij elke versiewissel.
  6. Gebruik een duurzame checkpointer in productie. MemorySaver is prima lokaal, maar wissel hem vóór livegang om voor PostgresSaver of RedisSaver — anders wist een serverherstart alle gespreksstate.

10. Wat Reddit en X zeggen in 2026

Na maanden meelezen op r/LangChain, r/LocalLLaMA en de AI-engineeringhoek van X komt het beeld uit de community neer op een paar terugkerende punten:

  • "Tool-ontwerp is 80% van het probleem." De best gewaardeerde debugposts op r/LangChain gaan bijna altijd over slecht genoemde tools of vage docstrings, niet over bugs in het framework. Hernoem de tool en het werkt.
  • "Overstappen van print-debuggen naar LangSmith was het kantelpunt." Een terugkerend geluid bij bouwers die van demo naar echt product gingen. De trace-weergave laat precies zien welke tool-aanroep faalde en waarom.
  • "Ik heb LangChain vervangen door directe SDK-calls." Nog steeds een veelvoorkomend type post, vooral bij teams die diep op één provider zitten of onder de 100 ms latency willen blijven. Bij simpele pipelines van 1 tot 3 stappen is de overhead van het framework reëel. Niet elke use case heeft het nodig.
  • "De opsplitsing in packages (langchain / langchain-core / langgraph) verwart beginners nog steeds." Het LangChain-team erkent dat. Het mentale model is schoner in v1, maar de installatie laat mensen bij de eerste poging nog struikelen.
  • "Parallelle tool-aanroepen maken complexe lookups eindelijk snel." Wie eerder sequentieel aan elkaar knoopte, ziet 2 tot 3 keer betere latency door het model onafhankelijke tools tegelijk te laten afvuren.

"De vraag in 2026 is niet 'moet ik LangChain gebruiken?' maar 'heb ik checkpointing, observability en provider-onafhankelijke tool calling nodig — of zit ik op één provider, drie stappen, en volstaat een directe call?' Weet welk probleem je hebt voordat je een framework kiest."

11. Wanneer je LangChain-agents gebruikt en wanneer niet

LangChain-agents zijn de juiste keuze zodra je minstens twee van deze dingen nodig hebt:

  • Provider-onafhankelijkheid (dezelfde agent op Claude, GPT of Gemini met één codewijziging)
  • Duurzame state over meerdere beurten, met pauzeren en hervatten
  • Human-in-the-loop op destructieve acties
  • Ingebouwde tracing en evaluatie zonder eigen logging
  • Herbruikbare middleware (PII-redactie, samenvatten, retries)

Pak in plaats daarvan de SDK van de provider als:

  • Je op één provider zit en latency de belangrijkste beperking is (onder de <100ms komen is lastig met de overhead van het framework)
  • Je "agent" eigenlijk 2 of 3 lineaire stappen zonder vertakking is — een pipeline is simpeler dan een graph
  • Het team uitgesproken ideeën heeft over abstracties en de loop liever volledig zelf in de hand houdt

De kern

LangChain-agents zijn in 2026 geen tutorialspeelgoed meer. Met create_agent, native tool calling, state met checkpoints, structured output, streaming en middleware dekt het framework inmiddels alles wat een productie-agent nodig heeft. De leercurve is echt — vooral bij tool-ontwerp en het checkpoint-model van LangGraph — maar je krijgt er een agent voor terug die je kunt observeren, pauzeren, aan een mens kunt overdragen en naar een ander model kunt omzetten zonder je code te herschrijven. Dat is een stevige basis voor elke AI-MVP.

IdeaToMVP Academy

Want to build with AI — not just read about it?

4-week live cohort for founders. Learn to ship AI agents, scope MVPs, and automate your business — taught by the same team that writes these guides.

Explore the Academy →
Share this post :