Strona główna / Artykuły / LangChain, LangGraph, LangSmith and Langflow: What Each Tool Does

Artykuł opublikowany po angielsku.

LangChain, LangGraph, LangSmith and Langflow: What Each Tool Does

Four Lang tools solve different problems. See when to use LangChain pipelines, LangGraph stateful flows, LangSmith tracing and Langflow's visual builder, with code.

1169 słów

Four names from one ecosystem keep appearing together: LangChain, LangGraph, LangSmith and Langflow. People often file them as rival frameworks, yet each covers a separate job.

  • LangChain supplies building blocks such as model wrappers, prompt templates, retrievers, tool bindings and output parsers.
  • LangGraph runs applications that need memory between steps, branching or loops.
  • LangSmith watches what happened and scores it, in development and in production.
  • Langflow puts a drag-and-drop canvas over the same ideas.

LangChain for straight-line pipelines

LangChain wires a model to prompts, retrievers, tools, databases and structured outputs. When work moves one way, from input through a few steps to a result, it's usually the quickest route. Install it together with the OpenAI integration, import a prompt template and a chat model, define the template with a system line and a user line carrying a topic placeholder, and pin a small model at temperature zero for repeatable answers.

pip install langchain langchain-openai
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "You are a concise technical writer."),
        ("user", "Explain {topic} in three bullet points."),
    ]
)
model = ChatOpenAI(
    model="gpt-4.1-mini",
    temperature=0,
)

A pipe operator joins template and model into a chain. Invoking the chain with a topic dictionary returns a reply whose text sits in the content attribute.

chain = prompt | model
response = chain.invoke(
    {"topic": "retrieval-augmented generation"}
)
print(response.content)

Template and model stay separate objects, so either can be swapped, while the chain exposes one clean input shape. It suits integrations, retrieval, tool calling, prompt assembly and output parsing.

LangGraph when the flow has to decide

LangGraph describes an app as a graph. Nodes do work, edges say what runs next, and a typed state object travels along. That pays off once execution may branch, loop, retry, pause or resume. The demo below routes a support question. After installing the package, it imports typing helpers and the graph primitives.

pip install langgraph
from typing import Literal, TypedDict
from langgraph.graph import END, START, StateGraph

The shared state holds a question, a category and an answer. One node assigns a category from the question text, and two more produce the reply, one for billing and one for everything else.

class SupportState(TypedDict):
    question: str
    category: str
    answer: str
def classify(state: SupportState) -> dict:
    question = state["question"].lower()
    category = (
        "billing"
        if "invoice" in question
        else "general"
    )
    return {"category": category}
def answer_billing(state: SupportState) -> dict:
    return {
        "answer": "I will help you review the invoice."
    }
def answer_general(state: SupportState) -> dict:
    return {
        "answer": "I will help you with your request."
    }

A small router returns the label the classifier stored. Assembly registers the four nodes, then adds edges: start leads to the classifier, a conditional edge fans out to the matching answer node, and both answers lead to the end.

def route(
    state: SupportState,
) -> Literal["billing", "general"]:
    return state["category"]
builder = StateGraph(SupportState)
builder.add_node("classify", classify)
builder.add_node("billing", answer_billing)
builder.add_node("general", answer_general)
builder.add_edge(START, "classify")
builder.add_conditional_edges("classify", route)
builder.add_edge("billing", END)
builder.add_edge("general", END)

Compiling the builder gives a runnable graph. Feeding it an invoice question with an empty category sends the request down the billing branch, and printing the answer field confirms which path ran.

graph = builder.compile()
result = graph.invoke(
    {
        "question": "Why is my invoice higher?",
        "category": "",
        "answer": "",
    }
)
print(result["answer"])

The same shape stretches to tool loops, checkpoints, cooperating agents and human approval steps, which is where durable state, routing, cycles and retries earn their keep.

LangSmith for seeing what the system did

LangSmith doesn't compete with the previous two. It makes their behavior visible: prompts, model calls, tool choices, latency, failures, token counts and spend can all be inspected afterwards. Setup is two environment variables, one enabling tracing and one holding the API key.

import os
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = (
    "your-langsmith-api-key"
)
os.environ["LANGSMITH_PROJECT"] = (
    "agent-comparison-demo"
)

The key above is a placeholder. Real credentials belong in the environment or a secrets manager, never in source files. With tracing on, supported LangChain and LangGraph calls appear in the chosen project.

For evaluation, build a dataset resembling real traffic and compare versions on correctness, groundedness, tool-selection accuracy, speed and cost. LangSmith suits debugging, regression suites, production traces, monitoring and feedback analysis.

Langflow for building on a canvas

Langflow is a visual, low-code environment. Inputs, prompts, models, retrievers, vector stores, tools and outputs get dragged onto a canvas and linked. It shines for experiments, demos, teaching and mixed teams.

A deployed flow can be called over HTTP. The client below imports os and requests, reads the server address from an environment variable with the local default port as fallback, and wraps the call in a helper that builds the endpoint URL.

import os
import requests
LANGFLOW_URL = os.getenv(
    "LANGFLOW_URL",
    "http://localhost:7860",
)
FLOW_ID = os.environ["LANGFLOW_FLOW_ID"]
API_KEY = os.environ["LANGFLOW_API_KEY"]
def run_flow(message: str) -> dict:
    url = (
        f"{LANGFLOW_URL}/api/v1/run/{FLOW_ID}"
    )
    headers = {"x-api-key": API_KEY}
    payload = {
        "input_value": message,
        "input_type": "chat",
        "output_type": "chat",
    }

The helper posts the payload with headers and a timeout, checks for HTTP errors and returns the JSON body. Calling it with a comparison question prints the structured result.

response = requests.post(
        url,
        headers=headers,
        json=payload,
        timeout=60,
    )
    response.raise_for_status()
    return response.json()
result = run_flow(
    "Compare LangChain and LangGraph."
)
print(result)

Configuration stays out of the source, requests can't hang forever, and failures raise exceptions. Choose Langflow for visual prototyping, reusable flows, demos and quicker teamwork. Heavily customized production logic may be easier to keep as version-controlled Python.

Putting the four to work on one product

In a customer-support agent, LangChain links the model, prompt, knowledge base and tools. LangGraph governs classification, retrieval, approval and retries. LangSmith records each step and grades quality, speed and cost. Langflow offers a visual draft that stakeholders can click through.

Rules of thumb:

  • Linear pipeline: start with LangChain.
  • State, branching, loops or resumable runs: add LangGraph.
  • Proof of quality: bring in LangSmith.
  • Fast visual experiments: try Langflow.

None replaces another. One supplies components, one state and routing, one observability and evaluation, and one a visual way to build and expose flows. Use the smallest combination the team can still understand, test and trust.