diff --git a/404.html b/404.html index d647a4b565..8524618bba 100644 --- a/404.html +++ b/404.html @@ -24,7 +24,7 @@ - +
diff --git a/agent-tutorial.html b/agent-tutorial.html index 911b5a530f..5e4f68a930 100644 --- a/agent-tutorial.html +++ b/agent-tutorial.html @@ -24,7 +24,7 @@ - + diff --git a/agents-tools.html b/agents-tools.html index 1667e07407..5d47db59e3 100644 --- a/agents-tools.html +++ b/agents-tools.html @@ -24,7 +24,7 @@ - + diff --git a/agents.html b/agents.html index c5040e6ef0..e19043dc27 100644 --- a/agents.html +++ b/agents.html @@ -24,7 +24,7 @@ - + diff --git a/api-build.html b/api-build.html index 9ffba4a092..eb7707ca56 100644 --- a/api-build.html +++ b/api-build.html @@ -24,7 +24,7 @@ - + diff --git a/api-files.html b/api-files.html index 81f0de5399..ab161a2f38 100644 --- a/api-files.html +++ b/api-files.html @@ -24,7 +24,7 @@ - + diff --git a/api-flows-run.html b/api-flows-run.html index 20df66cf83..a28496eebe 100644 --- a/api-flows-run.html +++ b/api-flows-run.html @@ -24,7 +24,7 @@ - + diff --git a/api-flows.html b/api-flows.html index 117f7e4489..1487b1fb2f 100644 --- a/api-flows.html +++ b/api-flows.html @@ -24,7 +24,7 @@ - + diff --git a/api-keys-and-authentication.html b/api-keys-and-authentication.html index 73fa8b0727..62298bb72d 100644 --- a/api-keys-and-authentication.html +++ b/api-keys-and-authentication.html @@ -24,7 +24,7 @@ - + diff --git a/api-logs.html b/api-logs.html index e15a144ded..5f41586efc 100644 --- a/api-logs.html +++ b/api-logs.html @@ -24,7 +24,7 @@ - + diff --git a/api-monitor.html b/api-monitor.html index f0ade768ff..fb1f9319ea 100644 --- a/api-monitor.html +++ b/api-monitor.html @@ -24,7 +24,7 @@ - + diff --git a/api-openai-responses.html b/api-openai-responses.html index 545310a295..4cbcb5f752 100644 --- a/api-openai-responses.html +++ b/api-openai-responses.html @@ -24,7 +24,7 @@ - + diff --git a/api-projects.html b/api-projects.html index 6e5a38ba36..7efb9074ef 100644 --- a/api-projects.html +++ b/api-projects.html @@ -24,7 +24,7 @@ - + diff --git a/api-reference-api-examples.html b/api-reference-api-examples.html index 6151fad25d..4ca6f1e8e6 100644 --- a/api-reference-api-examples.html +++ b/api-reference-api-examples.html @@ -24,7 +24,7 @@ - + diff --git a/api-request.html b/api-request.html index f3c4443554..e70d2635e9 100644 --- a/api-request.html +++ b/api-request.html @@ -24,7 +24,7 @@ - + diff --git a/api-users.html b/api-users.html index bc209b9e4c..2c7e510256 100644 --- a/api-users.html +++ b/api-users.html @@ -24,7 +24,7 @@ - + diff --git a/api.html b/api.html index 7bdbd90bc2..a6d75d895b 100644 --- a/api.html +++ b/api.html @@ -24,7 +24,7 @@ - + diff --git a/api/openapi.json.html b/api/openapi.json.html index 83ff4fa232..e30a43f238 100644 --- a/api/openapi.json.html +++ b/api/openapi.json.html @@ -24,7 +24,7 @@ - + diff --git a/api/openapi.yaml.html b/api/openapi.yaml.html index 6b40cedc35..68d9c5c4d4 100644 --- a/api/openapi.yaml.html +++ b/api/openapi.yaml.html @@ -24,7 +24,7 @@ - + diff --git a/assets/js/20177945.0768ab3a.js b/assets/js/20177945.0768ab3a.js deleted file mode 100644 index be574b3575..0000000000 --- a/assets/js/20177945.0768ab3a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(globalThis.webpackChunklangflow_docs=globalThis.webpackChunklangflow_docs||[]).push([[8392],{11470:(o,t,e)=>{e.d(t,{A:()=>k});var n=e(96540),s=e(18215),r=e(17559),l=e(23104),c=e(56347),p=e(205),a=e(57485),i=e(31682),d=e(70679);function y(o){return n.Children.toArray(o).filter(o=>"\n"!==o).map(o=>{if(!o||(0,n.isValidElement)(o)&&function(o){const{props:t}=o;return!!t&&"object"==typeof t&&"value"in t}(o))return o;throw new Error(`Docusaurus error: Bad__init__.py file",id:"create-the-__init__py-file",level:3},{value:"Load your component",id:"load-your-component",level:3},{value:"Docker deployment",id:"docker-deployment",level:3},{value:"How components execute",id:"how-components-execute",level:2},{value:"Inputs and outputs",id:"inputs-and-outputs",level:2},{value:"Inputs",id:"inputs",level:3},{value:"Outputs",id:"outputs",level:3},{value:"Associated methods",id:"associated-methods",level:4},{value:"Components with multiple outputs",id:"components-with-multiple-outputs",level:4},{value:"Tool mode",id:"tool-mode",level:3},{value:"Typed annotations",id:"typed-annotations",level:2},{value:"Common return types",id:"common-return-types",level:3},{value:"Enable dynamic fields",id:"enable-dynamic-fields",level:2},{value:"Show or hide fields based on user selections",id:"show-or-hide-fields-based-on-user-selections",level:3},{value:"Error handling and logging",id:"error-handling-and-logging",level:2},{value:"Contribute custom components to Langflow",id:"contribute-custom-components-to-langflow",level:2}];function m(o){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...o.components},{Details:e}=t;return h||f("CH",!1),h.Code||f("CH.Code",!0),e||f("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("style",{dangerouslySetInnerHTML:{__html:'[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; }'}}),"\n","\n",(0,s.jsx)(t.p,{children:"Create your own custom components to add any functionality you need to Langflow, from API integrations to data processing."}),"\n",(0,s.jsx)(t.p,{children:'In Langflow\'s node-based environment, each node is a "component" that performs discrete functions.\nCustom components in Langflow are built upon:'}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["The Python class that inherits from ",(0,s.jsx)(t.code,{children:"Component"}),"."]}),"\n",(0,s.jsx)(t.li,{children:"Class-level attributes that identify and describe the component."}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.a,{href:"#inputs-and-outputs",children:"Input and output lists"})," that determine data flow."]}),"\n",(0,s.jsx)(t.li,{children:"Methods that define the component's behavior and logic."}),"\n",(0,s.jsxs)(t.li,{children:["Internal variables for ",(0,s.jsx)(t.a,{href:"#error-handling-and-logging",children:"Error handling and logging"})]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["Use the ",(0,s.jsx)(t.a,{href:"#quickstart",children:"Custom component quickstart"})," to add an example component to Langflow, and then use the reference guide that follows for more advanced component customization."]}),"\n",(0,s.jsx)(t.h2,{id:"quickstart",children:"Custom component quickstart"}),"\n",(0,s.jsxs)(t.p,{children:["Create a custom ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component by creating a Python file, saving it in the correct folder, including an ",(0,s.jsx)(t.code,{children:"__init__.py"})," file, and loading it into Langflow."]}),"\n",(0,s.jsx)(t.h3,{id:"create-a-python-file",children:"Create a Python file"}),"\n",(0,s.jsx)(i.Ay,{}),"\n",(0,s.jsx)(t.h3,{id:"custom-component-path",children:"Save the custom component"}),"\n",(0,s.jsx)(t.p,{children:"Save the custom component in the Langflow directory where the UI will discover and load it."}),"\n",(0,s.jsxs)(t.p,{children:["By default, Langflow looks for custom components in the ",(0,s.jsx)(t.code,{children:"src/lfx/src/lfx/components"})," directory."]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:"Components must be placed inside category folders, not directly in the base directory."}),"\n",(0,s.jsxs)(t.p,{children:["The category folder name determines where the component appears in the Langflow ",(0,s.jsx)(c.A,{name:"Component","aria-hidden":"true"})," ",(0,s.jsx)(t.strong,{children:"Core components"})," menu.\nFor example, to add the example ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component to the ",(0,s.jsx)(t.strong,{children:"Data"})," category, place it in the ",(0,s.jsx)(t.code,{children:"data"})," subfolder:"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"src/lfx/src/lfx/components/",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 data/ # Category folder (determines menu location)",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py # Required - makes it a Python package",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 dataframe_processor.py # Your custom component file",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["If you're creating custom components in a different location using the ",(0,s.jsx)(t.code,{children:"LANGFLOW_COMPONENTS_PATH"})," ",(0,s.jsx)(t.a,{href:"/environment-variables",children:"environment variable"}),", components must be similarly organized in a specific directory structure to be displayed in the visual editor."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"/your/custom/components/path/ # Base directory set by LANGFLOW_COMPONENTS_PATH",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 category_name/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 custom_component.py",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsx)(t.p,{children:"You can have multiple category folders to organize components into different categories:"}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"/app/custom_components/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 data/",props:{}}]},{tokens:[{content:" \u2502 \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2502 \u2514\u2500\u2500 dataframe_processor.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 tools/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 custom_tool.py",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsxs)(t.h3,{id:"create-the-__init__py-file",children:["Create the ",(0,s.jsx)(t.code,{children:"__init__.py"})," file"]}),"\n",(0,s.jsxs)(t.p,{children:["Each category directory ",(0,s.jsx)(t.strong,{children:"must"})," contain an ",(0,s.jsx)(t.code,{children:"__init__.py"})," file for Langflow to properly recognize and load the components.\nThis is a Python package requirement that ensures the directory is treated as a module."]}),"\n",(0,s.jsxs)(t.p,{children:["To include the ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component, create a file named ",(0,s.jsx)(t.code,{children:"__init__.py"})," in your component's directory with the following content."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" .dataframe_processor ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" DataFrameProcessor",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"__all__ ",props:{style:{color:"#79C0FF"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}},{content:'"DataFrameProcessor"',props:{style:{color:"#A5D6FF"}}},{content:"]",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsxs)(e,{closed:!0,children:[(0,s.jsx)("summary",{children:"Lazy load the DataFrameProcessor component"}),(0,s.jsxs)(t.p,{children:["Alternatively, you can load your component ",(0,s.jsx)(t.strong,{children:"lazily"}),", which is better for performance but a little more complex."]}),(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from ",props:{style:{color:"#FF7B72"}}},{content:"__future__ ",props:{style:{color:"#79C0FF"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" annotations",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" typing ",props:{style:{color:"#C9D1D9"}}},{content:"import ",props:{style:{color:"#FF7B72"}}},{content:"TYPE_CHECKING",props:{style:{color:"#79C0FF"}}},{content:", Any",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.components._importing ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" import_mod",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"if ",props:{style:{color:"#FF7B72"}}},{content:"TYPE_CHECKING",props:{style:{color:"#79C0FF"}}},{content:":",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" from",props:{style:{color:"#FF7B72"}}},{content:" lfx.components.data.dataframe_processor ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" DataFrameProcessor",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"_dynamic_imports ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" {",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:' "DataFrameProcessor"',props:{style:{color:"#A5D6FF"}}},{content:": ",props:{style:{color:"#C9D1D9"}}},{content:'"dataframe_processor"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"}",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"__all__ ",props:{style:{color:"#79C0FF"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:' "DataFrameProcessor"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"]",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"def ",props:{style:{color:"#FF7B72"}}},{content:"__getattr__",props:{style:{color:"#79C0FF"}}},{content:"(attr_name: ",props:{style:{color:"#C9D1D9"}}},{content:"str",props:{style:{color:"#79C0FF"}}},{content:") -> Any:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:' """Lazily import data components on attribute access."""',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" if",props:{style:{color:"#FF7B72"}}},{content:" attr_name ",props:{style:{color:"#C9D1D9"}}},{content:"not in",props:{style:{color:"#FF7B72"}}},{content:" _dynamic_imports:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" msg ",props:{style:{color:"#C9D1D9"}}},{content:"= f",props:{style:{color:"#FF7B72"}}},{content:"\"module '",props:{style:{color:"#A5D6FF"}}},{content:"{__name__}",props:{style:{color:"#79C0FF"}}},{content:"' has no attribute '",props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"attr_name",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:"'\"",props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" raise ",props:{style:{color:"#FF7B72"}}},{content:"AttributeError",props:{style:{color:"#79C0FF"}}},{content:"(msg)",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" try",props:{style:{color:"#FF7B72"}}},{content:":",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" result ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" import_mod(attr_name, _dynamic_imports[attr_name], ",props:{style:{color:"#C9D1D9"}}},{content:"__spec__",props:{style:{color:"#79C0FF"}}},{content:".parent)",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" except",props:{style:{color:"#FF7B72"}}},{content:" (",props:{style:{color:"#C9D1D9"}}},{content:"ModuleNotFoundError",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"ImportError",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"AttributeError",props:{style:{color:"#79C0FF"}}},{content:") ",props:{style:{color:"#C9D1D9"}}},{content:"as",props:{style:{color:"#FF7B72"}}},{content:" e:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" msg ",props:{style:{color:"#C9D1D9"}}},{content:"= f",props:{style:{color:"#FF7B72"}}},{content:"\"Could not import '",props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"attr_name",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:"' from '",props:{style:{color:"#A5D6FF"}}},{content:"{__name__}",props:{style:{color:"#79C0FF"}}},{content:"': ",props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"e",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:'"',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" raise ",props:{style:{color:"#FF7B72"}}},{content:"AttributeError",props:{style:{color:"#79C0FF"}}},{content:"(msg) ",props:{style:{color:"#C9D1D9"}}},{content:"from",props:{style:{color:"#FF7B72"}}},{content:" e",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" globals",props:{style:{color:"#79C0FF"}}},{content:"()[attr_name] ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" result",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" result",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"def ",props:{style:{color:"#FF7B72"}}},{content:"__dir__",props:{style:{color:"#79C0FF"}}},{content:"() -> list[",props:{style:{color:"#C9D1D9"}}},{content:"str",props:{style:{color:"#79C0FF"}}},{content:"]:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" return ",props:{style:{color:"#FF7B72"}}},{content:"list",props:{style:{color:"#79C0FF"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"__all__",props:{style:{color:"#79C0FF"}}},{content:")",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),(0,s.jsxs)(t.p,{children:["For an additional example of lazy loading, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/components/FAISS/__init__.py",children:"FAISS component"}),"."]})]}),"\n",(0,s.jsx)(t.h3,{id:"load-your-component",children:"Load your component"}),"\n",(0,s.jsx)(t.p,{children:"Ensure the application builds your component."}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["To rebuild the backend and frontend, run ",(0,s.jsx)(t.code,{children:"make install_frontend && make build_frontend && make install_backend && uv run langflow run --port 7860"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["Refresh the frontend application.\nYour new ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component is available in the ",(0,s.jsx)(c.A,{name:"Component","aria-hidden":"true"})," ",(0,s.jsx)(t.strong,{children:"Core components"})," menu under the ",(0,s.jsx)(t.strong,{children:"Data"})," category in the visual editor."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"docker-deployment",children:"Docker deployment"}),"\n",(0,s.jsxs)(t.p,{children:["When running Langflow in Docker, mount your custom components directory and set the ",(0,s.jsx)(t.code,{children:"LANGFLOW_COMPONENTS_PATH"})," environment variable in the ",(0,s.jsx)(t.code,{children:"docker run"})," command to point to the custom components directory."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"docker ",props:{style:{color:"#FFA657"}}},{content:"run ",props:{style:{color:"#A5D6FF"}}},{content:"-d \\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" --name ",props:{style:{color:"#79C0FF"}}},{content:"langflow ",props:{style:{color:"#A5D6FF"}}},{content:"\\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" -p ",props:{style:{color:"#79C0FF"}}},{content:"7860:",props:{style:{color:"#A5D6FF"}}},{content:"7860 \\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" -v ",props:{style:{color:"#79C0FF"}}},{content:"./custom_components:/app/custom_components ",props:{style:{color:"#A5D6FF"}}},{content:"\\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" -e ",props:{style:{color:"#79C0FF"}}},{content:"LANGFLOW_COMPONENTS_PATH=/app/custom_components ",props:{style:{color:"#A5D6FF"}}},{content:"\\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" langflowai/langflow:latest",props:{style:{color:"#A5D6FF"}}}]}],lang:"bash"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["Create the same custom components directory structure as the example in ",(0,s.jsx)(t.a,{href:"#custom-component-path",children:"Save the custom component"}),"."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"/app/custom_components/ # LANGFLOW_COMPONENTS_PATH",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 data/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 dataframe_processor.py",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsx)(t.h2,{id:"how-components-execute",children:"How components execute"}),"\n",(0,s.jsx)(t.p,{children:"Langflow's engine manages:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Instantiation"}),": A component is created and internal structures are initialized."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Assigning Inputs"}),": Values from the visual editor or connections are assigned to component fields."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Validation and Setup"}),": Optional hooks like ",(0,s.jsx)(t.code,{children:"_pre_run_setup"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Outputs Generation"}),": ",(0,s.jsx)(t.code,{children:"run()"})," or ",(0,s.jsx)(t.code,{children:"build_results()"})," triggers output methods."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"You can customize execution by overriding these optional hooks in your custom component code."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"_pre_run_setup()"})})," - Used during ",(0,s.jsx)(t.strong,{children:"Validation and Setup"}),".\nAdd this method inside your component class to initialize component state before execution begins:"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"class ",props:{style:{color:"#FF7B72"}}},{content:"MyComponent",props:{style:{color:"#FFA657"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"Component",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # ... your inputs, outputs, and other attributes ...",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"_pre_run_setup",props:{style:{color:"#D2A8FF"}}},{content:"(self):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" if not ",props:{style:{color:"#FF7B72"}}},{content:"hasattr",props:{style:{color:"#79C0FF"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"self",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:'"_initialized"',props:{style:{color:"#A5D6FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:"._initialized ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"True",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".iteration ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"0",props:{style:{color:"#79C0FF"}}}]}],lang:"python"},annotations:[]}]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsxs)(t.strong,{children:["Override ",(0,s.jsx)(t.code,{children:"run"})," or ",(0,s.jsx)(t.code,{children:"_run"})]})," - Used during ",(0,s.jsx)(t.strong,{children:"Outputs Generation"}),".\nAdd this method inside your component class to customize the main execution logic:"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"class ",props:{style:{color:"#FF7B72"}}},{content:"MyComponent",props:{style:{color:"#FFA657"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"Component",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" async",props:{style:{color:"#FF7B72"}}},{content:" def_run(",props:{style:{color:"#C9D1D9"}}},{content:"self",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Custom execution logic here",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" # This runs instead of the default output method calls",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" pass",props:{style:{color:"#FF7B72"}}}]}],lang:"python"},annotations:[]}]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsxs)(t.strong,{children:["Store data in ",(0,s.jsx)(t.code,{children:"self.ctx"})]}),".\nUse ",(0,s.jsx)(t.code,{children:"self.ctx"})," in any of your component methods to share data between method calls."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"class ",props:{style:{color:"#FF7B72"}}},{content:"MyComponent",props:{style:{color:"#FFA657"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"Component",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"_pre_run_setup",props:{style:{color:"#D2A8FF"}}},{content:"(self):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Initialize counter in setup",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:'"processed_items"',props:{style:{color:"#A5D6FF"}}},{content:"] ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"0",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"process_data",props:{style:{color:"#D2A8FF"}}},{content:"(self) -> Data:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Increment counter during processing",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:'"processed_items"',props:{style:{color:"#A5D6FF"}}},{content:"] ",props:{style:{color:"#C9D1D9"}}},{content:"+= ",props:{style:{color:"#FF7B72"}}},{content:"1",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" Data(",props:{style:{color:"#C9D1D9"}}},{content:"data",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"{",props:{style:{color:"#C9D1D9"}}},{content:'"item"',props:{style:{color:"#A5D6FF"}}},{content:": ",props:{style:{color:"#C9D1D9"}}},{content:"f",props:{style:{color:"#FF7B72"}}},{content:'"processed ',props:{style:{color:"#A5D6FF"}}},{content:"{self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:"'processed_items'",props:{style:{color:"#A5D6FF"}}},{content:"]",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:'"',props:{style:{color:"#A5D6FF"}}},{content:"})",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"get_summary",props:{style:{color:"#D2A8FF"}}},{content:"(self) -> Data:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Access counter in different method",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" total ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:'"processed_items"',props:{style:{color:"#A5D6FF"}}},{content:"]",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" Data(",props:{style:{color:"#C9D1D9"}}},{content:"data",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"{",props:{style:{color:"#C9D1D9"}}},{content:'"summary"',props:{style:{color:"#A5D6FF"}}},{content:": ",props:{style:{color:"#C9D1D9"}}},{content:"f",props:{style:{color:"#FF7B72"}}},{content:'"Processed ',props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"total",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:' items total"',props:{style:{color:"#A5D6FF"}}},{content:"})",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"inputs-and-outputs",children:"Inputs and outputs"}),"\n",(0,s.jsxs)(t.p,{children:["Inputs and outputs are ",(0,s.jsx)(t.strong,{children:"class-level configurations"})," that define how data flows through the component, how it appears in the visual editor, and how connections to other components are validated."]}),"\n",(0,s.jsx)(t.h3,{id:"inputs",children:"Inputs"}),"\n",(0,s.jsxs)(t.p,{children:["Inputs are defined in a class-level ",(0,s.jsx)(t.code,{children:"inputs"})," list. When Langflow loads the component, it uses this list to render component fields and ",(0,s.jsx)(t.a,{href:"/concepts-components#component-ports",children:"ports"})," in the visual editor. Users or other components provide values or connections to fill these inputs."]}),"\n",(0,s.jsxs)(t.p,{children:["An input is usually an instance of a class from ",(0,s.jsx)(t.code,{children:"lfx.io"})," (such as ",(0,s.jsx)(t.code,{children:"StrInput"}),", ",(0,s.jsx)(t.code,{children:"DataInput"}),", or ",(0,s.jsx)(t.code,{children:"MessageTextInput"}),")."]}),"\n",(0,s.jsxs)(t.p,{children:["For example, this component has three inputs: a text field (",(0,s.jsx)(t.code,{children:"StrInput"}),"), a Boolean toggle (",(0,s.jsx)(t.code,{children:"BoolInput"}),"), and a dropdown selection (",(0,s.jsx)(t.code,{children:"DropdownInput"}),")."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.io ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" StrInput, BoolInput, DropdownInput",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"inputs ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" StrInput(",props:{style:{color:"#C9D1D9"}}},{content:"name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"title"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Title"',props:{style:{color:"#A5D6FF"}}},{content:"),",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" BoolInput(",props:{style:{color:"#C9D1D9"}}},{content:"name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"enabled"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Enabled"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"value",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"True",props:{style:{color:"#79C0FF"}}},{content:"),",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" DropdownInput(",props:{style:{color:"#C9D1D9"}}},{content:"name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"mode"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Mode"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"options",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"[",props:{style:{color:"#C9D1D9"}}},{content:'"Fast"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:'"Safe"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:'"Experimental"',props:{style:{color:"#A5D6FF"}}},{content:"], ",props:{style:{color:"#C9D1D9"}}},{content:"value",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Safe"',props:{style:{color:"#A5D6FF"}}},{content:")",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"]",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"StrInput"})," creates a single-line text field for entering text. The ",(0,s.jsx)(t.code,{children:'name="title"'})," parameter means you access this value in your component methods with ",(0,s.jsx)(t.code,{children:"self.title"}),", while ",(0,s.jsx)(t.code,{children:'display_name="Title"'}),' shows "Title" as the label in the visual editor.']}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"BoolInput"})," creates a boolean toggle that's enabled by default with ",(0,s.jsx)(t.code,{children:"value=True"}),". Users can turn this on or off, and you access the current state with ",(0,s.jsx)(t.code,{children:"self.enabled"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"DropdownInput"}),' provides a selection menu with three predefined options: "Fast", "Safe", and "Experimental".\nThe ',(0,s.jsx)(t.code,{children:'value="Safe"'}),' sets "Safe" as the default selection, and you access the user\'s choice with ',(0,s.jsx)(t.code,{children:"self.mode"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["For a list of all available parameters, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/inputs/input_mixin.py",children:"BaseInputMixin definition"})," in the Langflow codebase."]}),"\n",(0,s.jsxs)(t.p,{children:["For a list of all available input types, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/inputs/inputs.py",children:"input type definitions"})," in the Langflow codebase."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.io ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" StrInput, DataInput, MultilineInput, IntInput, BoolInput, DropdownInput, FileInput, CodeInput, ModelInput, HandleInput, Output",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsx)(t.h3,{id:"outputs",children:"Outputs"}),"\n",(0,s.jsxs)(t.p,{children:["Outputs are defined in a class-level ",(0,s.jsx)(t.code,{children:"outputs"})," 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."]}),"\n",(0,s.jsxs)(t.p,{children:["An output is usually an instance of ",(0,s.jsx)(t.code,{children:"Output"})," from ",(0,s.jsx)(t.code,{children:"lfx.io"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["For example, this component has one ",(0,s.jsx)(t.code,{children:"output"})," that returns a ",(0,s.jsx)(t.code,{children:"DataFrame"}),":"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.io ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" Output",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.schema ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" DataFrame",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"outputs ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" Output(",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"df_out"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"DataFrame Output"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" method",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"build_df"',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" )",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"]",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"def ",props:{style:{color:"#FF7B72"}}},{content:"build_df",props:{style:{color:"#D2A8FF"}}},{content:"(self) -> DataFrame:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Process data and return DataFrame",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" df ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" DataFrame({",props:{style:{color:"#C9D1D9"}}},{content:'"col1"',props:{style:{color:"#A5D6FF"}}},{content:": [",props:{style:{color:"#C9D1D9"}}},{content:"1",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"2",props:{style:{color:"#79C0FF"}}},{content:"], ",props:{style:{color:"#C9D1D9"}}},{content:'"col2"',props:{style:{color:"#A5D6FF"}}},{content:": [",props:{style:{color:"#C9D1D9"}}},{content:"3",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"4",props:{style:{color:"#79C0FF"}}},{content:"]})",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".status ",props:{style:{color:"#C9D1D9"}}},{content:"= f",props:{style:{color:"#FF7B72"}}},{content:'"Built DataFrame with ',props:{style:{color:"#A5D6FF"}}},{content:"{len",props:{style:{color:"#79C0FF"}}},{content:"(df)",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:' rows."',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" df",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"Output"})," creates a connector point in the visual editor labeled ",(0,s.jsx)(t.strong,{children:"DataFrame Output"}),". The ",(0,s.jsx)(t.code,{children:'name="df_out"'})," parameter identifies this output, while ",(0,s.jsx)(t.code,{children:'display_name="DataFrame Output"'})," shows the label in the UI. The ",(0,s.jsx)(t.code,{children:'method="build_df"'})," parameter tells Langflow to call the ",(0,s.jsx)(t.code,{children:"build_df"})," method when this output is connected to another component."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"build_df"})," method processes data and returns a ",(0,s.jsx)(t.code,{children:"DataFrame"}),". The ",(0,s.jsx)(t.code,{children:"-> DataFrame"})," type annotation helps Langflow validate connections and provides color-coding in the visual editor. You can also set ",(0,s.jsx)(t.code,{children:"self.status"})," to show progress messages in the UI."]}),"\n",(0,s.jsxs)(t.p,{children:["For a complete list of all available parameters, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/template/field/base.py",children:"Output class definition"})," in the Langflow codebase. Common parameters include:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Additional return types:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"Message"})}),": Structured chat messages"]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"Data"})}),": Flexible object with ",(0,s.jsx)(t.code,{children:".data"})," and optional ",(0,s.jsx)(t.code,{children:".text"})]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"DataFrame"})}),": Tabular data (pandas DataFrame subclass)"]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Primitive types"}),": ",(0,s.jsx)(t.code,{children:"str"}),", ",(0,s.jsx)(t.code,{children:"int"}),", ",(0,s.jsx)(t.code,{children:"bool"}),", not recommended for type consistency"]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"associated-methods",children:"Associated methods"}),"\n",(0,s.jsxs)(t.p,{children:["Each output is linked to a method where the output method name must match the method name. The method typically returns objects like ",(0,s.jsx)(t.code,{children:"Message"}),", ",(0,s.jsx)(t.code,{children:"Data"}),", or ",(0,s.jsx)(t.code,{children:"DataFrame"}),", and can use inputs with ",(0,s.jsx)(t.code,{children:"self.__init__.py file",id:"create-the-__init__py-file",level:3},{value:"Load your component",id:"load-your-component",level:3},{value:"Docker deployment",id:"docker-deployment",level:3},{value:"How components execute",id:"how-components-execute",level:2},{value:"Inputs and outputs",id:"inputs-and-outputs",level:2},{value:"Inputs",id:"inputs",level:3},{value:"Outputs",id:"outputs",level:3},{value:"Associated methods",id:"associated-methods",level:4},{value:"Components with multiple outputs",id:"components-with-multiple-outputs",level:4},{value:"Tool mode",id:"tool-mode",level:3},{value:"Typed annotations",id:"typed-annotations",level:2},{value:"Common return types",id:"common-return-types",level:3},{value:"Enable dynamic fields",id:"enable-dynamic-fields",level:2},{value:"Show or hide fields based on user selections",id:"show-or-hide-fields-based-on-user-selections",level:3},{value:"Error handling and logging",id:"error-handling-and-logging",level:2},{value:"Contribute custom components to Langflow",id:"contribute-custom-components-to-langflow",level:2}];function m(o){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",h4:"h4",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...o.components},{Details:e}=t;return h||f("CH",!1),h.Code||f("CH.Code",!0),e||f("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)("style",{dangerouslySetInnerHTML:{__html:'[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; }'}}),"\n","\n",(0,s.jsx)(t.p,{children:"Create your own custom components to add any functionality you need to Langflow, from API integrations to data processing."}),"\n",(0,s.jsx)(t.p,{children:'In Langflow\'s node-based environment, each node is a "component" that performs discrete functions.\nCustom components in Langflow are built upon:'}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["The Python class that inherits from ",(0,s.jsx)(t.code,{children:"Component"}),"."]}),"\n",(0,s.jsx)(t.li,{children:"Class-level attributes that identify and describe the component."}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.a,{href:"#inputs-and-outputs",children:"Input and output lists"})," that determine data flow."]}),"\n",(0,s.jsx)(t.li,{children:"Methods that define the component's behavior and logic."}),"\n",(0,s.jsxs)(t.li,{children:["Internal variables for ",(0,s.jsx)(t.a,{href:"#error-handling-and-logging",children:"Error handling and logging"})]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["Use the ",(0,s.jsx)(t.a,{href:"#quickstart",children:"Custom component quickstart"})," to add an example component to Langflow, and then use the reference guide that follows for more advanced component customization."]}),"\n",(0,s.jsx)(t.h2,{id:"quickstart",children:"Custom component quickstart"}),"\n",(0,s.jsxs)(t.p,{children:["Create a custom ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component by creating a Python file, saving it in the correct folder, including an ",(0,s.jsx)(t.code,{children:"__init__.py"})," file, and loading it into Langflow."]}),"\n",(0,s.jsx)(t.h3,{id:"create-a-python-file",children:"Create a Python file"}),"\n",(0,s.jsx)(i.Ay,{}),"\n",(0,s.jsx)(t.h3,{id:"custom-component-path",children:"Save the custom component"}),"\n",(0,s.jsx)(t.p,{children:"Save the custom component in the Langflow directory where the UI will discover and load it."}),"\n",(0,s.jsxs)(t.p,{children:["By default, Langflow looks for custom components in the ",(0,s.jsx)(t.code,{children:"src/lfx/src/lfx/components"})," directory."]}),"\n",(0,s.jsx)(t.p,{children:"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."}),"\n",(0,s.jsx)(t.p,{children:"Components must be placed inside category folders, not directly in the base directory."}),"\n",(0,s.jsxs)(t.p,{children:["The category folder name determines where the component appears in the Langflow ",(0,s.jsx)(c.A,{name:"Component","aria-hidden":"true"})," ",(0,s.jsx)(t.strong,{children:"Core components"})," menu.\nFor example, to add the example ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component to the ",(0,s.jsx)(t.strong,{children:"Data"})," category, place it in the ",(0,s.jsx)(t.code,{children:"data"})," subfolder:"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"src/lfx/src/lfx/components/",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 data/ # Category folder (determines menu location)",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py # Required - makes it a Python package",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 dataframe_processor.py # Your custom component file",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["If you're creating custom components in a different location using the ",(0,s.jsx)(t.code,{children:"LANGFLOW_COMPONENTS_PATH"})," ",(0,s.jsx)(t.a,{href:"/environment-variables",children:"environment variable"}),", components must be similarly organized in a specific directory structure to be displayed in the visual editor."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"/your/custom/components/path/ # Base directory set by LANGFLOW_COMPONENTS_PATH",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 category_name/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 custom_component.py",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsx)(t.p,{children:"You can have multiple category folders to organize components into different categories, with multiple components inside each folder:"}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"/app/custom_components/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 data/",props:{}}]},{tokens:[{content:" \u2502 \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2502 \u251c\u2500\u2500 custom_component.py",props:{}}]},{tokens:[{content:" \u2502 \u2514\u2500\u2500 dataframe_processor.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 tools/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 custom_tool.py",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsxs)(t.h3,{id:"create-the-__init__py-file",children:["Create the ",(0,s.jsx)(t.code,{children:"__init__.py"})," file"]}),"\n",(0,s.jsxs)(t.p,{children:["Each category directory ",(0,s.jsx)(t.strong,{children:"must"})," contain an ",(0,s.jsx)(t.code,{children:"__init__.py"})," file for Langflow to properly recognize and load the components.\nThis is a Python package requirement that ensures the directory is treated as a module."]}),"\n",(0,s.jsxs)(t.p,{children:["To include the ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component, create a file named ",(0,s.jsx)(t.code,{children:"__init__.py"})," in your component's directory with the following content."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" .dataframe_processor ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" DataFrameProcessor",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"__all__ ",props:{style:{color:"#79C0FF"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}},{content:'"DataFrameProcessor"',props:{style:{color:"#A5D6FF"}}},{content:"]",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsxs)(e,{closed:!0,children:[(0,s.jsx)("summary",{children:"Lazy load the DataFrameProcessor component"}),(0,s.jsxs)(t.p,{children:["Alternatively, you can load your component ",(0,s.jsx)(t.strong,{children:"lazily"}),", which is better for performance but a little more complex."]}),(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from ",props:{style:{color:"#FF7B72"}}},{content:"__future__ ",props:{style:{color:"#79C0FF"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" annotations",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" typing ",props:{style:{color:"#C9D1D9"}}},{content:"import ",props:{style:{color:"#FF7B72"}}},{content:"TYPE_CHECKING",props:{style:{color:"#79C0FF"}}},{content:", Any",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.components._importing ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" import_mod",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"if ",props:{style:{color:"#FF7B72"}}},{content:"TYPE_CHECKING",props:{style:{color:"#79C0FF"}}},{content:":",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" from",props:{style:{color:"#FF7B72"}}},{content:" lfx.components.data.dataframe_processor ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" DataFrameProcessor",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"_dynamic_imports ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" {",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:' "DataFrameProcessor"',props:{style:{color:"#A5D6FF"}}},{content:": ",props:{style:{color:"#C9D1D9"}}},{content:'"dataframe_processor"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"}",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"__all__ ",props:{style:{color:"#79C0FF"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:' "DataFrameProcessor"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"]",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"def ",props:{style:{color:"#FF7B72"}}},{content:"__getattr__",props:{style:{color:"#79C0FF"}}},{content:"(attr_name: ",props:{style:{color:"#C9D1D9"}}},{content:"str",props:{style:{color:"#79C0FF"}}},{content:") -> Any:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:' """Lazily import data components on attribute access."""',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" if",props:{style:{color:"#FF7B72"}}},{content:" attr_name ",props:{style:{color:"#C9D1D9"}}},{content:"not in",props:{style:{color:"#FF7B72"}}},{content:" _dynamic_imports:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" msg ",props:{style:{color:"#C9D1D9"}}},{content:"= f",props:{style:{color:"#FF7B72"}}},{content:"\"module '",props:{style:{color:"#A5D6FF"}}},{content:"{__name__}",props:{style:{color:"#79C0FF"}}},{content:"' has no attribute '",props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"attr_name",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:"'\"",props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" raise ",props:{style:{color:"#FF7B72"}}},{content:"AttributeError",props:{style:{color:"#79C0FF"}}},{content:"(msg)",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" try",props:{style:{color:"#FF7B72"}}},{content:":",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" result ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" import_mod(attr_name, _dynamic_imports[attr_name], ",props:{style:{color:"#C9D1D9"}}},{content:"__spec__",props:{style:{color:"#79C0FF"}}},{content:".parent)",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" except",props:{style:{color:"#FF7B72"}}},{content:" (",props:{style:{color:"#C9D1D9"}}},{content:"ModuleNotFoundError",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"ImportError",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"AttributeError",props:{style:{color:"#79C0FF"}}},{content:") ",props:{style:{color:"#C9D1D9"}}},{content:"as",props:{style:{color:"#FF7B72"}}},{content:" e:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" msg ",props:{style:{color:"#C9D1D9"}}},{content:"= f",props:{style:{color:"#FF7B72"}}},{content:"\"Could not import '",props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"attr_name",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:"' from '",props:{style:{color:"#A5D6FF"}}},{content:"{__name__}",props:{style:{color:"#79C0FF"}}},{content:"': ",props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"e",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:'"',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" raise ",props:{style:{color:"#FF7B72"}}},{content:"AttributeError",props:{style:{color:"#79C0FF"}}},{content:"(msg) ",props:{style:{color:"#C9D1D9"}}},{content:"from",props:{style:{color:"#FF7B72"}}},{content:" e",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" globals",props:{style:{color:"#79C0FF"}}},{content:"()[attr_name] ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" result",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" result",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"def ",props:{style:{color:"#FF7B72"}}},{content:"__dir__",props:{style:{color:"#79C0FF"}}},{content:"() -> list[",props:{style:{color:"#C9D1D9"}}},{content:"str",props:{style:{color:"#79C0FF"}}},{content:"]:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" return ",props:{style:{color:"#FF7B72"}}},{content:"list",props:{style:{color:"#79C0FF"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"__all__",props:{style:{color:"#79C0FF"}}},{content:")",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),(0,s.jsxs)(t.p,{children:["For an additional example of lazy loading, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/components/FAISS/__init__.py",children:"FAISS component"}),"."]})]}),"\n",(0,s.jsx)(t.h3,{id:"load-your-component",children:"Load your component"}),"\n",(0,s.jsx)(t.p,{children:"Ensure the application builds your component."}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["To rebuild the backend and frontend, run ",(0,s.jsx)(t.code,{children:"make install_frontend && make build_frontend && make install_backend && uv run langflow run --port 7860"}),"."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["Refresh the frontend application.\nYour new ",(0,s.jsx)(t.code,{children:"DataFrameProcessor"})," component is available in the ",(0,s.jsx)(c.A,{name:"Component","aria-hidden":"true"})," ",(0,s.jsx)(t.strong,{children:"Core components"})," menu under the ",(0,s.jsx)(t.strong,{children:"Data"})," category in the visual editor."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"docker-deployment",children:"Docker deployment"}),"\n",(0,s.jsxs)(t.p,{children:["When running Langflow in Docker, mount your custom components directory and set the ",(0,s.jsx)(t.code,{children:"LANGFLOW_COMPONENTS_PATH"})," environment variable in the ",(0,s.jsx)(t.code,{children:"docker run"})," command to point to the custom components directory."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"docker ",props:{style:{color:"#FFA657"}}},{content:"run ",props:{style:{color:"#A5D6FF"}}},{content:"-d \\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" --name ",props:{style:{color:"#79C0FF"}}},{content:"langflow ",props:{style:{color:"#A5D6FF"}}},{content:"\\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" -p ",props:{style:{color:"#79C0FF"}}},{content:"7860:",props:{style:{color:"#A5D6FF"}}},{content:"7860 \\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" -v ",props:{style:{color:"#79C0FF"}}},{content:"./custom_components:/app/custom_components ",props:{style:{color:"#A5D6FF"}}},{content:"\\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" -e ",props:{style:{color:"#79C0FF"}}},{content:"LANGFLOW_COMPONENTS_PATH=/app/custom_components ",props:{style:{color:"#A5D6FF"}}},{content:"\\",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" langflowai/langflow:latest",props:{style:{color:"#A5D6FF"}}}]}],lang:"bash"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["Create the same custom components directory structure as the example in ",(0,s.jsx)(t.a,{href:"#custom-component-path",children:"Save the custom component"}),"."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"/app/custom_components/ # LANGFLOW_COMPONENTS_PATH",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 data/",props:{}}]},{tokens:[{content:" \u251c\u2500\u2500 __init__.py",props:{}}]},{tokens:[{content:" \u2514\u2500\u2500 dataframe_processor.py",props:{}}]}],lang:"text"},annotations:[]}]}),"\n",(0,s.jsx)(t.h2,{id:"how-components-execute",children:"How components execute"}),"\n",(0,s.jsx)(t.p,{children:"Langflow's engine manages:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Instantiation"}),": A component is created and internal structures are initialized."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Assigning Inputs"}),": Values from the visual editor or connections are assigned to component fields."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Validation and Setup"}),": Optional hooks like ",(0,s.jsx)(t.code,{children:"_pre_run_setup"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Outputs Generation"}),": ",(0,s.jsx)(t.code,{children:"run()"})," or ",(0,s.jsx)(t.code,{children:"build_results()"})," triggers output methods."]}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"You can customize execution by overriding these optional hooks in your custom component code."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"_pre_run_setup()"})})," - Used during ",(0,s.jsx)(t.strong,{children:"Validation and Setup"}),".\nAdd this method inside your component class to initialize component state before execution begins:"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"class ",props:{style:{color:"#FF7B72"}}},{content:"MyComponent",props:{style:{color:"#FFA657"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"Component",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # ... your inputs, outputs, and other attributes ...",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"_pre_run_setup",props:{style:{color:"#D2A8FF"}}},{content:"(self):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" if not ",props:{style:{color:"#FF7B72"}}},{content:"hasattr",props:{style:{color:"#79C0FF"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"self",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:'"_initialized"',props:{style:{color:"#A5D6FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:"._initialized ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"True",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".iteration ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"0",props:{style:{color:"#79C0FF"}}}]}],lang:"python"},annotations:[]}]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsxs)(t.strong,{children:["Override ",(0,s.jsx)(t.code,{children:"run"})," or ",(0,s.jsx)(t.code,{children:"_run"})]})," - Used during ",(0,s.jsx)(t.strong,{children:"Outputs Generation"}),".\nAdd this method inside your component class to customize the main execution logic:"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"class ",props:{style:{color:"#FF7B72"}}},{content:"MyComponent",props:{style:{color:"#FFA657"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"Component",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" async",props:{style:{color:"#FF7B72"}}},{content:" def_run(",props:{style:{color:"#C9D1D9"}}},{content:"self",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Custom execution logic here",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" # This runs instead of the default output method calls",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" pass",props:{style:{color:"#FF7B72"}}}]}],lang:"python"},annotations:[]}]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsxs)(t.strong,{children:["Store data in ",(0,s.jsx)(t.code,{children:"self.ctx"})]}),".\nUse ",(0,s.jsx)(t.code,{children:"self.ctx"})," in any of your component methods to share data between method calls."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"class ",props:{style:{color:"#FF7B72"}}},{content:"MyComponent",props:{style:{color:"#FFA657"}}},{content:"(",props:{style:{color:"#C9D1D9"}}},{content:"Component",props:{style:{color:"#79C0FF"}}},{content:"):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"_pre_run_setup",props:{style:{color:"#D2A8FF"}}},{content:"(self):",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Initialize counter in setup",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:'"processed_items"',props:{style:{color:"#A5D6FF"}}},{content:"] ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"0",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"process_data",props:{style:{color:"#D2A8FF"}}},{content:"(self) -> Data:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Increment counter during processing",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:'"processed_items"',props:{style:{color:"#A5D6FF"}}},{content:"] ",props:{style:{color:"#C9D1D9"}}},{content:"+= ",props:{style:{color:"#FF7B72"}}},{content:"1",props:{style:{color:"#79C0FF"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" Data(",props:{style:{color:"#C9D1D9"}}},{content:"data",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"{",props:{style:{color:"#C9D1D9"}}},{content:'"item"',props:{style:{color:"#A5D6FF"}}},{content:": ",props:{style:{color:"#C9D1D9"}}},{content:"f",props:{style:{color:"#FF7B72"}}},{content:'"processed ',props:{style:{color:"#A5D6FF"}}},{content:"{self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:"'processed_items'",props:{style:{color:"#A5D6FF"}}},{content:"]",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:'"',props:{style:{color:"#A5D6FF"}}},{content:"})",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" def ",props:{style:{color:"#FF7B72"}}},{content:"get_summary",props:{style:{color:"#D2A8FF"}}},{content:"(self) -> Data:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Access counter in different method",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" total ",props:{style:{color:"#C9D1D9"}}},{content:"= ",props:{style:{color:"#FF7B72"}}},{content:"self",props:{style:{color:"#79C0FF"}}},{content:".ctx[",props:{style:{color:"#C9D1D9"}}},{content:'"processed_items"',props:{style:{color:"#A5D6FF"}}},{content:"]",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" Data(",props:{style:{color:"#C9D1D9"}}},{content:"data",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"{",props:{style:{color:"#C9D1D9"}}},{content:'"summary"',props:{style:{color:"#A5D6FF"}}},{content:": ",props:{style:{color:"#C9D1D9"}}},{content:"f",props:{style:{color:"#FF7B72"}}},{content:'"Processed ',props:{style:{color:"#A5D6FF"}}},{content:"{",props:{style:{color:"#79C0FF"}}},{content:"total",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:' items total"',props:{style:{color:"#A5D6FF"}}},{content:"})",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"inputs-and-outputs",children:"Inputs and outputs"}),"\n",(0,s.jsxs)(t.p,{children:["Inputs and outputs are ",(0,s.jsx)(t.strong,{children:"class-level configurations"})," that define how data flows through the component, how it appears in the visual editor, and how connections to other components are validated."]}),"\n",(0,s.jsx)(t.h3,{id:"inputs",children:"Inputs"}),"\n",(0,s.jsxs)(t.p,{children:["Inputs are defined in a class-level ",(0,s.jsx)(t.code,{children:"inputs"})," list. When Langflow loads the component, it uses this list to render component fields and ",(0,s.jsx)(t.a,{href:"/concepts-components#component-ports",children:"ports"})," in the visual editor. Users or other components provide values or connections to fill these inputs."]}),"\n",(0,s.jsxs)(t.p,{children:["An input is usually an instance of a class from ",(0,s.jsx)(t.code,{children:"lfx.io"})," (such as ",(0,s.jsx)(t.code,{children:"StrInput"}),", ",(0,s.jsx)(t.code,{children:"DataInput"}),", or ",(0,s.jsx)(t.code,{children:"MessageTextInput"}),")."]}),"\n",(0,s.jsxs)(t.p,{children:["For example, this component has three inputs: a text field (",(0,s.jsx)(t.code,{children:"StrInput"}),"), a Boolean toggle (",(0,s.jsx)(t.code,{children:"BoolInput"}),"), and a dropdown selection (",(0,s.jsx)(t.code,{children:"DropdownInput"}),")."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.io ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" StrInput, BoolInput, DropdownInput",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"inputs ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" StrInput(",props:{style:{color:"#C9D1D9"}}},{content:"name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"title"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Title"',props:{style:{color:"#A5D6FF"}}},{content:"),",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" BoolInput(",props:{style:{color:"#C9D1D9"}}},{content:"name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"enabled"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Enabled"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"value",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"True",props:{style:{color:"#79C0FF"}}},{content:"),",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" DropdownInput(",props:{style:{color:"#C9D1D9"}}},{content:"name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"mode"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Mode"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"options",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:"[",props:{style:{color:"#C9D1D9"}}},{content:'"Fast"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:'"Safe"',props:{style:{color:"#A5D6FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:'"Experimental"',props:{style:{color:"#A5D6FF"}}},{content:"], ",props:{style:{color:"#C9D1D9"}}},{content:"value",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"Safe"',props:{style:{color:"#A5D6FF"}}},{content:")",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"]",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"StrInput"})," creates a single-line text field for entering text. The ",(0,s.jsx)(t.code,{children:'name="title"'})," parameter means you access this value in your component methods with ",(0,s.jsx)(t.code,{children:"self.title"}),", while ",(0,s.jsx)(t.code,{children:'display_name="Title"'}),' shows "Title" as the label in the visual editor.']}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"BoolInput"})," creates a boolean toggle that's enabled by default with ",(0,s.jsx)(t.code,{children:"value=True"}),". Users can turn this on or off, and you access the current state with ",(0,s.jsx)(t.code,{children:"self.enabled"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"DropdownInput"}),' provides a selection menu with three predefined options: "Fast", "Safe", and "Experimental".\nThe ',(0,s.jsx)(t.code,{children:'value="Safe"'}),' sets "Safe" as the default selection, and you access the user\'s choice with ',(0,s.jsx)(t.code,{children:"self.mode"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["For a list of all available parameters, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/inputs/input_mixin.py",children:"BaseInputMixin definition"})," in the Langflow codebase."]}),"\n",(0,s.jsxs)(t.p,{children:["For a list of all available input types, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/inputs/inputs.py",children:"input type definitions"})," in the Langflow codebase."]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.io ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" StrInput, DataInput, MultilineInput, IntInput, BoolInput, DropdownInput, FileInput, CodeInput, ModelInput, HandleInput, Output",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsx)(t.h3,{id:"outputs",children:"Outputs"}),"\n",(0,s.jsxs)(t.p,{children:["Outputs are defined in a class-level ",(0,s.jsx)(t.code,{children:"outputs"})," 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."]}),"\n",(0,s.jsxs)(t.p,{children:["An output is usually an instance of ",(0,s.jsx)(t.code,{children:"Output"})," from ",(0,s.jsx)(t.code,{children:"lfx.io"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["For example, this component has one ",(0,s.jsx)(t.code,{children:"output"})," that returns a ",(0,s.jsx)(t.code,{children:"DataFrame"}),":"]}),"\n",(0,s.jsx)(h.Code,{codeConfig:u,northPanel:{tabs:[""],active:"",heightRatio:1},files:[{name:"",focus:"",code:{lines:[{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.io ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" Output",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"from",props:{style:{color:"#FF7B72"}}},{content:" lfx.schema ",props:{style:{color:"#C9D1D9"}}},{content:"import",props:{style:{color:"#FF7B72"}}},{content:" DataFrame",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"outputs ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" [",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" Output(",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"df_out"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" display_name",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"DataFrame Output"',props:{style:{color:"#A5D6FF"}}},{content:",",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" method",props:{style:{color:"#FFA657"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:'"build_df"',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" )",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"]",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:"def ",props:{style:{color:"#FF7B72"}}},{content:"build_df",props:{style:{color:"#D2A8FF"}}},{content:"(self) -> DataFrame:",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" # Process data and return DataFrame",props:{style:{color:"#8B949E"}}}]},{tokens:[{content:" df ",props:{style:{color:"#C9D1D9"}}},{content:"=",props:{style:{color:"#FF7B72"}}},{content:" DataFrame({",props:{style:{color:"#C9D1D9"}}},{content:'"col1"',props:{style:{color:"#A5D6FF"}}},{content:": [",props:{style:{color:"#C9D1D9"}}},{content:"1",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"2",props:{style:{color:"#79C0FF"}}},{content:"], ",props:{style:{color:"#C9D1D9"}}},{content:'"col2"',props:{style:{color:"#A5D6FF"}}},{content:": [",props:{style:{color:"#C9D1D9"}}},{content:"3",props:{style:{color:"#79C0FF"}}},{content:", ",props:{style:{color:"#C9D1D9"}}},{content:"4",props:{style:{color:"#79C0FF"}}},{content:"]})",props:{style:{color:"#C9D1D9"}}}]},{tokens:[{content:" self",props:{style:{color:"#79C0FF"}}},{content:".status ",props:{style:{color:"#C9D1D9"}}},{content:"= f",props:{style:{color:"#FF7B72"}}},{content:'"Built DataFrame with ',props:{style:{color:"#A5D6FF"}}},{content:"{len",props:{style:{color:"#79C0FF"}}},{content:"(df)",props:{style:{color:"#C9D1D9"}}},{content:"}",props:{style:{color:"#79C0FF"}}},{content:' rows."',props:{style:{color:"#A5D6FF"}}}]},{tokens:[{content:" return",props:{style:{color:"#FF7B72"}}},{content:" df",props:{style:{color:"#C9D1D9"}}}]}],lang:"python"},annotations:[]}]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"Output"})," creates a connector point in the visual editor labeled ",(0,s.jsx)(t.strong,{children:"DataFrame Output"}),". The ",(0,s.jsx)(t.code,{children:'name="df_out"'})," parameter identifies this output, while ",(0,s.jsx)(t.code,{children:'display_name="DataFrame Output"'})," shows the label in the UI. The ",(0,s.jsx)(t.code,{children:'method="build_df"'})," parameter tells Langflow to call the ",(0,s.jsx)(t.code,{children:"build_df"})," method when this output is connected to another component."]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"build_df"})," method processes data and returns a ",(0,s.jsx)(t.code,{children:"DataFrame"}),". The ",(0,s.jsx)(t.code,{children:"-> DataFrame"})," type annotation helps Langflow validate connections and provides color-coding in the visual editor. You can also set ",(0,s.jsx)(t.code,{children:"self.status"})," to show progress messages in the UI."]}),"\n",(0,s.jsxs)(t.p,{children:["For a complete list of all available parameters, see the ",(0,s.jsx)(t.a,{href:"https://github.com/langflow-ai/langflow/blob/main/src/lfx/src/lfx/template/field/base.py",children:"Output class definition"})," in the Langflow codebase. Common parameters include:"]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Additional return types:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"Message"})}),": Structured chat messages"]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"Data"})}),": Flexible object with ",(0,s.jsx)(t.code,{children:".data"})," and optional ",(0,s.jsx)(t.code,{children:".text"})]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"DataFrame"})}),": Tabular data (pandas DataFrame subclass)"]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Primitive types"}),": ",(0,s.jsx)(t.code,{children:"str"}),", ",(0,s.jsx)(t.code,{children:"int"}),", ",(0,s.jsx)(t.code,{children:"bool"}),", not recommended for type consistency"]}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"associated-methods",children:"Associated methods"}),"\n",(0,s.jsxs)(t.p,{children:["Each output is linked to a method where the output method name must match the method name. The method typically returns objects like ",(0,s.jsx)(t.code,{children:"Message"}),", ",(0,s.jsx)(t.code,{children:"Data"}),", or ",(0,s.jsx)(t.code,{children:"DataFrame"}),", and can use inputs with ",(0,s.jsx)(t.code,{children:"self.DataFrameProcessor component to the
_10src/lfx/src/lfx/components/_10 └── data/ # Category folder (determines menu location)_10 ├── __init__.py # Required - makes it a Python package_10 └── dataframe_processor.py # Your custom component file
If you're creating custom components in a different location using the LANGFLOW_COMPONENTS_PATH environment variable, components must be similarly organized in a specific directory structure to be displayed in the visual editor.
_10/your/custom/components/path/ # Base directory set by LANGFLOW_COMPONENTS_PATH_10 └── category_name/_10 ├── __init__.py_10 └── custom_component.py
You can have multiple category folders to organize components into different categories:
-
_10/app/custom_components/_10 ├── data/_10 │ ├── __init__.py_10 │ └── dataframe_processor.py_10 └── tools/_10 ├── __init__.py_10 └── custom_tool.py
You can have multiple category folders to organize components into different categories, with multiple components inside each folder:
+
_10/app/custom_components/_10 ├── data/_10 │ ├── __init__.py_10 │ ├── custom_component.py_10 │ └── dataframe_processor.py_10 └── tools/_10 ├── __init__.py_10 └── custom_tool.py
__init__.py file​Each category directory must contain an __init__.py 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.
The Core components and [Bundles] that you see in the Langflow visual editor are automatically included in the base Langflow Docker image.
-If you have any custom components that you created for your application, you must include these components in your application directory:
+The Core components and Bundles that you see in the Langflow visual editor are automatically included in the base Langflow Docker image.
+If you have custom components for your application, include them in your application directory. +Custom components must be placed inside category folders, not directly in the base directory:
/components folder in your application directory./components folder./components in your docker.env.Create a /components folder in your application directory.
Inside /components, create category subfolders (for example, /components/data, /components/tools).
Add your custom component files to the appropriate category folders.
+Copy the /components folder to your Docker image and set the LANGFLOW_COMPONENTS_PATH environment variable:
_10COPY components /app/components_10ENV LANGFLOW_COMPONENTS_PATH=/app/components
The Dockerfile determines how your Langflow image is built, including the dependencies, flows, components, and configuration files.
diff --git a/directory.html b/directory.html index 63ea251d91..ee76c617fc 100644 --- a/directory.html +++ b/directory.html @@ -24,7 +24,7 @@ - + diff --git a/dynamic-create-data.html b/dynamic-create-data.html index 1f833b539b..337168b000 100644 --- a/dynamic-create-data.html +++ b/dynamic-create-data.html @@ -24,7 +24,7 @@ - + diff --git a/enterprise-database-guide.html b/enterprise-database-guide.html index 7dec1f170c..2e3db5786e 100644 --- a/enterprise-database-guide.html +++ b/enterprise-database-guide.html @@ -24,7 +24,7 @@ - + diff --git a/environment-variables.html b/environment-variables.html index bd7bb9eae5..60da1b287c 100644 --- a/environment-variables.html +++ b/environment-variables.html @@ -24,7 +24,7 @@ - + diff --git a/get-started-installation.html b/get-started-installation.html index 3bc0fe2ba3..909e917f98 100644 --- a/get-started-installation.html +++ b/get-started-installation.html @@ -24,7 +24,7 @@ - + diff --git a/get-started-quickstart.html b/get-started-quickstart.html index 9436dee5cd..a86bb802e2 100644 --- a/get-started-quickstart.html +++ b/get-started-quickstart.html @@ -24,7 +24,7 @@ - + diff --git a/if-else.html b/if-else.html index 400a5c19a7..fb82596287 100644 --- a/if-else.html +++ b/if-else.html @@ -24,7 +24,7 @@ - + diff --git a/index.html b/index.html index db7498d03d..8085dd6a99 100644 --- a/index.html +++ b/index.html @@ -24,7 +24,7 @@ - + diff --git a/install-custom-dependencies.html b/install-custom-dependencies.html index b0099b3ca8..ec28190867 100644 --- a/install-custom-dependencies.html +++ b/install-custom-dependencies.html @@ -24,7 +24,7 @@ - + diff --git a/integrations-arize.html b/integrations-arize.html index be85322c89..87df4ccb32 100644 --- a/integrations-arize.html +++ b/integrations-arize.html @@ -24,7 +24,7 @@ - + diff --git a/integrations-instana-traceloop.html b/integrations-instana-traceloop.html index f423319312..5803c1fa01 100644 --- a/integrations-instana-traceloop.html +++ b/integrations-instana-traceloop.html @@ -24,7 +24,7 @@ - + diff --git a/integrations-langfuse.html b/integrations-langfuse.html index f33b2b4fc5..12c144bd3a 100644 --- a/integrations-langfuse.html +++ b/integrations-langfuse.html @@ -24,7 +24,7 @@ - + diff --git a/integrations-langsmith.html b/integrations-langsmith.html index b4b2b45536..3afc68f45f 100644 --- a/integrations-langsmith.html +++ b/integrations-langsmith.html @@ -24,7 +24,7 @@ - + diff --git a/integrations-langwatch.html b/integrations-langwatch.html index 305700f35d..3b5bc13ac5 100644 --- a/integrations-langwatch.html +++ b/integrations-langwatch.html @@ -24,7 +24,7 @@ - + diff --git a/integrations-opik.html b/integrations-opik.html index b655b69c2f..9de5cf08e7 100644 --- a/integrations-opik.html +++ b/integrations-opik.html @@ -24,7 +24,7 @@ - + diff --git a/legacy-core-components.html b/legacy-core-components.html index 56db554138..4acc215ed6 100644 --- a/legacy-core-components.html +++ b/legacy-core-components.html @@ -24,7 +24,7 @@ - + diff --git a/llm-selector.html b/llm-selector.html index fcf73593a7..5c2367b41b 100644 --- a/llm-selector.html +++ b/llm-selector.html @@ -24,7 +24,7 @@ - + diff --git a/logging.html b/logging.html index 80dda2b5a0..90d5fd51b0 100644 --- a/logging.html +++ b/logging.html @@ -24,7 +24,7 @@ - + diff --git a/loop.html b/loop.html index 8c3d629314..6c1590baa8 100644 --- a/loop.html +++ b/loop.html @@ -24,7 +24,7 @@ - + diff --git a/luna-for-langflow.html b/luna-for-langflow.html index a604523c30..80dcf12e95 100644 --- a/luna-for-langflow.html +++ b/luna-for-langflow.html @@ -24,7 +24,7 @@ - + diff --git a/mcp-client.html b/mcp-client.html index 0c9642835c..3e175d136c 100644 --- a/mcp-client.html +++ b/mcp-client.html @@ -24,7 +24,7 @@ - + diff --git a/mcp-component-astra.html b/mcp-component-astra.html index 5876b82a28..0b9074a441 100644 --- a/mcp-component-astra.html +++ b/mcp-component-astra.html @@ -24,7 +24,7 @@ - + diff --git a/mcp-server.html b/mcp-server.html index 9034d9ce85..5fda081004 100644 --- a/mcp-server.html +++ b/mcp-server.html @@ -24,7 +24,7 @@ - + diff --git a/mcp-tools.html b/mcp-tools.html index d225c68620..355d20d31f 100644 --- a/mcp-tools.html +++ b/mcp-tools.html @@ -24,7 +24,7 @@ - + diff --git a/mcp-tutorial.html b/mcp-tutorial.html index 8d099ee2c5..003fdcdf89 100644 --- a/mcp-tutorial.html +++ b/mcp-tutorial.html @@ -24,7 +24,7 @@ - + diff --git a/memory.html b/memory.html index 462c6edf75..6f12e4c8b6 100644 --- a/memory.html +++ b/memory.html @@ -24,7 +24,7 @@ - + diff --git a/message-history.html b/message-history.html index 38d4ca9994..464a998577 100644 --- a/message-history.html +++ b/message-history.html @@ -24,7 +24,7 @@ - + diff --git a/mock-data.html b/mock-data.html index f7e46aca1f..103638f3a0 100644 --- a/mock-data.html +++ b/mock-data.html @@ -24,7 +24,7 @@ - + diff --git a/notify-and-listen.html b/notify-and-listen.html index 9e6cc74155..e3cc58093b 100644 --- a/notify-and-listen.html +++ b/notify-and-listen.html @@ -24,7 +24,7 @@ - + diff --git a/parser.html b/parser.html index d3e7bc0040..7cbc123c89 100644 --- a/parser.html +++ b/parser.html @@ -24,7 +24,7 @@ - + diff --git a/python-interpreter.html b/python-interpreter.html index 3aa5fb09c0..53608f2f69 100644 --- a/python-interpreter.html +++ b/python-interpreter.html @@ -24,7 +24,7 @@ - + diff --git a/read-file.html b/read-file.html index 13c58d8ea5..e5f12b0c7f 100644 --- a/read-file.html +++ b/read-file.html @@ -24,7 +24,7 @@ - + diff --git a/release-notes.html b/release-notes.html index 64cfb30d21..d011da1fea 100644 --- a/release-notes.html +++ b/release-notes.html @@ -24,7 +24,7 @@ - + diff --git a/run-flow.html b/run-flow.html index 33e81ef148..db4b126421 100644 --- a/run-flow.html +++ b/run-flow.html @@ -24,7 +24,7 @@ - + diff --git a/search.html b/search.html index e2a40c6018..d922db4316 100644 --- a/search.html +++ b/search.html @@ -24,7 +24,7 @@ - + diff --git a/security.html b/security.html index 84dffc87f7..e5e9f82a7a 100644 --- a/security.html +++ b/security.html @@ -24,7 +24,7 @@ - + diff --git a/session-id.html b/session-id.html index 425d25ede9..83c87c33ad 100644 --- a/session-id.html +++ b/session-id.html @@ -24,7 +24,7 @@ - + diff --git a/sitemap.xml b/sitemap.xml index de806e3649..9372313899 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1 +1 @@ -