Files
langflow/components-custom-components.html
2026-03-13 15:08:39 +00:00

267 lines
105 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="en" dir="ltr" class="docs-wrapper plugin-docs plugin-id-default docs-version-current docs-doc-page docs-doc-id-Components/components-custom-components" data-has-hydrated="false">
<head>
<meta charset="UTF-8">
<meta name="generator" content="Docusaurus v3.9.2">
<title data-rh="true">Create custom Python components | Langflow Documentation</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:url" content="https://docs.langflow.org/components-custom-components"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docusaurus_version" content="current"><meta data-rh="true" name="docusaurus_tag" content="docs-default-current"><meta data-rh="true" name="docsearch:version" content="current"><meta data-rh="true" name="docsearch:docusaurus_tag" content="docs-default-current"><meta data-rh="true" property="og:title" content="Create custom Python components | Langflow Documentation"><meta data-rh="true" name="description" content="Create your own custom components to add any functionality you need to Langflow, from API integrations to data processing."><meta data-rh="true" property="og:description" content="Create your own custom components to add any functionality you need to Langflow, from API integrations to data processing."><link data-rh="true" rel="icon" href="/img/favicon.ico"><link data-rh="true" rel="canonical" href="https://docs.langflow.org/components-custom-components"><link data-rh="true" rel="alternate" href="https://docs.langflow.org/components-custom-components" hreflang="en"><link data-rh="true" rel="alternate" href="https://docs.langflow.org/components-custom-components" hreflang="x-default"><link data-rh="true" rel="preconnect" href="https://UZK6BDPCVY-dsn.algolia.net" crossorigin="anonymous"><script data-rh="true" type="application/ld+json">{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Create custom Python components","item":"https://docs.langflow.org/components-custom-components"}]}</script><link rel="preconnect" href="https://www.google-analytics.com">
<link rel="preconnect" href="https://www.googletagmanager.com">
<script async src="https://www.googletagmanager.com/gtag/js?id=G-SLQFLQ3KPT"></script>
<script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","G-SLQFLQ3KPT",{})</script>
<link rel="search" type="application/opensearchdescription+xml" title="Langflow Documentation" href="/opensearch.xml">
<script>window._ibmAnalytics={settings:{name:"DataStax",tealiumProfileName:"ibm-subsidiary"},trustarc:{privacyPolicyLink:"https://ibm.com/privacy"},"digitalData.page.services.google.enabled":!0},window.digitalData={page:{pageInfo:{ibm:{siteId:"IBM_"+_ibmAnalytics.settings.name},segment:{enabled:!0,env:"prod",key:"B04fNhD06DqDPuaRfQl5lZ2iQICdxxuh",coremetrics:!1,carbonComponentEvents:!1}},category:{primaryCategory:"PC230"}},commonProperties:{productTitle:"IBM Elite Support for Langflow",productCode:"5900BUB",productCodeType:"WWPC",UT30:"30AS5",instanceId:"docs-site",subscriptionId:"public-access",productPlanName:"Public",productPlanType:"freemium",userId:"IBMid-ANONYMOUS"}}</script>
<script src="//1.www.s81c.com/common/stats/ibm-common.js" async="true"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@550;600&amp;display=swap">
<script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("consent","default",{ad_storage:"denied",ad_user_data:"denied",ad_personalization:"denied",analytics_storage:"denied"})</script>
<script>!function(){function e(){if(void 0!==window.truste&&window.truste.cma){var e=window.truste.cma.callApi("getConsent",window.location.href)||{},n=1===e[2],t=1===e[3];gtag("consent","update",{ad_storage:n?"granted":"denied",ad_user_data:n?"granted":"denied",ad_personalization:n?"granted":"denied",analytics_storage:t?"granted":"denied"})}}window.addEventListener&&(window.addEventListener("cm_data_subject_consent_changed",e),window.addEventListener("cm_consent_preferences_set",e)),"complete"===document.readyState?e():window.addEventListener("load",e)}()</script><link rel="stylesheet" href="/assets/css/styles.ba773e30.css">
<script src="/assets/js/runtime~main.de456ad1.js" defer="defer"></script>
<script src="/assets/js/main.e8d613fb.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<svg style="display: none;"><defs>
<symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
</defs></svg>
<script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top navbarHideable_m1mJ"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/"><div class="navbar__logo"><img src="/img/lf-docs-light.svg" alt="Langflow" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/img/lf-docs-dark.svg" alt="Langflow" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div></a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://github.com/langflow-ai/langflow" target="_blank" class="navbar__item navbar__link header-github-link" data-event="UI Interaction" data-action="clicked" data-channel="docs" data-element-id="social-github" data-namespace="header" data-platform-title="Langflow"></a><a href="https://twitter.com/langflow_ai" target="_blank" class="navbar__item navbar__link header-twitter-link" data-event="UI Interaction" data-action="clicked" data-channel="docs" data-element-id="social-twitter" data-namespace="header" data-platform-title="Langflow"></a><a href="https://discord.gg/EqksyE2EX9" target="_blank" class="navbar__item navbar__link header-discord-link" data-event="UI Interaction" data-action="clicked" data-channel="docs" data-element-id="social-discord" data-namespace="header" data-platform-title="Langflow"></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP systemToggleIcon_QzmC"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search (Meta+k)" aria-keyshortcuts="Meta+k"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="8" stroke="currentColor" fill="none" stroke-width="1.4"></circle><path d="m21 21-4.3-4.3" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"></span></button></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_z2l0"><div class="docsWrapper_hBAB"><button aria-label="Scroll back to top" class="clean-btn theme-back-to-top-button backToTopButton_sjWU" type="button"></button><div class="docRoot_UBD9"><aside class="theme-doc-sidebar-container docSidebarContainer_YfHR"><div class="sidebarViewport_aRkj"><div class="sidebar_njMd sidebarWithHideableNavbar_wUlq"><a tabindex="-1" class="sidebarLogo_isFc" href="/"><img src="/img/lf-docs-light.svg" alt="Langflow" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/img/lf-docs-dark.svg" alt="Langflow" class="themedComponent_mlkZ themedComponent--dark_xIcU"></a><nav aria-label="Docs sidebar" class="menu thin-scrollbar menu_SIkG"><ul class="theme-doc-sidebar-menu menu__list"><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/"><span title="Get started" class="categoryLinkLabel_W154">Get started</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/concepts-overview"><span title="Flows" class="categoryLinkLabel_W154">Flows</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/agents"><span title="Agents" class="categoryLinkLabel_W154">Agents</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/mcp-client"><span title="Model Context Protocol (MCP)" class="categoryLinkLabel_W154">Model Context Protocol (MCP)</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/api-keys-and-authentication"><span title="Develop" class="categoryLinkLabel_W154">Develop</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/deployment-overview"><span title="Deploy" class="categoryLinkLabel_W154">Deploy</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" role="button" aria-expanded="true" href="/concepts-components"><span title="Components reference" class="categoryLinkLabel_W154">Components reference</span></a></div><ul class="menu__list"><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link" tabindex="0" href="/concepts-components"><span title="Components overview" class="linkLabel_WmDU">Components overview</span></a></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-2 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" tabindex="0" href="/chat-input-and-output"><span title="Core components" class="categoryLinkLabel_W154">Core components</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-2 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" tabindex="0" href="/components-bundle-components"><span title="Bundles" class="categoryLinkLabel_W154">Bundles</span></a></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-2 menu__list-item"><a class="menu__link menu__link--active" aria-current="page" tabindex="0" href="/components-custom-components"><span title="Create custom Python components" class="linkLabel_WmDU">Create custom Python components</span></a></li></ul></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/api-reference-api-examples"><span title="API reference" class="categoryLinkLabel_W154">API reference</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/contributing-community"><span title="Contribute" class="categoryLinkLabel_W154">Contribute</span></a></div></li><li class="theme-doc-sidebar-item-category theme-doc-sidebar-item-category-level-1 menu__list-item menu__list-item--collapsed"><div class="menu__list-item-collapsible"><a class="categoryLink_byQd menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/troubleshoot"><span title="Support" class="categoryLinkLabel_W154">Support</span></a></div></li><li class="theme-doc-sidebar-item-link theme-doc-sidebar-item-link-level-1 sidebar-ad">
<a href="https://www.langflow.org/desktop" target="_blank" class="menu__link">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_1645_37)">
<path d="M12 17H20C21.1046 17 22 16.1046 22 15V13M12 17H4C2.89543 17 2 16.1046 2 15V5C2 3.89543 2.89543 3 4 3H10M12 17V21M8 21H12M12 21H16M11.75 10.2917H13.2083L16.125 7.375H17.5833L20.5 4.45833H21.9583M16.125 11.75H17.5833L20.5 8.83333H21.9583M11.75 5.91667H13.2083L16.125 3H17.5833" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_1645_37">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>
<div class="sidebar-ad-text-container">
<span class="sidebar-ad-text">Get started in minutes</span>
<span class="sidebar-ad-text sidebar-ad-text-gradient">Download Langflow Desktop</span>
</div>
</a>
</li></ul></nav></div></div></aside><main class="docMainContainer_TBSr"><div class="container padding-top--md padding-bottom--lg"><div class="row"><div class="col docItemCol_VOVn"><div class="docItemContainer_Djhp"><article><nav class="theme-doc-breadcrumbs breadcrumbsContainer_Z_bl" aria-label="Breadcrumbs"><ul class="breadcrumbs"><li class="breadcrumbs__item"><a aria-label="Home page" class="breadcrumbs__link" href="/"><svg viewBox="0 0 24 24" class="breadcrumbHomeIcon_YNFT"><path d="M10 19v-5h4v5c0 .55.45 1 1 1h3c.55 0 1-.45 1-1v-7h1.7c.46 0 .68-.57.33-.87L12.67 3.6c-.38-.34-.96-.34-1.34 0l-8.36 7.53c-.34.3-.13.87.33.87H5v7c0 .55.45 1 1 1h3c.55 0 1-.45 1-1z" fill="currentColor"></path></svg></a></li><li class="breadcrumbs__item"><span class="breadcrumbs__link">Components reference</span></li><li class="breadcrumbs__item breadcrumbs__item--active"><span class="breadcrumbs__link">Create custom Python components</span></li></ul></nav><div class="tocCollapsible_ETCw theme-doc-toc-mobile tocMobile_ITEo"><button type="button" class="clean-btn tocCollapsibleButton_TO0P">On this page</button></div><div class="theme-doc-markdown markdown"><header><h1>Create custom Python components</h1></header><style>[data-ch-theme="github-dark"] { --ch-t-colorScheme: dark;--ch-t-foreground: #c9d1d9;--ch-t-background: #0d1117;--ch-t-lighter-inlineBackground: #0d1117e6;--ch-t-editor-background: #0d1117;--ch-t-editor-foreground: #c9d1d9;--ch-t-editor-lineHighlightBackground: #6e76811a;--ch-t-editor-rangeHighlightBackground: #ffffff0b;--ch-t-editor-infoForeground: #3794FF;--ch-t-editor-selectionBackground: #264F78;--ch-t-focusBorder: #1f6feb;--ch-t-tab-activeBackground: #0d1117;--ch-t-tab-activeForeground: #c9d1d9;--ch-t-tab-inactiveBackground: #010409;--ch-t-tab-inactiveForeground: #8b949e;--ch-t-tab-border: #30363d;--ch-t-tab-activeBorder: #0d1117;--ch-t-editorGroup-border: #30363d;--ch-t-editorGroupHeader-tabsBackground: #010409;--ch-t-editorLineNumber-foreground: #6e7681;--ch-t-input-background: #0d1117;--ch-t-input-foreground: #c9d1d9;--ch-t-input-border: #30363d;--ch-t-icon-foreground: #8b949e;--ch-t-sideBar-background: #010409;--ch-t-sideBar-foreground: #c9d1d9;--ch-t-sideBar-border: #30363d;--ch-t-list-activeSelectionBackground: #6e768166;--ch-t-list-activeSelectionForeground: #c9d1d9;--ch-t-list-hoverBackground: #6e76811a;--ch-t-list-hoverForeground: #c9d1d9; }</style>
<!-- -->
<p>Create your own custom components to add any functionality you need to Langflow, from API integrations to data processing.</p>
<p>In Langflow&#x27;s node-based environment, each node is a &quot;component&quot; that performs discrete functions.
Custom components in Langflow are built upon:</p>
<ul>
<li class="">The Python class that inherits from <code>Component</code>.</li>
<li class="">Class-level attributes that identify and describe the component.</li>
<li class=""><a href="#inputs-and-outputs" class="">Input and output lists</a> that determine data flow.</li>
<li class="">Methods that define the component&#x27;s behavior and logic.</li>
<li class="">Internal variables for <a href="#error-handling-and-logging" class="">Error handling and logging</a></li>
</ul>
<p>Use the <a href="#quickstart" class="">Custom component quickstart</a> to add an example component to Langflow, and then use the reference guide that follows for more advanced component customization.</p>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="quickstart">Custom component quickstart<a href="#quickstart" class="hash-link" aria-label="Direct link to Custom component quickstart" title="Direct link to Custom component quickstart" translate="no"></a></h2>
<p>Create a custom <code>DataFrameProcessor</code> component by creating a Python file, saving it in the correct folder, including an <code>__init__.py</code> file, and loading it into Langflow.</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="create-a-python-file">Create a Python file<a href="#create-a-python-file" class="hash-link" aria-label="Direct link to Create a Python file" title="Direct link to Create a Python file" translate="no"></a></h3>
<style>[data-ch-theme="github-dark"] { --ch-t-colorScheme: dark;--ch-t-foreground: #c9d1d9;--ch-t-background: #0d1117;--ch-t-lighter-inlineBackground: #0d1117e6;--ch-t-editor-background: #0d1117;--ch-t-editor-foreground: #c9d1d9;--ch-t-editor-lineHighlightBackground: #6e76811a;--ch-t-editor-rangeHighlightBackground: #ffffff0b;--ch-t-editor-infoForeground: #3794FF;--ch-t-editor-selectionBackground: #264F78;--ch-t-focusBorder: #1f6feb;--ch-t-tab-activeBackground: #0d1117;--ch-t-tab-activeForeground: #c9d1d9;--ch-t-tab-inactiveBackground: #010409;--ch-t-tab-inactiveForeground: #8b949e;--ch-t-tab-border: #30363d;--ch-t-tab-activeBorder: #0d1117;--ch-t-editorGroup-border: #30363d;--ch-t-editorGroupHeader-tabsBackground: #010409;--ch-t-editorLineNumber-foreground: #6e7681;--ch-t-input-background: #0d1117;--ch-t-input-foreground: #c9d1d9;--ch-t-input-border: #30363d;--ch-t-icon-foreground: #8b949e;--ch-t-sideBar-background: #010409;--ch-t-sideBar-foreground: #c9d1d9;--ch-t-sideBar-border: #30363d;--ch-t-list-activeSelectionBackground: #6e768166;--ch-t-list-activeSelectionForeground: #c9d1d9;--ch-t-list-hoverBackground: #6e76811a;--ch-t-list-hoverForeground: #c9d1d9; }</style>
<ol>
<li class="">
<p>Create a Python file for your component, such as <code>dataframe_processor.py</code>.</p>
</li>
<li class="">
<p>Write your component as an object of the <a href="https://github.com/langflow-ai/langflow/blob/main/src/backend/base/langflow/custom/custom_component/component.py" target="_blank" rel="noopener noreferrer" class=""><code>Component</code></a> class. Create a new class that inherits from <code>Component</code> and override the base class&#x27;s methods.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Backwards compatibility</div><div class="admonitionContent_BuS1"><p>The <code>lfx</code> import path replaced the <code>import from langflow.custom import Component</code> in Langflow 1.7, but the original input is still compatible and works the same way.</p></div></div>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>from typing import Any, Dict, Optional</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>import pandas as pd</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>from lfx.custom.custom_component.component import Component</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>class DataFrameProcessor(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> &quot;&quot;&quot;A component that processes pandas DataFrames with various operations.&quot;&quot;&quot;</span></div></div><br></code></div></div>
</li>
<li class="">
<p>Define class attributes to provide information about your custom component:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span>from typing import Any, Dict, Optional</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span>import pandas as pd</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span>from lfx.custom.custom_component.component import Component</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span>class DataFrameProcessor(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> &quot;&quot;&quot;A component that processes pandas DataFrames with various operations.&quot;&quot;&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> display_name: str = &quot;DataFrame Processor&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> description: str = &quot;Process and transform pandas DataFrames with various operations like filtering, sorting, and aggregation.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> documentation: str = &quot;https://docs.langflow.org/components-dataframe-processor&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> icon: str = &quot;DataframeIcon&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> priority: int = 100</span></div></div><div><span class="ch-code-line-number">_<!-- -->13</span><div style="display:inline-block;margin-left:16px"><span> name: str = &quot;dataframe_processor&quot;</span></div></div><br></code></div></div>
<ul>
<li class=""><code>display_name</code>: A user-friendly name shown in the visual editor.</li>
<li class=""><code>description</code>: A brief description of what your component does.</li>
<li class=""><code>documentation</code>: A link to detailed documentation.</li>
<li class=""><code>icon</code>: An emoji or icon identifier for visual representation.
Langflow uses <a href="https://lucide.dev/icons" target="_blank" rel="noopener noreferrer" class="">Lucide</a> for icons. To assign an icon to your component, set the icon attribute to the name of a Lucide icon as a string, such as <code>icon = &quot;file-text&quot;</code>. Langflow renders icons from the Lucide library automatically.
For more information, see <a class="" href="/contributing-bundles#add-the-bundle-to-the-frontend-folder">Contributing bundles</a>.</li>
<li class=""><code>priority</code>: An optional integer to control display order. Lower numbers appear first.</li>
<li class=""><code>name</code>: An optional internal identifier that defaults to class name.</li>
</ul>
</li>
<li class="">
<p>Define the component&#x27;s interface by specifying its inputs, outputs, and the method that will process them. The method name must match the <code>method</code> field in your outputs list, as this is how Langflow knows which method to call to generate each output.</p>
<p>This example creates a minimal custom component skeleton.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span>from typing import Any, Dict, Optional</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span>import pandas as pd</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span>from lfx.custom.custom_component.component import Component</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span>class DataFrameProcessor(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> &quot;&quot;&quot;A component that processes pandas DataFrames with various operations.&quot;&quot;&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> display_name: str = &quot;DataFrame Processor&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> description: str = &quot;Process and transform pandas DataFrames with various operations like filtering, sorting, and aggregation.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> documentation: str = &quot;https://docs.langflow.org/components-dataframe-processor&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> icon: str = &quot;DataframeIcon&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> priority: int = 100</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> name: str = &quot;dataframe_processor&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> # input and output lists</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> inputs = []</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> outputs = []</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> # method</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> def some_output_method(self):</span></div></div><div><span class="ch-code-line-number">_<!-- -->21</span><div style="display:inline-block;margin-left:16px"><span> return ...</span></div></div><br></code></div></div>
</li>
</ol>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="custom-component-path">Save the custom component<a href="#custom-component-path" class="hash-link" aria-label="Direct link to Save the custom component" title="Direct link to Save the custom component" translate="no"></a></h3>
<p>Save the custom component in the Langflow directory where the UI will discover and load it.</p>
<p>By default, Langflow looks for custom components in the <code>src/lfx/src/lfx/components</code> directory.</p>
<p>When saving components in the default directory, components must be organized in a specific directory structure to be properly loaded and displayed in the visual editor.</p>
<p>Components must be placed inside category folders, not directly in the base directory.</p>
<p>The category folder name determines where the component appears in the Langflow <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-component" aria-hidden="true"><path d="M15.536 11.293a1 1 0 0 0 0 1.414l2.376 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"></path><path d="M2.297 11.293a1 1 0 0 0 0 1.414l2.377 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414L6.088 8.916a1 1 0 0 0-1.414 0z"></path><path d="M8.916 17.912a1 1 0 0 0 0 1.415l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.415l-2.377-2.376a1 1 0 0 0-1.414 0z"></path><path d="M8.916 4.674a1 1 0 0 0 0 1.414l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"></path></svg> <strong>Core components</strong> menu.
For example, to add the example <code>DataFrameProcessor</code> component to the <strong>Data</strong> category, place it in the <code>data</code> subfolder:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>src/lfx/src/lfx/components/</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── data/ # Category folder (determines menu location)</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── __init__.py # Required - makes it a Python package</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── dataframe_processor.py # Your custom component file</span></div></div><br></code></div></div>
<p>If you&#x27;re creating custom components in a different location using the <code>LANGFLOW_COMPONENTS_PATH</code> <a class="" href="/environment-variables">environment variable</a>, components must be similarly organized in a specific directory structure to be displayed in the visual editor.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>/your/custom/components/path/ # Base directory set by LANGFLOW_COMPONENTS_PATH</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── category_name/</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── __init__.py</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── custom_component.py</span></div></div><br></code></div></div>
<p>You can have multiple category folders to organize components into different categories, with multiple components inside each folder:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>/app/custom_components/</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── data/</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> │ ├── __init__.py</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> │ ├── custom_component.py</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> │ └── dataframe_processor.py</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── tools/</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── __init__.py</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── custom_tool.py</span></div></div><br></code></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="create-the-__init__py-file">Create the <code>__init__.py</code> file<a href="#create-the-__init__py-file" class="hash-link" aria-label="Direct link to create-the-__init__py-file" title="Direct link to create-the-__init__py-file" translate="no"></a></h3>
<p>Each category directory <strong>must</strong> contain an <code>__init__.py</code> file for Langflow to properly recognize and load the components.
This is a Python package requirement that ensures the directory is treated as a module.</p>
<p>To include the <code>DataFrameProcessor</code> component, create a file named <code>__init__.py</code> in your component&#x27;s directory with the following content.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>from .dataframe_processor import DataFrameProcessor</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>__all__ = [&quot;DataFrameProcessor&quot;]</span></div></div><br></code></div></div>
<details class="details_lb9f alert alert--info details_b_Ee" data-collapsed="true"><summary>Lazy load the DataFrameProcessor component</summary><div><div class="collapsibleContent_i85q"><p>Alternatively, you can load your component <strong>lazily</strong>, which is better for performance but a little more complex.</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>from __future__ import annotations</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>from typing import TYPE_CHECKING, Any</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>from lfx.components._importing import import_mod</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>if TYPE_CHECKING:</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> from lfx.components.data.dataframe_processor import DataFrameProcessor</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>_dynamic_imports = {</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> &quot;DataFrameProcessor&quot;: &quot;dataframe_processor&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>}</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>__all__ = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> &quot;DataFrameProcessor&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>def __getattr__(attr_name: str) -&gt; Any:</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> &quot;&quot;&quot;Lazily import data components on attribute access.&quot;&quot;&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> if attr_name not in _dynamic_imports:</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> msg = f&quot;module &#x27;{__name__}&#x27; has no attribute &#x27;{attr_name}&#x27;&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> raise AttributeError(msg)</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> try:</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> except (ModuleNotFoundError, ImportError, AttributeError) as e:</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> msg = f&quot;Could not import &#x27;{attr_name}&#x27; from &#x27;{__name__}&#x27;: {e}&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> raise AttributeError(msg) from e</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> globals()[attr_name] = result</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> return result</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span>def __dir__() -&gt; list[str]:</span></div></div><div><span class="ch-code-line-number">_<!-- -->32</span><div style="display:inline-block;margin-left:16px"><span> return list(__all__)</span></div></div><br></code></div></div><p>For an additional example of lazy loading, see the <a href="https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/components/FAISS/__init__.py" target="_blank" rel="noopener noreferrer" class="">FAISS component</a>.</p></div></div></details>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="load-your-component">Load your component<a href="#load-your-component" class="hash-link" aria-label="Direct link to Load your component" title="Direct link to Load your component" translate="no"></a></h3>
<p>Ensure the application builds your component.</p>
<ol>
<li class="">
<p>To rebuild the backend and frontend, run <code>make install_frontend &amp;&amp; make build_frontend &amp;&amp; make install_backend &amp;&amp; uv run langflow run --port 7860</code>.</p>
</li>
<li class="">
<p>Refresh the frontend application.
Your new <code>DataFrameProcessor</code> component is available in the <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-component" aria-hidden="true"><path d="M15.536 11.293a1 1 0 0 0 0 1.414l2.376 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"></path><path d="M2.297 11.293a1 1 0 0 0 0 1.414l2.377 2.377a1 1 0 0 0 1.414 0l2.377-2.377a1 1 0 0 0 0-1.414L6.088 8.916a1 1 0 0 0-1.414 0z"></path><path d="M8.916 17.912a1 1 0 0 0 0 1.415l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.415l-2.377-2.376a1 1 0 0 0-1.414 0z"></path><path d="M8.916 4.674a1 1 0 0 0 0 1.414l2.377 2.376a1 1 0 0 0 1.414 0l2.377-2.376a1 1 0 0 0 0-1.414l-2.377-2.377a1 1 0 0 0-1.414 0z"></path></svg> <strong>Core components</strong> menu under the <strong>Data</strong> category in the visual editor.</p>
</li>
</ol>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="docker-deployment">Docker deployment<a href="#docker-deployment" class="hash-link" aria-label="Direct link to Docker deployment" title="Direct link to Docker deployment" translate="no"></a></h3>
<p>When running Langflow in Docker, mount your custom components directory and set the <code>LANGFLOW_COMPONENTS_PATH</code> environment variable in the <code>docker run</code> command to point to the custom components directory.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>docker run -d \</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> --name langflow \</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> -p 7860:7860 \</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> -v ./custom_components:/app/custom_components \</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> -e LANGFLOW_COMPONENTS_PATH=/app/custom_components \</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> langflowai/langflow:latest</span></div></div><br></code></div></div>
<p>Create the same custom components directory structure as the example in <a href="#custom-component-path" class="">Save the custom component</a>.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>/app/custom_components/ # LANGFLOW_COMPONENTS_PATH</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── data/</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── __init__.py</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── dataframe_processor.py</span></div></div><br></code></div></div>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="how-components-execute">How components execute<a href="#how-components-execute" class="hash-link" aria-label="Direct link to How components execute" title="Direct link to How components execute" translate="no"></a></h2>
<p>Langflow&#x27;s engine manages:</p>
<ol>
<li class=""><strong>Instantiation</strong>: A component is created and internal structures are initialized.</li>
<li class=""><strong>Assigning Inputs</strong>: Values from the visual editor or connections are assigned to component fields.</li>
<li class=""><strong>Validation and Setup</strong>: Optional hooks like <code>_pre_run_setup</code>.</li>
<li class=""><strong>Outputs Generation</strong>: <code>run()</code> or <code>build_results()</code> triggers output methods.</li>
</ol>
<p>You can customize execution by overriding these optional hooks in your custom component code.</p>
<ul>
<li class="">
<p><strong><code>_pre_run_setup()</code></strong> - Used during <strong>Validation and Setup</strong>.
Add this method inside your component class to initialize component state before execution begins:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>class MyComponent(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> # ... your inputs, outputs, and other attributes ...</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> def _pre_run_setup(self):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> if not hasattr(self, &quot;_initialized&quot;):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> self._initialized = True</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> self.iteration = 0</span></div></div><br></code></div></div>
</li>
<li class="">
<p><strong>Override <code>run</code> or <code>_run</code></strong> - Used during <strong>Outputs Generation</strong>.
Add this method inside your component class to customize the main execution logic:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>class MyComponent(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> async def_run(self):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> # Custom execution logic here</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> # This runs instead of the default output method calls</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> pass</span></div></div><br></code></div></div>
</li>
<li class="">
<p><strong>Store data in <code>self.ctx</code></strong>.
Use <code>self.ctx</code> in any of your component methods to share data between method calls.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span>class MyComponent(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> def _pre_run_setup(self):</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> # Initialize counter in setup</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> self.ctx[&quot;processed_items&quot;] = 0</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> def process_data(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> # Increment counter during processing</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> self.ctx[&quot;processed_items&quot;] += 1</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> return Data(data={&quot;item&quot;: f&quot;processed {self.ctx[&#x27;processed_items&#x27;]}&quot;})</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> def get_summary(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> # Access counter in different method</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> total = self.ctx[&quot;processed_items&quot;]</span></div></div><div><span class="ch-code-line-number">_<!-- -->15</span><div style="display:inline-block;margin-left:16px"><span> return Data(data={&quot;summary&quot;: f&quot;Processed {total} items total&quot;})</span></div></div><br></code></div></div>
</li>
</ul>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="inputs-and-outputs">Inputs and outputs<a href="#inputs-and-outputs" class="hash-link" aria-label="Direct link to Inputs and outputs" title="Direct link to Inputs and outputs" translate="no"></a></h2>
<p>Inputs and outputs are <strong>class-level configurations</strong> that define how data flows through the component, how it appears in the visual editor, and how connections to other components are validated.</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="inputs">Inputs<a href="#inputs" class="hash-link" aria-label="Direct link to Inputs" title="Direct link to Inputs" translate="no"></a></h3>
<p>Inputs are defined in a class-level <code>inputs</code> list. When Langflow loads the component, it uses this list to render component fields and <a class="" href="/concepts-components#component-ports">ports</a> in the visual editor. Users or other components provide values or connections to fill these inputs.</p>
<p>An input is usually an instance of a class from <code>lfx.io</code> (such as <code>StrInput</code>, <code>DataInput</code>, or <code>MessageTextInput</code>).</p>
<p>For example, this component has three inputs: a text field (<code>StrInput</code>), a Boolean toggle (<code>BoolInput</code>), and a dropdown selection (<code>DropdownInput</code>).</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>from lfx.io import StrInput, BoolInput, DropdownInput</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>inputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> StrInput(name=&quot;title&quot;, display_name=&quot;Title&quot;),</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> BoolInput(name=&quot;enabled&quot;, display_name=&quot;Enabled&quot;, value=True),</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> DropdownInput(name=&quot;mode&quot;, display_name=&quot;Mode&quot;, options=[&quot;Fast&quot;, &quot;Safe&quot;, &quot;Experimental&quot;], value=&quot;Safe&quot;)</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><br></code></div></div>
<p>The <code>StrInput</code> creates a single-line text field for entering text. The <code>name=&quot;title&quot;</code> parameter means you access this value in your component methods with <code>self.title</code>, while <code>display_name=&quot;Title&quot;</code> shows &quot;Title&quot; as the label in the visual editor.</p>
<p>The <code>BoolInput</code> creates a boolean toggle that&#x27;s enabled by default with <code>value=True</code>. Users can turn this on or off, and you access the current state with <code>self.enabled</code>.</p>
<p>The <code>DropdownInput</code> provides a selection menu with three predefined options: &quot;Fast&quot;, &quot;Safe&quot;, and &quot;Experimental&quot;.
The <code>value=&quot;Safe&quot;</code> sets &quot;Safe&quot; as the default selection, and you access the user&#x27;s choice with <code>self.mode</code>.</p>
<p>For a list of all available parameters, see the <a href="https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/inputs/input_mixin.py" target="_blank" rel="noopener noreferrer" class="">BaseInputMixin definition</a> in the Langflow codebase.</p>
<p>For a list of all available input types, see the <a href="https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/inputs/inputs.py" target="_blank" rel="noopener noreferrer" class="">input type definitions</a> in the Langflow codebase.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>from lfx.io import StrInput, DataInput, MultilineInput, IntInput, BoolInput, DropdownInput, FileInput, CodeInput, ModelInput, HandleInput, Output</span></div></div><br></code></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="outputs">Outputs<a href="#outputs" class="hash-link" aria-label="Direct link to Outputs" title="Direct link to Outputs" translate="no"></a></h3>
<p>Outputs are defined in a class-level <code>outputs</code> list. When Langflow renders a component, each output becomes a connector point in the visual editor. When you connect something to an output, Langflow automatically calls the corresponding method and passes the returned object to the next component.</p>
<p>An output is usually an instance of <code>Output</code> from <code>lfx.io</code>.</p>
<p>For example, this component has one <code>output</code> that returns a <code>DataFrame</code>:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span>from lfx.io import Output</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span>from lfx.schema import DataFrame</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span>outputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;df_out&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;DataFrame Output&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> method=&quot;build_df&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> )</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span>def build_df(self) -&gt; DataFrame:</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> # Process data and return DataFrame</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> df = DataFrame({&quot;col1&quot;: [1, 2], &quot;col2&quot;: [3, 4]})</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> self.status = f&quot;Built DataFrame with {len(df)} rows.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->16</span><div style="display:inline-block;margin-left:16px"><span> return df</span></div></div><br></code></div></div>
<p>The <code>Output</code> creates a connector point in the visual editor labeled <strong>DataFrame Output</strong>. The <code>name=&quot;df_out&quot;</code> parameter identifies this output, while <code>display_name=&quot;DataFrame Output&quot;</code> shows the label in the UI. The <code>method=&quot;build_df&quot;</code> parameter tells Langflow to call the <code>build_df</code> method when this output is connected to another component.</p>
<p>The <code>build_df</code> method processes data and returns a <code>DataFrame</code>. The <code>-&gt; DataFrame</code> type annotation helps Langflow validate connections and provides color-coding in the visual editor. You can also set <code>self.status</code> to show progress messages in the UI.</p>
<p>For a complete list of all available parameters, see the <a href="https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/template/field/base.py" target="_blank" rel="noopener noreferrer" class="">Output class definition</a> in the Langflow codebase. Common parameters include:</p>
<p><strong>Additional return types:</strong></p>
<ul>
<li class=""><strong><code>Message</code></strong>: Structured chat messages</li>
<li class=""><strong><code>Data</code></strong>: Flexible object with <code>.data</code> and optional <code>.text</code></li>
<li class=""><strong><code>DataFrame</code></strong>: Tabular data (pandas DataFrame subclass)</li>
<li class=""><strong>Primitive types</strong>: <code>str</code>, <code>int</code>, <code>bool</code>, not recommended for type consistency</li>
</ul>
<h4 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="associated-methods">Associated methods<a href="#associated-methods" class="hash-link" aria-label="Direct link to Associated methods" title="Direct link to Associated methods" translate="no"></a></h4>
<p>Each output is linked to a method where the output method name must match the method name. The method typically returns objects like <code>Message</code>, <code>Data</code>, or <code>DataFrame</code>, and can use inputs with <code>self.&lt;input_name&gt;</code>.</p>
<p>For example, the <code>Output</code> defines a connector point called <code>file_contents</code> that will call the <code>read_file</code> method when connected. The <code>read_file</code> method accesses the filename input with <code>self.filename</code>, reads the file content, sets a status message, and returns the content wrapped in a <code>Data</code> object.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span>Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;file_contents&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;File Contents&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> method=&quot;read_file&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span>)</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span>def read_file(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> path = self.filename</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> with open(path, &quot;r&quot;) as f:</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> content = f.read()</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> self.status = f&quot;Read {len(content)} chars from {path}&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> return Data(data={&quot;content&quot;: content})</span></div></div><br></code></div></div>
<h4 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="components-with-multiple-outputs">Components with multiple outputs<a href="#components-with-multiple-outputs" class="hash-link" aria-label="Direct link to Components with multiple outputs" title="Direct link to Components with multiple outputs" translate="no"></a></h4>
<p>A component can define multiple outputs.
Each output can have a different corresponding method.</p>
<p>For example:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>outputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> Output(display_name=&quot;Processed Data&quot;, name=&quot;processed_data&quot;, method=&quot;process_data&quot;),</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> Output(display_name=&quot;Debug Info&quot;, name=&quot;debug_info&quot;, method=&quot;provide_debug_info&quot;),</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><br></code></div></div>
<p>By default, components in Langflow that produce multiple outputs only allow one output selection in the visual editor.
The component will have only one output port where the user can select the preferred output type.</p>
<p>This behavior is controlled by the <code>group_outputs</code> parameter:</p>
<ul>
<li class="">
<p><strong><code>group_outputs=False</code> (default)</strong>: When a component has more than one output and <code>group_outputs</code> is <code>false</code> or not set, the outputs are grouped in the visual editor, and the user must select one.</p>
<p>Use this option when the component is expected to return only one type of output when used in a flow.</p>
</li>
<li class="">
<p><strong><code>group_outputs=True</code></strong>: All outputs are available simultaneously in the visual editor. The component has one output port for each output, and the user can connect zero or more outputs to other components.</p>
<p>Use this option when the component is expected to return multiple values that are used in parallel by downstream components or processes.</p>
</li>
</ul>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">False or not set</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">True</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><p>In this example, the visual editor provides a single output port, and the user can select one of the outputs.
Since <code>group_outputs=False</code> is the default behavior, it doesn&#x27;t need to be explicitly set in the component, as shown in this example.</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span>outputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;structured_output&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;Structured Output&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> method=&quot;build_structured_output&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;dataframe_output&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;DataFrame Output&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> method=&quot;build_structured_dataframe&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->12</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><br></code></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>In this example, all outputs are available simultaneously in the visual editor.</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span>outputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;true_result&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;True&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> method=&quot;true_response&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> group_outputs=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;false_result&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;False&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> method=&quot;false_response&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> group_outputs=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><br></code></div></div></div></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="tool-mode">Tool mode<a href="#tool-mode" class="hash-link" aria-label="Direct link to Tool mode" title="Direct link to Tool mode" translate="no"></a></h3>
<p>Components that support <strong>Tool Mode</strong> can be used as standalone components (when <em>not</em> in <strong>Tool Mode</strong>) or as tools for other components with a <strong>Tools</strong> input, such as <strong>Agent</strong> components.</p>
<p>You can allow a custom component to support <strong>Tool Mode</strong> by setting <code>tool_mode=True</code>:</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>inputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> MessageTextInput(</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;message&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;Mensage&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> info=&quot;Enter the message that will be processed directly by the tool&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> tool_mode=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>]</span></div></div><br></code></div></div>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="typed-annotations">Typed annotations<a href="#typed-annotations" class="hash-link" aria-label="Direct link to Typed annotations" title="Direct link to Typed annotations" translate="no"></a></h2>
<p>In Langflow, typed annotations allow Langflow to visually guide users and maintain flow consistency.
Always annotate your output methods with return types like <code>-&gt; Data</code>, <code>-&gt; Message</code>, or <code>-&gt; DataFrame</code> to enable proper visual editor color-coding and validation.
Use <code>Data</code>, <code>Message</code>, or <code>DataFrame</code> wrappers instead of returning plain structures for better consistency. Stay consistent with types across your components to make flows predictable and easier to build.</p>
<p>Typed annotations provide color-coding where outputs like <code>-&gt; Data</code> or <code>-&gt; Message</code> get distinct colors, automatic validation that blocks incompatible connections, and improved readability for users to quickly understand data flow between components.</p>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="common-return-types">Common return types<a href="#common-return-types" class="hash-link" aria-label="Direct link to Common return types" title="Direct link to Common return types" translate="no"></a></h3>
<div class="theme-tabs-container tabs-container tabList__CuJ"><ul role="tablist" aria-orientation="horizontal" class="tabs"><li role="tab" tabindex="0" aria-selected="true" class="tabs__item tabItem_LNqP tabs__item--active">Message</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Data</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">DataFrame</li><li role="tab" tabindex="-1" aria-selected="false" class="tabs__item tabItem_LNqP">Primitive Types</li></ul><div class="margin-top--md"><div role="tabpanel" class="tabItem_Ymn6"><p>For chat-style outputs. Connects to any of several <code>Message</code>-compatible inputs.</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def produce_message(self) -&gt; Message:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return Message(text=&quot;Hello! from typed method!&quot;, sender=&quot;System&quot;)</span></div></div><br></code></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>For structured data like dicts or partial texts. Connects only to <code>DataInput</code> (ports that accept <code>Data</code>).</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def get_processed_data(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> processed = {&quot;key1&quot;: &quot;value1&quot;, &quot;key2&quot;: 123}</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return Data(data=processed)</span></div></div><br></code></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>For tabular data. Connects only to <code>DataFrameInput</code> (ports that accept <code>DataFrame</code>).</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def build_df(self) -&gt; DataFrame:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> pdf = pd.DataFrame({&quot;A&quot;: [1, 2], &quot;B&quot;: [3, 4]})</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return DataFrame(pdf)</span></div></div><br></code></div></div></div><div role="tabpanel" class="tabItem_Ymn6" hidden=""><p>Returning primitives is allowed, but wrapping in <code>Data</code> or <code>Message</code> is recommended for better consistency in the visual editor.</p><div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def compute_sum(self) -&gt; int:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return sum(self.numbers)</span></div></div><br></code></div></div></div></div></div>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="enable-dynamic-fields">Enable dynamic fields<a href="#enable-dynamic-fields" class="hash-link" aria-label="Direct link to Enable dynamic fields" title="Direct link to Enable dynamic fields" translate="no"></a></h2>
<p>In <strong>Langflow</strong>, dynamic fields allow inputs to change or appear based on user interactions. You can make an input dynamic by setting <code>dynamic=True</code>. Optionally, setting <code>real_time_refresh=True</code> triggers the <code>update_build_config</code> method to adjust the input&#x27;s visibility or properties in real time, creating a contextual visual editor experience that only exposes relevant fields based on the user&#x27;s choices.</p>
<p>In this example, the operator field triggers updates with <code>real_time_refresh=True</code>.
The <code>regex_pattern</code> field is initially hidden and controlled with <code>dynamic=True</code>.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span>from lfx.custom import Component</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span>from lfx.io import DropdownInput, StrInput</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span>class RegexRouter(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> display_name = &quot;Regex Router&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> description = &quot;Demonstrates dynamic fields for regex input.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> inputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> DropdownInput(</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;operator&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;Operator&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> options=[&quot;equals&quot;, &quot;contains&quot;, &quot;regex&quot;],</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> value=&quot;equals&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> real_time_refresh=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> StrInput(</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;regex_pattern&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;Regex Pattern&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> info=&quot;Used if operator=&#x27;regex&#x27;&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> dynamic=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> show=False,</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->23</span><div style="display:inline-block;margin-left:16px"><span> ]</span></div></div><br></code></div></div>
<h3 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="show-or-hide-fields-based-on-user-selections">Show or hide fields based on user selections<a href="#show-or-hide-fields-based-on-user-selections" class="hash-link" aria-label="Direct link to Show or hide fields based on user selections" title="Direct link to Show or hide fields based on user selections" translate="no"></a></h3>
<p>When a user changes a field with <code>real_time_refresh=True</code>, Langflow calls your <code>update_build_config</code> method.</p>
<p>This method lets you show, hide, or modify other fields based on what the user selected.</p>
<p>This example shows the <code>regex_pattern</code> field only when the user selects &quot;regex&quot; from the operator dropdown.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None) -&gt; dict:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> if field_name == &quot;operator&quot;:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> if field_value == &quot;regex&quot;:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;regex_pattern&quot;][&quot;show&quot;] = True</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> else:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;regex_pattern&quot;][&quot;show&quot;] = False</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return build_config</span></div></div><br></code></div></div>
<p>You can modify additional field properties in <code>update_build_config</code> other than just <code>show</code> and <code>hide</code>.</p>
<ul>
<li class="">
<p><strong><code>required</code></strong>: Make fields required or optional dynamically</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>if field_value == &quot;regex&quot;:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;regex_pattern&quot;][&quot;required&quot;] = True</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>else:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;regex_pattern&quot;][&quot;required&quot;] = False</span></div></div><br></code></div></div>
</li>
<li class="">
<p><strong><code>advanced</code></strong>: Move fields to the &quot;Advanced&quot; section</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>if field_value == &quot;experimental&quot;:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;regex_pattern&quot;][&quot;advanced&quot;] = False # Show in main section</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>else:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;regex_pattern&quot;][&quot;advanced&quot;] = True # Hide in advanced</span></div></div><br></code></div></div>
</li>
<li class="">
<p><strong><code>options</code></strong>: Change dropdown options based on other selections</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>if field_value == &quot;regex&quot;:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;operator&quot;][&quot;options&quot;] = [&quot;regex&quot;, &quot;contains&quot;, &quot;starts_with&quot;]</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>else:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> build_config[&quot;operator&quot;][&quot;options&quot;] = [&quot;equals&quot;, &quot;contains&quot;, &quot;not_equals&quot;]</span></div></div><br></code></div></div>
</li>
</ul>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="error-handling-and-logging">Error handling and logging<a href="#error-handling-and-logging" class="hash-link" aria-label="Direct link to Error handling and logging" title="Direct link to Error handling and logging" translate="no"></a></h2>
<p>You can raise standard Python exceptions such as <code>ValueError</code> or specialized exceptions like <code>ToolException</code> when validation fails. Langflow automatically catches these and displays appropriate error messages in the visual editor, helping users quickly identify what went wrong.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def compute_result(self) -&gt; str:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> if not self.user_input:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> raise ValueError(&quot;No input provided.&quot;)</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> # ...</span></div></div><br></code></div></div>
<p>Alternatively, instead of stopping a flow abruptly, you can return a <code>Data</code> object containing an <code>&quot;error&quot;</code> field. This approach allows the flow to continue operating and enables downstream components to detect and handle the error gracefully.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def run_model(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> try:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> # ...</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> except Exception as e:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return Data(data={&quot;error&quot;: str(e)})</span></div></div><br></code></div></div>
<p>Langflow provides several tools to help you debug and manage component execution. You can use <code>self.status</code> to display short messages about execution results directly in the visual editor, making troubleshooting easier for users.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def parse_data(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span># ...</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>self.status = f&quot;Parsed {len(rows)} rows successfully.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>return Data(data={&quot;rows&quot;: rows})</span></div></div><br></code></div></div>
<p>You can halt individual output paths when certain conditions fail using <code>self.stop()</code>, without stopping other outputs from the same component.</p>
<p>This example stops the output if the user input is empty, preventing the component from processing invalid data.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def some_output(self) -&gt; Data:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>if not self.user_input or len(self.user_input.strip()) == 0:</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> self.stop(&quot;some_output&quot;)</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> return Data(data={&quot;error&quot;: &quot;Empty input provided&quot;})</span></div></div><br></code></div></div>
<p>You can log key execution details inside components using <code>self.log()</code>. These logs are stored as structured data and displayed in the &quot;Logs&quot; or &quot;Events&quot; section of the component&#x27;s detail view, and can be accessed later through the <strong>Logs</strong> button in the visual editor or exported files.</p>
<p>Component logs are distinct from Langflow&#x27;s main application logging system. <code>self.log()</code> creates component-specific logs that appear in the UI, while Langflow&#x27;s main logging system uses <a href="https://www.structlog.org" target="_blank" rel="noopener noreferrer" class="">structlog</a> for application-level logging that outputs to <code>langflow.log</code> files. For more information, see <a class="" href="/logging">Logs</a>.</p>
<p>This example logs a message when the component starts processing a file.</p>
<div class="ch-codeblock not-prose" data-ch-theme="github-dark"><div class="ch-code-wrapper ch-code" data-ch-measured="false"><code class="ch-code-scroll-parent"><br><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>def process_file(self, file_path: str):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span>self.log(f&quot;Processing file {file_path}&quot;)</span></div></div><br></code></div></div>
<h2 class="anchor anchorTargetHideOnScrollNavbar_vjPI" id="contribute-custom-components-to-langflow">Contribute custom components to Langflow<a href="#contribute-custom-components-to-langflow" class="hash-link" aria-label="Direct link to Contribute custom components to Langflow" title="Direct link to Contribute custom components to Langflow" translate="no"></a></h2>
<p>To contribute your custom component to the Langflow project, see <a class="" href="/contributing-components">Contribute components</a>.</p></div></article><nav class="docusaurus-mt-lg pagination-nav" aria-label="Docs pages"><a class="pagination-nav__link pagination-nav__link--prev" href="/bundles-xai"><div class="pagination-nav__sublabel">Previous</div><div class="pagination-nav__label">xAI</div></a><a class="pagination-nav__link pagination-nav__link--next" href="/api-reference-api-examples"><div class="pagination-nav__sublabel">Next</div><div class="pagination-nav__label">Get started with the Langflow API</div></a></nav></div></div><div class="col col--3"><div class="tableOfContents_bqdL thin-scrollbar theme-doc-toc-desktop"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#quickstart" class="table-of-contents__link toc-highlight">Custom component quickstart</a><ul><li><a href="#create-a-python-file" class="table-of-contents__link toc-highlight">Create a Python file</a></li><li><a href="#custom-component-path" class="table-of-contents__link toc-highlight">Save the custom component</a></li><li><a href="#create-the-__init__py-file" class="table-of-contents__link toc-highlight">Create the <code>__init__.py</code> file</a></li><li><a href="#load-your-component" class="table-of-contents__link toc-highlight">Load your component</a></li><li><a href="#docker-deployment" class="table-of-contents__link toc-highlight">Docker deployment</a></li></ul></li><li><a href="#how-components-execute" class="table-of-contents__link toc-highlight">How components execute</a></li><li><a href="#inputs-and-outputs" class="table-of-contents__link toc-highlight">Inputs and outputs</a><ul><li><a href="#inputs" class="table-of-contents__link toc-highlight">Inputs</a></li><li><a href="#outputs" class="table-of-contents__link toc-highlight">Outputs</a></li><li><a href="#tool-mode" class="table-of-contents__link toc-highlight">Tool mode</a></li></ul></li><li><a href="#typed-annotations" class="table-of-contents__link toc-highlight">Typed annotations</a><ul><li><a href="#common-return-types" class="table-of-contents__link toc-highlight">Common return types</a></li></ul></li><li><a href="#enable-dynamic-fields" class="table-of-contents__link toc-highlight">Enable dynamic fields</a><ul><li><a href="#show-or-hide-fields-based-on-user-selections" class="table-of-contents__link toc-highlight">Show or hide fields based on user selections</a></li></ul></li><li><a href="#error-handling-and-logging" class="table-of-contents__link toc-highlight">Error handling and logging</a></li><li><a href="#contribute-custom-components-to-langflow" class="table-of-contents__link toc-highlight">Contribute custom components to Langflow</a></li></ul></div></div></div></div></main></div></div></div><footer class="theme-layout-footer footer"><div class="container container-fluid"><div class="row footer__links"><div class="theme-layout-footer-column col footer__col"><div class="footer__title"></div><ul class="footer__items clean-list"><li class="footer__item"><div class="footer-links">
<span>© 2026 Langflow</span>
<span id="preferenceCenterContainer"> ·&nbsp; <a href="#" onclick='return"undefined"!=typeof window&&window.truste&&window.truste.eu&&window.truste.eu.clickListener&&window.truste.eu.clickListener(),!1' style="cursor: pointer;">Manage Privacy Choices</a></span>
</div></li></ul></div></div></div></footer><div style="position:fixed;right:21px;bottom:21px;z-index:100;display:flex;align-items:center;gap:10px;cursor:pointer"><div style="background-color:#f6f6f6;border-radius:50%;width:48px;height:48px;display:flex;align-items:center;justify-content:center;box-shadow:0 2px 4px rgba(0,0,0,0.1)"><img src="/img/langflow-icon-black-transparent.svg" style="width:40px" alt="Search"></div></div></div>
</body>
</html>