cd /news/developer-tools/langchain-series-4-chains-explained-… · home topics developer-tools article
[ARTICLE · art-47391] src=pub.towardsai.net ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

LangChain Series #4: Chains Explained — Building AI Workflows with LCEL

LangChain released the fourth installment of its learning series, explaining how to build AI workflows using Chains and the LangChain Expression Language (LCEL). The article demonstrates Simple, Sequential, Parallel, and Conditional Chains with Python examples, showing how LCEL's pipe operator simplifies connecting prompts, models, and parsers into scalable pipelines.

read5 min views1 publishedJul 3, 2026

This is the fourth article in my LangChain learning series. In the previous article, we explored prompts and learned how to communicate effectively with language models. Now it’s time to connect those components into complete AI workflows. In this article, we’ll explore Chains in LangChain and learn how to build Simple, Sequential, Parallel, and Conditional Chains using the LangChain Expression Language (LCEL). Through practical Python examples, you’ll understand how these chain patterns simplify the development of scalable, maintainable AI applications.

In the previous article, we learned how to create prompts using PromptTemplate, ChatPromptTemplate, and Output Parsers.

But a real AI application doesn’t stop after sending a single prompt to an LLM.

Most applications involve multiple steps:

This is exactly what Chains helps us accomplish.

A Chain connects multiple LangChain components into a single executable workflow.

A Chain is a sequence of connected components where the output of one component becomes the input of the next.

Instead of manually calling every component, LangChain lets us connect them using the LangChain Expression Language (LCEL).

Without chains:

prompt.invoke()model.invoke()parser.invoke()

We manually call every component.

With chains:

chain = prompt | model | parser

One line executes the entire workflow.

Benefits:

LCEL introduces the | operator.

Instead of writing nested function calls, we compose pipelines.

chain = prompt | model | parser

Each component automatically passes its output to the next component.

This makes AI workflows easier to build and maintain.

A Simple Chain is the most basic LangChain workflow. It connects a prompt, an LLM, and an output parser into a single pipeline. The output of one component automatically becomes the input of the next.

from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom dotenv import load_dotenvfrom langchain_core.prompts import PromptTemplatefrom langchain_core.output_parsers import StrOutputParser# Load environment variablesload_dotenv()# Prompt templateprompt = PromptTemplate(    template="Generate 5 interesting facts about {topic}",    input_variables=["topic"])# Load Hugging Face modelllm = HuggingFaceEndpoint(    repo_id="Qwen/Qwen2.5-7B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)# Convert AIMessage -> Stringparser = StrOutputParser()# Build the chainchain = prompt | model | parser# Executeresult = chain.invoke({    "topic": "cricket"})print(result)# Visualize chainchain.get_graph().print_ascii()

A Sequential Chain is a workflow where the output of one chain becomes the input of the next chain. Unlike a Simple Chain, which performs only one task, a Sequential Chain breaks a complex problem into multiple steps, with each step depending on the previous one.

For example, instead of asking an LLM to generate a report and summarize it in a single prompt, we can split the task into two stages:

This approach makes the workflow more modular, reusable, and easier to maintain.

from dotenv import load_dotenvfrom langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom langchain_core.prompts import PromptTemplatefrom langchain_core.output_parsers import StrOutputParserload_dotenv()# ---------------------------------------# Load Hugging Face Model# ---------------------------------------llm = HuggingFaceEndpoint(    repo_id="meta-llama/Llama-3.1-8B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)# ---------------------------------------# Output Parser# ---------------------------------------parser = StrOutputParser()# ---------------------------------------# Prompt 1# Generate a Detailed Report# ---------------------------------------report_prompt = PromptTemplate(    template="""Write a detailed report about {topic}.Include:- Introduction- Working Principle- Advantages- Applications- Conclusion""",    input_variables=["topic"])# ---------------------------------------# Prompt 2# Summarize the Report# ---------------------------------------summary_prompt = PromptTemplate(    template="""Summarize the following report in 5 concise bullet points.Report:{report}""",    input_variables=["report"])# ---------------------------------------# Sequential Chain# ---------------------------------------chain = (    report_prompt    | model    | parser    | {"report": lambda x: x}    | summary_prompt    | model    | parser)# ---------------------------------------# Execute Chain# ---------------------------------------result = chain.invoke({    "topic": "Retrieval-Augmented Generation (RAG)"})print(result)

A Parallel Chain is a workflow where multiple chains execute simultaneously on the same input, instead of running one after another.

