{"slug": "langchain-series-4-chains-explained-building-ai-workflows-with-lcel", "title": "LangChain Series #4: Chains Explained — Building AI Workflows with LCEL", "summary": "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.", "body_md": "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.\n\nIn the previous article, we learned how to create prompts using PromptTemplate, ChatPromptTemplate, and Output Parsers.\n\nBut a real AI application doesn’t stop after sending a single prompt to an LLM.\n\nMost applications involve multiple steps:\n\nThis is exactly what **Chains** helps us accomplish.\n\nA Chain connects multiple LangChain components into a single executable workflow.\n\nA Chain is a sequence of connected components where the output of one component becomes the input of the next.\n\nInstead of manually calling every component, LangChain lets us connect them using the **LangChain Expression Language (LCEL)**.\n\nWithout chains:\n\n```\nprompt.invoke()model.invoke()parser.invoke()\n```\n\nWe manually call every component.\n\nWith chains:\n\n```\nchain = prompt | model | parser\n```\n\nOne line executes the entire workflow.\n\nBenefits:\n\nLCEL introduces the | operator.\n\nInstead of writing nested function calls, we compose pipelines.\n\n```\nchain = prompt | model | parser\n```\n\nEach component automatically passes its output to the next component.\n\nThis makes AI workflows easier to build and maintain.\n\nA 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.\n\n``` python\nfrom 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()\n```\n\nA **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.\n\nFor 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:\n\nThis approach makes the workflow more modular, reusable, and easier to maintain.\n\n``` python\nfrom 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)\n```\n\nA **Parallel Chain** is a workflow where **multiple chains execute simultaneously on the same input**, instead of running one after another.\n\nUnlike 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.\n\nUse a Parallel Chain when multiple tasks:\n\n``` python\nfrom 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\"])\n```\n\nA **Conditional Chain** is a workflow where the **next chain is chosen based on a condition or decision**.\n\nUnlike 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.\n\nFor 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.\n\nInstead of executing every chain, LangChain runs **only the branch whose condition is satisfied**.\n\nUse a Conditional Chain whenever your application needs to **make decisions** before choosing the next action.\n\nExamples include:\n\n``` python\nfrom 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)\n```\n\nChains are the backbone of LangChain applications.\n\nInstead of manually managing prompts, models, and parsers, LCEL allows us to connect components into reusable AI workflows using a simple pipeline syntax.\n\nBy understanding **Simple**, **Sequential**, **Parallel**, and **Conditional** Chains, you can build applications ranging from basic chatbots to sophisticated AI systems with multiple decision paths.\n\nIn 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.\n\n**Code Repository: **[https://github.com/Atul245/LangChain-for-developers](https://github.com/Atul245/LangChain-for-developers)\n\nIf you found this article helpful, consider:\n\n⭐ Starring the repository\n\n🍴 Forking the repository\n\n👤 Following me for more content on LangChain, Generative AI, and AI Engineering\n\n**Connect with me on LinkedIn:** [https://www.linkedin.com/in/atulkumar8/](https://www.linkedin.com/in/atulkumar8/)\n\n[🚀 LangChain Series #4: Chains Explained — Building AI Workflows with LCEL](https://pub.towardsai.net/langchain-series-4-chains-explained-building-ai-workflows-with-lcel-1d4f125ea740) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/langchain-series-4-chains-explained-building-ai-workflows-with-lcel", "canonical_source": "https://pub.towardsai.net/langchain-series-4-chains-explained-building-ai-workflows-with-lcel-1d4f125ea740?source=rss----98111c9905da---4", "published_at": "2026-07-03 22:01:01+00:00", "updated_at": "2026-07-03 22:23:45.651788+00:00", "lang": "en", "topics": ["developer-tools", "large-language-models", "ai-tools", "machine-learning"], "entities": ["LangChain", "HuggingFace", "Qwen", "Meta", "Llama"], "alternates": {"html": "https://wpnews.pro/news/langchain-series-4-chains-explained-building-ai-workflows-with-lcel", "markdown": "https://wpnews.pro/news/langchain-series-4-chains-explained-building-ai-workflows-with-lcel.md", "text": "https://wpnews.pro/news/langchain-series-4-chains-explained-building-ai-workflows-with-lcel.txt", "jsonld": "https://wpnews.pro/news/langchain-series-4-chains-explained-building-ai-workflows-with-lcel.jsonld"}}