…
Skip to content
Topics
On this page

LangChain Tutorial

LangChain is an open-source Python and JavaScript framework for building applications on large language models. It provides model integrations, tool definitions, prompt templates, composable chains and a ready tool-calling agent, so developers can connect a model to external functions and data with little custom code.

  • Model integrations: Provider packages expose chat models, such as Claude, through one common interface, so switching providers requires minimal modification.
  • Tools: The @tool decorator converts a typed Python function into a tool definition that the model can request with arguments.
  • Agents: An agent constructor combines a model, a tool list and a system prompt into an iterative reasoning and acting loop.
  • Chains: The pipe operator composes prompts, models and output parsers into a fixed, predictable pipeline without autonomous decisions.
  • Messages: Every step exchanges typed message objects, so tool invocations, observations and final answers remain inspectable.
The incident triage agent in LangChainThe goal, a 5xx spike on the checkout service, goes to an agent built with create_agent and ChatAnthropic. The agent calls three read tools defined with the tool decorator and receives their results. When it calls rollback_deploy, the tool checks the approved set in code and returns a pending status unless an engineer approved the rollback. The findings then pass through a fixed chain of prompt, model and parser that writes an incident note. The flow is illustrative.Goal5xx on checkoutcreate_agentChatAnthropicRead tools@tool x3rollback_deployapproved set?Note chainprompt | model | parser
The incident triage agent in LangChain

For example, a LangChain agent receives a report of a 5xx spike on the checkout service, calls its log, metric and deployment tools, and proposes a rollback that only runs after an engineer approves it.

The identical agent appears in the Claude Agent SDK tutorial and the LangGraph tutorial. This LangChain Python agent places the approval rule inside the tool itself, which is the simplest pattern that the prebuilt agent supports.

Prerequisites

  • Python 3.11: LangChain requires Python 3.10 or later, and the examples target version 3.11.
  • Agent fundamentals: Familiarity with tool calling and the ReAct agent pattern of reasoning, acting and observing.
  • Credentials: An Anthropic API key stored in the ANTHROPIC_API_KEY environment variable, never written into the code.
  • Optional comparison: Reading the Claude Agent SDK tutorial first clarifies which responsibilities each framework handles automatically.

Setup

Create a virtual environment and install LangChain with the Anthropic integration at pinned versions.

Bash
python3.11 -m venv .venv
source .venv/bin/activate
pip install langchain==1.0.0 langchain-anthropic==1.0.0
export ANTHROPIC_API_KEY="paste-your-key-here"

Step 1: Write the Incident Tools in Plain Python

The tool logic is written without any framework dependency, so its behaviour can be tested deterministically on any machine. The rollback function contains the approval guard, and without an approved identifier it only records a pending request instead of changing production. Save the module as incident_tools.py.

Python
# incident_tools.py: canned data and plain functions, before any LangChain code.
import json

LOGS = {
    "checkout": [
        "14:05:12 ERROR POST /api/pay 502 payment client timeout after 2000 ms",
        "14:05:13 ERROR POST /api/pay 502 payment client timeout after 2000 ms",
        "14:06:40 WARN retry budget exhausted for payments-api",
    ],
}
METRICS = {"checkout": {"5xx_rate": "12.0%", "baseline_5xx_rate": "0.2%", "p95_latency_ms": 2140}}
DEPLOYS = {
    "checkout": [
        {"version": "v2.4.1", "at": "14:03", "change": "payment client timeout 5000 ms to 2000 ms"},
    ],
}

def read_logs(service):
    return "\n".join(LOGS.get(service, ["no log lines found"]))

def get_metrics(service):
    return json.dumps(METRICS.get(service, {}))

def list_recent_deploys(service):
    return json.dumps(DEPLOYS.get(service, []))

def rollback_deploy(service, version, approved):
    # The guard lives in code: without a human approval, only a request is recorded.
    key = f"{service}@{version}"
    if key not in approved:
        return f"PENDING_APPROVAL: rollback of {key} needs an on-call engineer"
    return f"ROLLED_BACK: {service} is back on the release before {version}"