Unlike a Sequential Chain, where each step waits for the previous one to finish, a Parallel Chain performs independent tasks at the same time. This reduces execution time and allows you to generate multiple outputs from the same input.

Use a Parallel Chain when multiple tasks:

from dotenv import load_dotenvfrom langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom langchain_core.prompts import PromptTemplatefrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.runnables import RunnableParallelload_dotenv()# -------------------------------# Load Hugging Face Model# -------------------------------llm = HuggingFaceEndpoint(    repo_id="Qwen/Qwen2.5-7B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)parser = StrOutputParser()# -------------------------------# Prompt 1: Generate Notes# -------------------------------notes_prompt = PromptTemplate(    template="""Generate concise study notes about the following topic.Topic:{topic}""",    input_variables=["topic"])# -------------------------------# Prompt 2: Generate Quiz# -------------------------------quiz_prompt = PromptTemplate(    template="""Generate five multiple-choice questions about the following topic.Topic:{topic}""",    input_variables=["topic"])# -------------------------------# Create Parallel Chain# -------------------------------parallel_chain = RunnableParallel({    "Notes":        notes_prompt        | model        | parser,    "Quiz":        quiz_prompt        | model        | parser})# -------------------------------# Execute# -------------------------------result = parallel_chain.invoke({    "topic": "LangChain"})print("========== NOTES ==========\n")print(result["Notes"])print("\n========== QUIZ ==========\n")print(result["Quiz"])

A Conditional Chain is a workflow where the next chain is chosen based on a condition or decision.

Unlike a Sequential Chain, which always follows the same execution path, a Conditional Chain dynamically decides which branch to execute depending on the output of a previous step.

For example, imagine you’re building a customer support system. When a customer submits feedback, the application first analyzes the sentiment. If the sentiment is positive, it sends a thank-you response. If it’s negative, it forwards the complaint to customer support.

Instead of executing every chain, LangChain runs only the branch whose condition is satisfied.

Use a Conditional Chain whenever your application needs to make decisions before choosing the next action.

Examples include:

from dotenv import load_dotenvfrom langchain_huggingface import ChatHuggingFace, HuggingFaceEndpointfrom langchain_core.prompts import PromptTemplatefrom langchain_core.output_parsers import StrOutputParserfrom langchain_core.runnables import RunnableBranchload_dotenv()# ------------------------------------# Load Model# ------------------------------------llm = HuggingFaceEndpoint(    repo_id="Qwen/Qwen2.5-7B-Instruct",    task="text-generation")model = ChatHuggingFace(llm=llm)parser = StrOutputParser()# ------------------------------------# Prompt for Positive Feedback# ------------------------------------positive_prompt = PromptTemplate(    template="""Write a polite thank-you email for the following positive customer feedback.Feedback:{feedback}""",    input_variables=["feedback"])# ------------------------------------# Prompt for Negative Feedback# ------------------------------------negative_prompt = PromptTemplate(    template="""Write an apology email and inform the customer that the issue has been forwarded to customer support.Feedback:{feedback}""",    input_variables=["feedback"])# ------------------------------------# Create Conditional Chain# ------------------------------------chain = RunnableBranch(    (        lambda x: "good" in x["feedback"].lower()               or "excellent" in x["feedback"].lower()               or "amazing" in x["feedback"].lower(),        positive_prompt | model | parser    ),    negative_prompt | model | parser)# ------------------------------------# Execute# ------------------------------------result = chain.invoke({    "feedback":    "The service was excellent and your support team was amazing."})print(result)

Chains are the backbone of LangChain applications.

Instead of manually managing prompts, models, and parsers, LCEL allows us to connect components into reusable AI workflows using a simple pipeline syntax.

By understanding Simple, Sequential, Parallel, and Conditional Chains, you can build applications ranging from basic chatbots to sophisticated AI systems with multiple decision paths.

In the next article, we’ll explore Runnables in LangChain and learn how the Runnable interface powers LCEL through composition, parallel execution, branching, and reusable AI workflows.

**Code Repository: **https://github.com/Atul245/LangChain-for-developers

If you found this article helpful, consider:

⭐ Starring the repository

🍴 Forking the repository

👤 Following me for more content on LangChain, Generative AI, and AI Engineering

Connect with me on LinkedIn: https://www.linkedin.com/in/atulkumar8/

🚀 LangChain Series #4: Chains Explained — Building AI Workflows with LCEL was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #developer-tools 4 stories · sorted by recency
── more on @langchain 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/langchain-series-4-c…] indexed:0 read:5min 2026-07-03 ·