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