if __name__ == "__main__":
    print(get_metrics("checkout"))
    print(list_recent_deploys("checkout"))
    print(rollback_deploy("checkout", "v2.4.1", approved=set()))
    print(rollback_deploy("checkout", "v2.4.1", approved={"checkout@v2.4.1"}))

Output:

Example
{"5xx_rate": "12.0%", "baseline_5xx_rate": "0.2%", "p95_latency_ms": 2140}
[{"version": "v2.4.1", "at": "14:03", "change": "payment client timeout 5000 ms to 2000 ms"}]
PENDING_APPROVAL: rollback of checkout@v2.4.1 needs an on-call engineer
ROLLED_BACK: checkout is back on the release before v2.4.1
  • Deterministic guard: The rollback outcome depends exclusively on the approved set, never on the model's wording or reasoning.
  • Readable observations: Each tool returns a concise string, which the model receives as the observation for its next decision.
  • Framework independence: The same module serves the other two tutorials, which isolates the differences between the frameworks themselves.

Step 2: Define LangChain Tools with @tool

The @tool decorator inspects the function name, the type hints and the docstring, then generates the JSON schema that the model receives. The approved set is loaded from an environment variable that only the on-call engineer configures, so the model has no mechanism to grant its own approval.

Python
# lc_tools.py: the incident functions wrapped as LangChain tools.
import os

from langchain_core.tools import tool

import incident_tools as it

APPROVED_ROLLBACKS = {k for k in os.environ.get("APPROVED_ROLLBACKS", "").split(",") if k}

@tool
def read_logs(service: str) -> str:
    """Read recent error log lines for a service."""
    return it.read_logs(service)

@tool
def get_metrics(service: str) -> str:
    """Get the current 5xx rate, its baseline and p95 latency for a service."""
    return it.get_metrics(service)

@tool
def list_recent_deploys(service: str) -> str:
    """List deploys of a service in the last 24 hours, with their changes."""
    return it.list_recent_deploys(service)

@tool
def rollback_deploy(service: str, version: str) -> str:
    """Roll back a production deploy. Returns PENDING_APPROVAL until an engineer approves it."""
    return it.rollback_deploy(service, version, APPROVED_ROLLBACKS)

TOOLS = [read_logs, get_metrics, list_recent_deploys, rollback_deploy]
  • Descriptive docstrings: The model selects tools by reading these descriptions, so each one states precisely what the tool returns.
  • Typed arguments: The str annotations become required string parameters, and LangChain validates the arguments before the function executes.

Step 3: Build a LangChain Agent Example with Claude

The ChatAnthropic class reads the API key from the environment automatically. The LangChain create_agent() function combines the model, the tools and the system prompt into a tool-calling loop that terminates when the model produces a final answer without further tool requests. Earlier LangChain releases used AgentExecutor, which now resides in a separate legacy package.

Python
# triage_agent.py: the LangChain incident triage agent.
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic

from lc_tools import TOOLS

SYSTEM = (
    "You are an on-call triage agent. Read logs, metrics and recent deploys before "
    "naming a cause. If a recent deploy explains the errors, call rollback_deploy. "
    "If the result is PENDING_APPROVAL, stop and ask the engineer to approve it."
)

model = ChatAnthropic(model="claude-sonnet-5", temperature=0, max_tokens=1024)
agent = create_agent(model=model, tools=TOOLS, system_prompt=SYSTEM)

GOAL = "The checkout service has a 5xx spike. Find the likely cause and propose an action."
result = agent.invoke({"messages": [{"role": "user", "content": GOAL}]})

for message in result["messages"]:
    for call in getattr(message, "tool_calls", []):
        print(f"Tool call: {call['name']} {call['args']}")
