Files
langflow/components-custom-components.html
github-merge-queue[bot] d09addf91d deploy: 8881abda0a
2025-10-16 15:19:58 +00:00

383 lines
92 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.8.1">
<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="Custom components extend Langflow&#x27;s functionality through Python classes that inherit from Component. This enables integration of new features, data manipulation, external services, and specialized tools."><meta data-rh="true" property="og:description" content="Custom components extend Langflow&#x27;s functionality through Python classes that inherit from Component. This enables integration of new features, data manipulation, external services, and specialized tools."><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>!function(){var e="analytics",t=window[e]=window[e]||[];if(!t.initialize)if(t.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{t.invoked=!0,t.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","screen","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware","register"],t.factory=function(n){return function(){if(window[e].initialized)return window[e][n].apply(window[e],arguments);var r=Array.prototype.slice.call(arguments);if(["track","screen","alias","group","page","identify"].indexOf(n)>-1){var i=document.querySelector("link[rel='canonical']");r.push({__t:"bpc",c:i&&i.getAttribute("href")||void 0,p:location.pathname,u:location.href,s:location.search,t:document.title,r:document.referrer})}return r.unshift(n),t.push(r),t}};for(var n=0;n<t.methods.length;n++){var r=t.methods[n];t[r]=t.factory(r)}t.load=function(n,r){var i=document.createElement("script");i.type="text/javascript",i.async=!0,i.setAttribute("data-global-segment-analytics-key",e),i.src="https://cdn.segment.com/analytics.js/v1/"+n+"/analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(i,a),t._loadOptions=r},t._writeKey="60AfGDrVxy8nAGJngo3fCYWG4LvhMAlG",t.SNIPPET_VERSION="5.2.0",t.load("60AfGDrVxy8nAGJngo3fCYWG4LvhMAlG"),t.page()}}()</script>
<script>window.__SCROLL_TRACKING_CONFIG__={selectors:[{selector:"h1, h2, h3, h4, h5, h6",eventName:"Docs.langflow.org - Heading Viewed",properties:{element_type:"heading"}},{selector:".ch-codeblock",eventName:"Docs.langflow.org - Codeblock Viewed",properties:{element_type:"code",language:"helper:codeLanguage"}}]}</script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@550;600&amp;display=swap">
<script>!function(){window.semaphore=window.semaphore||[],window.ketch=function(){window.semaphore.push(arguments)};var e=document.createElement("script");e.type="text/javascript",e.src="https://global.ketchcdn.com/web/v3/config/datastax/langflow_org_web/boot.js",e.defer=e.async=!0,document.getElementsByTagName("head")[0].appendChild(e)}()</script>
<script defer="true">!function(){const e=e=>{if(window.gtag&&e.purposes&&"analytics"in e.purposes&&"targeted_advertising"in e.purposes){const n=!0===e.purposes.analytics?"granted":"denied",t=!0===e.purposes.targeted_advertising?"granted":"denied",a={analytics_storage:n,ad_personalization:t,ad_storage:t,ad_user_data:t};window.gtag("consent","update",a)}};window.ketch&&window.ketch("on","consent",e)}()</script><link rel="stylesheet" href="/assets/css/styles.5b49702d.css">
<script src="/assets/js/runtime~main.64c9d228.js" defer="defer"></script>
<script src="/assets/js/main.ab32be25.js" defer="defer"></script>
</head>
<body class="navigation-with-keyboard">
<svg xmlns="http://www.w3.org/2000/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="Docs.langflow.org - Social Clicked" data-platform="github"></a><a href="https://twitter.com/langflow_ai" target="_blank" class="navbar__item navbar__link header-twitter-link" data-event="Docs.langflow.org - Social Clicked" data-platform="x"></a><a href="https://discord.gg/EqksyE2EX9" target="_blank" class="navbar__item navbar__link header-discord-link" data-event="Docs.langflow.org - Social Clicked" data-platform="discord"></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 (Command+K)"><span class="DocSearch-Button-Container"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" 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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/">Get started</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/concepts-overview">Flows</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/agents">Agents</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/mcp-client">Model Context Protocol (MCP)</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/api-keys-and-authentication">Develop</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/deployment-overview">Deploy</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="menu__link menu__link--sublist menu__link--sublist-caret menu__link--active" role="button" aria-expanded="true" href="/concepts-components">Components reference</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">Components overview</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" tabindex="0" href="/components-io">Core components</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" tabindex="0" href="/components-bundle-components">Bundles</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">Create custom Python components</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/api-reference-api-examples">API reference</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/contributing-community">Contribute</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/release-notes">Release notes</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="menu__link menu__link--sublist menu__link--sublist-caret" role="button" aria-expanded="false" href="/troubleshoot">Support</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>Custom components extend Langflow&#x27;s functionality through Python classes that inherit from <code>Component</code>. This enables integration of new features, data manipulation, external services, and specialized tools.</p>
<p>In Langflow&#x27;s node-based environment, each node is a &quot;component&quot; that performs discrete functions. Custom components are Python classes which define:</p>
<ul>
<li><strong>Inputs</strong> — Data or parameters your component requires.</li>
<li><strong>Outputs</strong> — Data your component provides to downstream nodes.</li>
<li><strong>Logic</strong> — How you process inputs to produce outputs.</li>
</ul>
<p>The benefits of creating custom components include unlimited extensibility, reusability, automatic field generation in the visual editor based on inputs, and type-safe connections between nodes.</p>
<p>Create custom components for performing specialized tasks, calling APIs, or adding advanced logic.</p>
<p>Custom components in Langflow are built upon:</p>
<ul>
<li>The Python class that inherits from <code>Component</code>.</li>
<li>Class-level attributes that identify and describe the component.</li>
<li>Input and output lists that determine data flow.</li>
<li>Internal variables for logging and advanced logic.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="class-level-attributes">Class-level attributes<a href="#class-level-attributes" class="hash-link" aria-label="Direct link to Class-level attributes" title="Direct link to Class-level attributes"></a></h2>
<p>Define these attributes to control a custom component&#x27;s appearance and behavior:</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 MyCsvReader(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> display_name = &quot;CSV Reader&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> description = &quot;Reads CSV files&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> icon = &quot;file-text&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> name = &quot;CSVReader&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> documentation = &quot;http://docs.example.com/csv_reader&quot;</span></div></div><br></code></div></div>
<ul>
<li>
<p><code>display_name</code>: A user-friendly label shown in the visual editor.</p>
</li>
<li>
<p><code>description</code>: A brief summary shown in tooltips and printed below the component name when added to a flow.</p>
</li>
<li>
<p><code>icon</code>: A decorative icon from Langflow&#x27;s icon library, printed next to the name.</p>
<p>Langflow uses <a href="https://lucide.dev/icons" target="_blank" rel="noopener noreferrer">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.</p>
</li>
<li>
<p><code>name</code>: A unique internal identifier, typically the same name as the folder containing your component code.</p>
</li>
<li>
<p><code>documentation</code>: An optional link to external documentation, such as API or product documentation.</p>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="structure-of-a-custom-component">Structure of a custom component<a href="#structure-of-a-custom-component" class="hash-link" aria-label="Direct link to Structure of a custom component" title="Direct link to Structure of a custom component"></a></h3>
<p>A Langflow custom component is more than a class with inputs and outputs. It includes an internal structure with optional lifecycle steps, output generation, front-end interaction, and logic organization.</p>
<p>A basic component:</p>
<ul>
<li>Inherits from <code>langflow.custom.Component</code>.</li>
<li>Declares metadata like <code>display_name</code>, <code>description</code>, <code>icon</code>, and more.</li>
<li>Defines <code>inputs</code> and <code>outputs</code> lists.</li>
<li>Implements methods matching output specifications.</li>
</ul>
<p>A minimal custom component skeleton contains the following:</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>from langflow.custom import Component</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span>from langflow.template import Output</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>class MyComponent(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> display_name = &quot;My Component&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> description = &quot;A short summary.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> icon = &quot;sparkles&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> name = &quot;MyComponent&quot;</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> inputs = []</span></div></div><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></span></div></div><div><span class="ch-code-line-number">_<!-- -->14</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">_<!-- -->14</span><div style="display:inline-block;margin-left:16px"><span> return ...</span></div></div><br></code></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="internal-lifecycle-and-execution-flow">Internal Lifecycle and Execution Flow<a href="#internal-lifecycle-and-execution-flow" class="hash-link" aria-label="Direct link to Internal Lifecycle and Execution Flow" title="Direct link to Internal Lifecycle and Execution Flow"></a></h3>
<p>Langflow&#x27;s engine manages:</p>
<ul>
<li><strong>Instantiation</strong>: A component is created and internal structures are initialized.</li>
<li><strong>Assigning Inputs</strong>: Values from the visual editor or connections are assigned to component fields.</li>
<li><strong>Validation and Setup</strong>: Optional hooks like <code>_pre_run_setup</code>.</li>
<li><strong>Outputs Generation</strong>: <code>run()</code> or <code>build_results()</code> triggers output methods.</li>
</ul>
<p><strong>Optional Hooks</strong>:</p>
<ul>
<li><code>initialize_data</code> or <code>_pre_run_setup</code> can run setup logic before the component&#x27;s main execution.</li>
<li><code>__call__</code>, <code>run()</code>, or <code>_run()</code> can be overridden to customize how the component is called or to define custom execution logic.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h3>
<p>Custom component inputs are defined with properties like:</p>
<ul>
<li><code>name</code>, <code>display_name</code></li>
<li>Optional: <code>info</code>, <code>value</code>, <code>advanced</code>, <code>is_list</code>, <code>tool_mode</code>, <code>real_time_refresh</code></li>
</ul>
<p>For example:</p>
<ul>
<li><code>StrInput</code>: simple text input.</li>
<li><code>DropdownInput</code>: selectable options.</li>
<li><code>HandleInput</code>: specialized connections.</li>
</ul>
<p>Custom component <code>Output</code> properties define:</p>
<ul>
<li><code>name</code>, <code>display_name</code>, <code>method</code></li>
<li>Optional: <code>info</code></li>
</ul>
<p>For more information, see <a href="/components-custom-components#custom-component-inputs-and-outputs">Custom component inputs and outputs</a>.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h3>
<p>Each output is linked to a method:</p>
<ul>
<li>The output method name must match the method name.</li>
<li>The method typically returns objects like Message, Data, or DataFrame.</li>
<li>The method can use inputs with <code>self.&lt;input_name&gt;</code>.</li>
</ul>
<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">_<!-- -->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> 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> 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>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h3>
<p>A component can define multiple outputs.
Each output can have a different corresponding method.
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>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="output-grouping-behavior-with-group_outputs">Output Grouping Behavior with <code>group_outputs</code><a href="#output-grouping-behavior-with-group_outputs" class="hash-link" aria-label="Direct link to output-grouping-behavior-with-group_outputs" title="Direct link to output-grouping-behavior-with-group_outputs"></a></h4>
<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>
<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>
<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="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><ol start="2">
<li><code>group_outputs=True</code></li>
</ol><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 anchorWithHideOnScrollNavbar_WYt5" id="common-internal-patterns">Common internal patterns<a href="#common-internal-patterns" class="hash-link" aria-label="Direct link to Common internal patterns" title="Direct link to Common internal patterns"></a></h3>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="_pre_run_setup"><code>_pre_run_setup()</code><a href="#_pre_run_setup" class="hash-link" aria-label="Direct link to _pre_run_setup" title="Direct link to _pre_run_setup"></a></h4>
<p>To initialize a custom component with counters set:</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 _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>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="override-run-or-_run">Override <code>run</code> or <code>_run</code><a href="#override-run-or-_run" class="hash-link" aria-label="Direct link to override-run-or-_run" title="Direct link to override-run-or-_run"></a></h4>
<p>You can override <code>async def _run(self): ...</code> to define custom execution logic, although the default behavior from the base class usually covers most cases.</p>
<h4 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="store-data-in-selfctx">Store data in <code>self.ctx</code><a href="#store-data-in-selfctx" class="hash-link" aria-label="Direct link to store-data-in-selfctx" title="Direct link to store-data-in-selfctx"></a></h4>
<p>Use <code>self.ctx</code> as a shared storage for data or counters across the component&#x27;s execution flow:</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_method(self):</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> count = self.ctx.get(&quot;my_count&quot;, 0)</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> self.ctx[&quot;my_count&quot;] = count + 1</span></div></div><br></code></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="directory-structure-requirements">Directory structure requirements<a href="#directory-structure-requirements" class="hash-link" aria-label="Direct link to Directory structure requirements" title="Direct link to Directory structure requirements"></a></h2>
<p>By default, Langflow looks for custom components in the <code>/components</code> directory.</p>
<p>If you&#x27;re creating custom components in a different location using the <code>LANGFLOW_COMPONENTS_PATH</code> <a href="/environment-variables">environment variable</a>, components must be organized in a specific directory structure to be properly loaded and displayed in the visual editor:</p>
<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>
<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/ # Required category subfolder that determines menu name</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── __init__.py # Required</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── custom_component.py # Component file</span></div></div><br></code></div></div>
<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 a component to the <strong>Helpers</strong> category, place it in the <code>helpers</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>/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> └── helpers/ # Displayed within the &quot;Helpers&quot; category</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> ├── __init__.py # Required</span></div></div><div><span class="ch-code-line-number">_<!-- -->10</span><div style="display:inline-block;margin-left:16px"><span> └── custom_component.py # Your component</span></div></div><br></code></div></div>
<p>You can have multiple category folders to organize components into different categories:</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> ├── helpers/</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> │ └── helper_component.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> └── tool_component.py</span></div></div><br></code></div></div>
<p>This folder structure is required for Langflow to properly discover and load your custom components. Components placed directly in the base directory aren&#x27;t loaded.</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> └── custom_component.py # Won&#x27;t be loaded - missing category folder!</span></div></div><br></code></div></div>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="custom-component-inputs-and-outputs">Custom component inputs and outputs<a href="#custom-component-inputs-and-outputs" class="hash-link" aria-label="Direct link to Custom component inputs and outputs" title="Direct link to Custom component inputs and outputs"></a></h2>
<p>Inputs and outputs 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 anchorWithHideOnScrollNavbar_WYt5" id="inputs">Inputs<a href="#inputs" class="hash-link" aria-label="Direct link to Inputs" title="Direct link to Inputs"></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 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>langflow.io</code> (such as <code>StrInput</code>, <code>DataInput</code>, or <code>MessageTextInput</code>). The most common constructor parameters are:</p>
<ul>
<li><strong><code>name</code></strong>: The internal variable name, accessed with <code>self.&lt;name&gt;</code>.</li>
<li><strong><code>display_name</code></strong>: The label shown to users in the visual editor.</li>
<li><strong><code>info</code></strong> <em>(optional)</em>: A tooltip or short description.</li>
<li><strong><code>value</code></strong> <em>(optional)</em>: The default value.</li>
<li><strong><code>advanced</code></strong> <em>(optional)</em>: If <code>true</code>, moves the field into the &quot;Advanced&quot; section.</li>
<li><strong><code>required</code></strong> <em>(optional)</em>: If <code>true</code>, forces the user to provide a value.</li>
<li><strong><code>is_list</code></strong> <em>(optional)</em>: If <code>true</code>, allows multiple values.</li>
<li><strong><code>input_types</code></strong> <em>(optional)</em>: Restricts allowed connection types (e.g., <code>[&quot;Data&quot;]</code>, <code>[&quot;LanguageModel&quot;]</code>).</li>
</ul>
<p>Here are the most commonly used input classes and their typical usage.</p>
<p><strong>Text Inputs</strong>: For simple text entries.</p>
<ul>
<li><strong><code>StrInput</code></strong> creates a single-line text field.</li>
<li><strong><code>MultilineInput</code></strong> creates a multi-line text area.</li>
</ul>
<p><strong>Numeric and Boolean Inputs</strong>: Ensures users can only enter valid numeric or Boolean data.</p>
<ul>
<li><strong><code>BoolInput</code></strong>, <strong><code>IntInput</code></strong>, and <strong><code>FloatInput</code></strong> provide fields for Boolean, integer, and float values, ensuring type consistency.</li>
</ul>
<p><strong>Dropdowns</strong>: For selecting from predefined options, useful for modes or levels.</p>
<ul>
<li><strong><code>DropdownInput</code></strong></li>
</ul>
<p><strong>Secrets</strong>: A specialized input for sensitive data, ensuring input is hidden in the visual editor.</p>
<ul>
<li><strong><code>SecretStrInput</code></strong> for API keys and passwords.</li>
</ul>
<p><strong>Specialized Data Inputs</strong>: Ensures type-checking and color-coded connections in the visual editor.</p>
<ul>
<li><strong><code>DataInput</code></strong> expects a <code>Data</code> object (typically with <code>.data</code> and optional <code>.text</code>).</li>
<li><strong><code>MessageInput</code></strong> expects a <code>Message</code> object, used in chat or agent flows.</li>
<li><strong><code>MessageTextInput</code></strong> simplifies access to the <code>.text</code> field of a <code>Message</code>.</li>
</ul>
<p><strong>Handle-Based Inputs</strong>: Used to connect outputs of specific types, ensuring correct pipeline connections.</p>
<ul>
<li><strong><code>HandleInput</code></strong></li>
</ul>
<p><strong>File Uploads</strong>: Allows users to upload files directly through the visual editor or receive file paths from other components.</p>
<ul>
<li><strong><code>FileInput</code></strong></li>
</ul>
<p><strong>Lists</strong>: Set <code>is_list=True</code> to accept multiple values, ideal for batch or grouped operations.</p>
<p>This example defines 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 langflow.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>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="outputs">Outputs<a href="#outputs" class="hash-link" aria-label="Direct link to Outputs" title="Direct link to Outputs"></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>langflow.io</code>, with common parameters:</p>
<ul>
<li><strong><code>name</code></strong>: The internal variable name.</li>
<li><strong><code>display_name</code></strong>: The label shown in the visual editor.</li>
<li><strong><code>method</code></strong>: The name of the method called to produce the output.</li>
<li><strong><code>info</code></strong> <em>(optional)</em>: Help text shown on hover.</li>
</ul>
<p>The method must exist in the class, and it is recommended to annotate its return type for better type checking.
You can also set a <code>self.status</code> message inside the method to show progress or logs.</p>
<p><strong>Common Return Types</strong>:</p>
<ul>
<li><strong><code>Message</code></strong>: Structured chat messages.</li>
<li><strong><code>Data</code></strong>: Flexible object with <code>.data</code> and optional <code>.text</code>.</li>
<li><strong><code>DataFrame</code></strong>: Pandas-based tables (<code>langflow.schema.DataFrame</code>).</li>
<li><strong>Primitive types</strong>: <code>str</code>, <code>int</code>, <code>bool</code> (not recommended if you need type/color consistency).</li>
</ul>
<p>In this example, the <code>DataToDataFrame</code> component defines its output using the outputs list. The <code>df_out</code> output is linked to the <code>build_df</code> method, so when connected to another component (node), Langflow calls this method and passes its returned <code>DataFrame</code> to the next node. This demonstrates how each output maps to a method that generates the actual output 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">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span>from langflow.custom import Component</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span>from langflow.io import DataInput, Output</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span>from langflow.schema import Data, DataFrame</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span>class DataToDataFrame(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> display_name = &quot;Data to DataFrame&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> description = &quot;Convert multiple Data objects into a DataFrame&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> icon = &quot;table&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> name = &quot;DataToDataFrame&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> inputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> DataInput(</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;items&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> display_name=&quot;Data Items&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> info=&quot;List of Data objects to convert&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> is_list=True</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> )</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> ]</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> outputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> Output(</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</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">_<!-- -->37</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">_<!-- -->37</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">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> )</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> ]</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->37</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">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> rows = []</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> for item in self.items:</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> row_dict = item.data.copy() if item.data else {}</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> row_dict[&quot;text&quot;] = item.get_text() or &quot;&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> rows.append(row_dict)</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> df = DataFrame(rows)</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> self.status = f&quot;Built DataFrame with {len(rows)} rows.&quot;</span></div></div><div><span class="ch-code-line-number">_<!-- -->37</span><div style="display:inline-block;margin-left:16px"><span> return df</span></div></div><br></code></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></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>
<p>Langflow currently supports the following input types for <strong>Tool Mode</strong>:</p>
<ul>
<li><code>DataInput</code></li>
<li><code>DataFrameInput</code></li>
<li><code>PromptInput</code></li>
<li><code>MessageTextInput</code></li>
<li><code>MultilineInput</code></li>
<li><code>DropdownInput</code></li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h2>
<p>In Langflow, <strong>typed annotations</strong> allow Langflow to visually guide users and maintain flow consistency.</p>
<p>Typed annotations provide:</p>
<ul>
<li><strong>Color-coding</strong>: Outputs like <code>-&gt; Data</code> or <code>-&gt; Message</code> get distinct colors.</li>
<li><strong>Validation</strong>: Langflow blocks incompatible connections automatically.</li>
<li><strong>Readability</strong>: Developers can quickly understand data flow.</li>
<li><strong>Development tools</strong>: Better code suggestions and error checking in your code editor.</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h3>
<ul>
<li>
<p><code>Message</code>: 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>
</li>
<li>
<p><code>Data</code>: 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>
</li>
<li>
<p><code>DataFrame</code>: 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>
</li>
<li>
<p>Primitive Types (<code>str</code>, <code>int</code>, <code>bool</code>): 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>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="tips-for-typed-annotations">Tips for typed annotations<a href="#tips-for-typed-annotations" class="hash-link" aria-label="Direct link to Tips for typed annotations" title="Direct link to Tips for typed annotations"></a></h3>
<p>When using typed annotations, consider the following best practices:</p>
<ul>
<li><strong>Always Annotate Outputs</strong>: Specify 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.</li>
<li><strong>Wrap Raw Data</strong>: Use <code>Data</code>, <code>Message</code>, or <code>DataFrame</code> wrappers instead of returning plain structures.</li>
<li><strong>Use Primitives Carefully</strong>: Direct <code>str</code> or <code>int</code> returns are fine for simple flows, but wrapping improves flexibility.</li>
<li><strong>Annotate Helpers Too</strong>: Even if internal, typing improves maintainability and clarity.</li>
<li><strong>Handle Edge Cases</strong>: Prefer returning structured <code>Data</code> with error fields when needed.</li>
<li><strong>Stay Consistent</strong>: Use the same types across your components to make flows predictable and easier to build.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></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">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span>from langflow.io import DropdownInput, StrInput</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span>class RegexRouter(Component):</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</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">_<!-- -->22</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">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span></span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> inputs = [</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> DropdownInput(</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> name=&quot;operator&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</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">_<!-- -->22</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">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> value=&quot;equals&quot;,</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> real_time_refresh=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> StrInput(</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</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">_<!-- -->22</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">_<!-- -->22</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">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> dynamic=True,</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> show=False,</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> ),</span></div></div><div><span class="ch-code-line-number">_<!-- -->22</span><div style="display:inline-block;margin-left:16px"><span> ]</span></div></div><br></code></div></div>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="implement-update_build_config">Implement <code>update_build_config</code><a href="#implement-update_build_config" class="hash-link" aria-label="Direct link to implement-update_build_config" title="Direct link to implement-update_build_config"></a></h3>
<p>When a field with <code>real_time_refresh=True</code> is modified, Langflow calls the <code>update_build_config</code> method, passing the updated field name, value, and the component&#x27;s configuration to dynamically adjust the visibility or properties of other fields based on user input.</p>
<p>This example will show or hide the <code>regex_pattern</code> field when the user selects a different operator.</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>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="additional-dynamic-field-controls">Additional Dynamic Field Controls<a href="#additional-dynamic-field-controls" class="hash-link" aria-label="Direct link to Additional Dynamic Field Controls" title="Direct link to Additional Dynamic Field Controls"></a></h3>
<p>You can also modify other properties within <code>update_build_config</code>, such as:</p>
<ul>
<li>
<p><code>required</code>: Set <code>build_config[&quot;some_field&quot;][&quot;required&quot;] = True/False</code></p>
</li>
<li>
<p><code>advanced</code>: Set <code>build_config[&quot;some_field&quot;][&quot;advanced&quot;] = True</code></p>
</li>
<li>
<p><code>options</code>: Modify dynamic dropdown options.</p>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="tips-for-managing-dynamic-fields">Tips for Managing Dynamic Fields<a href="#tips-for-managing-dynamic-fields" class="hash-link" aria-label="Direct link to Tips for Managing Dynamic Fields" title="Direct link to Tips for Managing Dynamic Fields"></a></h3>
<p>When working with dynamic fields, consider the following best practices to ensure a smooth user experience:</p>
<ul>
<li><strong>Minimize field changes</strong>: Hide only fields that are truly irrelevant to avoid confusing users.</li>
<li><strong>Test behavior</strong>: Ensure that adding or removing fields doesn&#x27;t accidentally erase user input.</li>
<li><strong>Preserve data</strong>: Use <code>build_config[&quot;some_field&quot;][&quot;show&quot;] = False</code> to hide fields without losing their values.</li>
<li><strong>Clarify logic</strong>: Add <code>info</code> notes to explain why fields appear or disappear based on conditions.</li>
<li><strong>Keep it manageable</strong>: If the dynamic logic becomes too complex, consider breaking it into smaller components, unless it serves a clear purpose in a single node.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h2>
<p>In Langflow, robust error handling ensures that your components behave predictably, even when unexpected situations occur, such as invalid inputs, external API failures, or internal logic errors.</p>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="error-handling-techniques">Error handling techniques<a href="#error-handling-techniques" class="hash-link" aria-label="Direct link to Error handling techniques" title="Direct link to Error handling techniques"></a></h3>
<ul>
<li>
<p><strong>Raise Exceptions</strong>: If a critical error occurs, you can raise standard Python exceptions such as <code>ValueError</code>, or specialized exceptions like <code>ToolException</code>. Langflow will automatically catch these and display 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>
</li>
<li>
<p><strong>Return Structured Error Data</strong>: Instead of stopping a flow abruptly, you can return a Data object containing an &quot;error&quot; 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>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="improve-debugging-and-flow-management">Improve debugging and flow management<a href="#improve-debugging-and-flow-management" class="hash-link" aria-label="Direct link to Improve debugging and flow management" title="Direct link to Improve debugging and flow management"></a></h3>
<ul>
<li>
<p><strong>Use <code>self.status</code></strong>: Each component has a status field where you can store short messages about the execution result—such as success summaries, partial progress, or error notifications. These appear 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>
</li>
<li>
<p><strong>Stop specific outputs with <code>self.stop(...)</code></strong>: You can halt individual output paths when certain conditions fail, without affecting the entire component. This is especially useful when working with components that have multiple output branches.</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 &lt;some condition&gt;:</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;) # Tells Langflow no data flows</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;Condition not met&quot;})</span></div></div><br></code></div></div>
</li>
<li>
<p><strong>Log events</strong>: You can log key execution details inside components. Logs are 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 flow&#x27;s debug panel or exported files, providing a clear trace of the component&#x27;s behavior for easier debugging.</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><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>
</li>
</ul>
<h3 class="anchor anchorWithHideOnScrollNavbar_WYt5" id="tips-for-error-handling-and-logging">Tips for error handling and logging<a href="#tips-for-error-handling-and-logging" class="hash-link" aria-label="Direct link to Tips for error handling and logging" title="Direct link to Tips for error handling and logging"></a></h3>
<p>To build more reliable components, consider the following best practices:</p>
<ul>
<li><strong>Validate inputs early</strong>: Catch missing or invalid inputs at the start to prevent broken logic.</li>
<li><strong>Summarize with <code>self.status</code></strong>: Use short success or error summaries to help users understand results quickly.</li>
<li><strong>Keep logs concise</strong>: Focus on meaningful messages to avoid cluttering the visual editor.</li>
<li><strong>Return structured errors</strong>: When appropriate, return <code>Data(data={&quot;error&quot;: ...})</code> instead of raising exceptions to allow downstream handling.</li>
<li><strong>Stop outputs selectively</strong>: Only halt specific outputs with <code>self.stop(...)</code> if necessary, to preserve correct flow behavior elsewhere.</li>
</ul>
<h2 class="anchor anchorWithHideOnScrollNavbar_WYt5" 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"></a></h2>
<p>See <a href="/contributing-components">How to Contribute</a> to contribute your custom component to Langflow.</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="#class-level-attributes" class="table-of-contents__link toc-highlight">Class-level attributes</a><ul><li><a href="#structure-of-a-custom-component" class="table-of-contents__link toc-highlight">Structure of a custom component</a></li><li><a href="#internal-lifecycle-and-execution-flow" class="table-of-contents__link toc-highlight">Internal Lifecycle and Execution Flow</a></li><li><a href="#inputs-and-outputs" class="table-of-contents__link toc-highlight">Inputs and outputs</a></li><li><a href="#associated-methods" class="table-of-contents__link toc-highlight">Associated Methods</a></li><li><a href="#components-with-multiple-outputs" class="table-of-contents__link toc-highlight">Components with multiple outputs</a></li><li><a href="#common-internal-patterns" class="table-of-contents__link toc-highlight">Common internal patterns</a></li></ul></li><li><a href="#directory-structure-requirements" class="table-of-contents__link toc-highlight">Directory structure requirements</a></li><li><a href="#custom-component-inputs-and-outputs" class="table-of-contents__link toc-highlight">Custom component 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><li><a href="#tips-for-typed-annotations" class="table-of-contents__link toc-highlight">Tips for typed annotations</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="#implement-update_build_config" class="table-of-contents__link toc-highlight">Implement <code>update_build_config</code></a></li><li><a href="#additional-dynamic-field-controls" class="table-of-contents__link toc-highlight">Additional Dynamic Field Controls</a></li><li><a href="#tips-for-managing-dynamic-fields" class="table-of-contents__link toc-highlight">Tips for Managing Dynamic Fields</a></li></ul></li><li><a href="#error-handling-and-logging" class="table-of-contents__link toc-highlight">Error handling and logging</a><ul><li><a href="#error-handling-techniques" class="table-of-contents__link toc-highlight">Error handling techniques</a></li><li><a href="#improve-debugging-and-flow-management" class="table-of-contents__link toc-highlight">Improve debugging and flow management</a></li><li><a href="#tips-for-error-handling-and-logging" class="table-of-contents__link toc-highlight">Tips for error handling and logging</a></li></ul></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>© 2025 Langflow</span>
<span id="preferenceCenterContainer"> ·&nbsp; <a href="https://langflow.org/preferences">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>