print(f"Agent: {result['messages'][-1].text}")
  • Temperature zero: A deterministic sampling setting reduces variation between investigations of the same incident.
  • Message history: The returned state contains every human, AI and tool message, which supports auditing and debugging.

Step 4: Summarise the Incident with a Chain

A chain is a fixed pipeline in which the application, not the model, determines every step. Here, a prompt template, the same model and a string parser transform the agent's findings into a short, consistently formatted note for the incident channel.

Python
# incident_note.py: an LCEL chain that formats the agent's findings.
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

from triage_agent import model, result

prompt = ChatPromptTemplate.from_messages([
    ("system", "Write a three-line incident note: impact, likely cause, next action."),
    ("human", "{findings}"),
])
note_chain = prompt | model | StrOutputParser()
print(note_chain.invoke({"findings": result["messages"][-1].text}))

Output

The LangChain code was not executed for this page, so the output is illustrative. The first run stops at the approval guard; the engineer then exports APPROVED_ROLLBACKS=checkout@v2.4.1 and runs the agent again.

Example
Tool call: get_metrics {'service': 'checkout'}
Tool call: read_logs {'service': 'checkout'}
Tool call: list_recent_deploys {'service': 'checkout'}
Tool call: rollback_deploy {'service': 'checkout', 'version': 'v2.4.1'}
Agent: The 5xx rate is 12.0% against a 0.2% baseline, caused by payment client
timeouts after v2.4.1 cut the timeout to 2000 ms. The rollback of v2.4.1 is
PENDING_APPROVAL; please approve it to proceed.

Impact: checkout 5xx rate at 12.0% (baseline 0.2%).
Likely cause: v2.4.1 reduced the payment client timeout to 2000 ms.
Next action: roll back v2.4.1 after on-call approval.
  • Tool order: The model chose the order of tool calls; a different run may read the logs first.
  • Guard in practice: The rollback tool was called but returned a pending status, so nothing changed in production.
  • Limitation: A second run repeats the investigation. The LangGraph tutorial pauses and resumes the same run instead, and LangChain offers a human-in-the-loop middleware for the same purpose.

Common Errors

  • ImportError: cannot import name 'AgentExecutor' from 'langchain.agents': The code follows an older tutorial, so switch to create_agent() or install the legacy package that now contains the executor.
  • ValueError: Function must have a docstring if description not provided.: A decorated tool has no docstring, so add a one-line description of what the tool does.
  • ModuleNotFoundError: No module named 'langchain_anthropic': The integration package is missing from the active environment, so install it with the pinned version.
  • anthropic.NotFoundError: The model identifier is incorrect or unavailable to the account, so compare it with the current model list in the Anthropic documentation.
  • anthropic.AuthenticationError: The API rejected the key with status 401, so confirm that the environment variable is exported in the same terminal session.
  • GraphRecursionError: The agent exceeded its step limit, usually because a tool keeps returning an unhelpful result, so tighten the tool descriptions and the system prompt.

Next Steps

Quick Quiz

Pick an answer to check yourself. Nothing is saved.

Question 1 / 3

  1. 1. In the LangChain triage agent, what prevents an unapproved production rollback?

Frequently Asked Questions

Is LangChain still used for building agents?

LangChain remains a widely used framework for connecting language models to tools, prompts and data sources. Its agent constructor now runs on LangGraph internally, so an agent can later move to a custom graph without rewriting its tools.

What is the difference between LangChain and LangGraph?

LangChain provides model integrations, tools, prompts and a ready agent loop. LangGraph is a lower-level library for writing that loop as an explicit graph with state, branches, persistence and human interrupts.

Does LangChain work with Claude?

Yes. The langchain-anthropic package provides the ChatAnthropic class, which reads the API key from the ANTHROPIC_API_KEY environment variable and supports tool calling and structured output.

Why does a LangChain tool need a docstring?

The @tool decorator turns the docstring into the tool description that the model reads. Without it the decorator raises an error, and a vague description leads the model to call the wrong tool.