Create custom Python components
Custom components are created within Langflow and extend the platform's functionality with custom, reusable Python code.
-Since Langflow operates with Python behind the scenes, you can implement any Python function within a Custom Component. This means you can leverage the power of libraries such as Pandas, Scikit-learn, Numpy, and thousands of other packages to create components that handle data processing in unlimited ways. You can use any type as long as the type is properly annotated in the output methods (e.g., > list[int]).
Custom Components create reusable and configurable components to enhance the capabilities of Langflow, making it a powerful tool for developing complex processing between user and AI messages.
+Custom components extend Langflow's functionality through Python classes that inherit from Component. This enables integration of new features, data manipulation, external services, and specialized tools.
In Langflow's node-based environment, each node is a "component" that performs discrete functions. Custom components are Python classes which define:
+-
+
- Inputs — Data or parameters your component requires. +
- Outputs — Data your component provides to downstream nodes. +
- Logic — How you process inputs to produce outputs. +
The benefits of creating custom components include unlimited extensibility, reusability, automatic UI field generation based on inputs, and type-safe connections between nodes.
+Create custom components for performing specialized tasks, calling APIs, or adding advanced logic.
+Custom components in Langflow are built upon:
+-
+
- The Python class that inherits from
Component.
+ - Class-level attributes that identify and describe the component. +
- Input and output lists that determine data flow. +
- Internal variables for logging and advanced logic. +
Class-level attributes​
+Define these attributes to control a custom component's appearance and behavior:
+
_10class MyCsvReader(Component):_10 display_name = "CSV Reader" # Shown in node header_10 description = "Reads CSV files" # Tooltip text_10 icon = "file-text" # Visual identifier_10 name = "CSVReader" # Unique internal ID_10 documentation = "http://docs.example.com/csv_reader" # Optional
-
+
- display_name: A user-friendly label in the node header. +
- description: A brief summary shown in tooltips. +
- icon: A visual identifier from Langflow's icon library. +
- name: A unique internal identifier. +
- documentation: An optional link to external docs. +
Structure of a custom component​
+A Langflow custom component goes beyond a simple class with inputs and outputs. It includes an internal structure with optional lifecycle steps, output generation, front-end interaction, and logic organization.
+A basic component:
+-
+
- Inherits from
langflow.custom.Component.
+ - Declares metadata like
display_name,description,icon, and more.
+ - Defines
inputsandoutputslists.
+ - Implements methods matching output specifications. +
A minimal custom component skeleton contains the following:
+
_14from langflow.custom import Component_14from langflow.template import Output_14_14class MyComponent(Component):_14 display_name = "My Component"_14 description = "A short summary."_14 icon = "sparkles"_14 name = "MyComponent"_14_14 inputs = []_14 outputs = []_14_14 def some_output_method(self):_14 return ...
Internal Lifecycle and Execution Flow​
+Langflow's engine manages:
+-
+
- Instantiation: A component is created and internal structures are initialized. +
- Assigning Inputs: Values from the UI or connections are assigned to component fields. +
- Validation and Setup: Optional hooks like
_pre_run_setup.
+ - Outputs Generation:
run()orbuild_results()triggers output methods.
+
Optional Hooks:
+-
+
initialize_dataor_pre_run_setupcan run setup logic before the component's main execution.
+__call__,run(), or_run()can be overridden to customize how the component is called or to define custom execution logic.
+
Inputs and outputs​
+Custom component inputs are defined with properties like:
+-
+
name,display_name
+- Optional:
info,value,advanced,is_list,tool_mode,real_time_refresh
+
For example:
+-
+
StrInput: simple text input.
+DropdownInput: selectable options.
+HandleInput: specialized connections.
+
Custom component Output properties define:
-
+
name,display_name,method
+- Optional:
info
+
For more information, see Custom component inputs and outputs.
+Associated Methods​
+Each output is linked to a method:
+-
+
- The output method name must match the method name. +
- The method typically returns objects like Message, Data, or DataFrame. +
- The method can use inputs with
self.<input_name>.
+
For example:
+
_12Output(_12 display_name="File Contents",_12 name="file_contents",_12 method="read_file"_12)_12#..._12def read_file(self) -> Data:_12 path = self.filename_12 with open(path, "r") as f:_12 content = f.read()_12 self.status = f"Read {len(content)} chars from {path}"_12 return Data(data={"content": content})
Components with multiple outputs​
+A component can define multiple outputs. +Each output can have a different corresponding method. +For example:
+
_10outputs = [_10 Output(display_name="Processed Data", name="processed_data", method="process_data"),_10 Output(display_name="Debug Info", name="debug_info", method="provide_debug_info"),_10]
Common internal patterns​
+_pre_run_setup()​
+To initialize a custom component with counters set:
+
_10def _pre_run_setup(self):_10 if not hasattr(self, "_initialized"):_10 self._initialized = True_10 self.iteration = 0
Override run or _run​
+You can override async def _run(self): ... to define custom execution logic, although the default behavior from the base class usually covers most cases.
Store data in self.ctx​
+Use self.ctx as a shared storage for data or counters across the component's execution flow:
_10def some_method(self):_10 count = self.ctx.get("my_count", 0)_10 self.ctx["my_count"] = count + 1
Directory structure requirements​
By default, Langflow looks for custom components in the langflow/components directory.
If you're creating custom components in a different location using the LANGFLOW_COMPONENTS_PATH
-LANGFLOW_COMPONENTS_PATH environment variable, components must be organized in a specific directory structure to be properly loaded and displayed in the UI:
_10/your/custom/components/path/ # Base directory (set by LANGFLOW_COMPONENTS_PATH)_10 └ ── category_name/ # Required category subfolder (determines menu name)_10 └── custom_component.py # Component file
If you're creating custom components in a different location using the LANGFLOW_COMPONENTS_PATH environment variable, components must be organized in a specific directory structure to be properly loaded and displayed in the UI:
+
_10/your/custom/components/path/ # Base directory set by LANGFLOW_COMPONENTS_PATH_10 └── category_name/ # Required category subfolder that determines menu name_10 └── custom_component.py # Component file
Components must be placed inside category folders, not directly in the base directory. The category folder name determines where the component appears in the UI menu.
For example, to add a component to the Helpers menu, place it in a helpers subfolder:
_10/app/custom_components/ # LANGFLOW_COMPONENTS_PATH_10 └── helpers/ # Shows up as "Helpers" menu_10 └── custom_component.py # Your component
_10/app/custom_components/ # LANGFLOW_COMPONENTS_PATH_10 └── helpers/ # Displayed within the "Helpers" menu_10 └── custom_component.py # Your component
You can have multiple category folders to organize components into different menus:
_10/app/custom_components/_10 ├── helpers/_10 │ └── helper_component.py_10 └── tools/_10 └── tool_component.py
This folder structure is required for Langflow to properly discover and load your custom components. Components placed directly in the base directory will not be loaded.
_10/app/custom_components/ # LANGFLOW_COMPONENTS_PATH_10 └── custom_component.py # Won't be loaded - missing category folder!
Create a custom component in Langflow​
-Creating custom components in Langflow involves creating a Python class that defines the component's functionality, inputs, and outputs. -The default code provides a working structure for your custom component.
-
_25# from langflow.field_typing import Data_25from langflow.custom import Component_25from langflow.io import MessageTextInput, Output_25from langflow.schema import Data_25_25_25class CustomComponent(Component):_25 display_name = "Custom Component"_25 description = "Use as a template to create your own component."_25 documentation: str = "https://docs.langflow.org/components-custom-components"_25 icon = "custom_components"_25 name = "CustomComponent"_25_25 inputs = [_25 MessageTextInput(name="input_value", display_name="Input Value", value="Hello, World!"),_25 ]_25_25 outputs = [_25 Output(display_name="Output", name="output", method="build_output"),_25 ]_25_25 def build_output(self) -> Data:_25 data = Data(value=self.input_value)_25 self.status = data_25 return data
You can create your class in your favorite text editor outside of Langflow and paste it in later, or just follow along in the code pane.
--
-
- In Langflow, click + Custom Component to add a custom component into the workspace. -
- Open the component's code pane. -
- Import dependencies.
-Your custom component inherits from the langflow
Componentclass so you need to include it.
-
_10from langflow.custom import Component_10from langflow.io import MessageTextInput, Output_10from langflow.schema import Data
-
-
- Define the Class: Start by defining a Python class that inherits fromÂ
Component. This class will encapsulate the functionality of your custom component.
-
_10class CustomComponent(Component):_10 display_name = "Custom Component"_10 description = "Use as a template to create your own component."_10 documentation: str = "https://docs.langflow.org/components-custom-components"_10 icon = "custom_components"_10 name = "CustomComponent"
-
-
- Specify Inputs and Outputs: Use Langflow's input and output classes to define the inputs and outputs of your component. They should be declared as class attributes. -
_10 inputs = [_10 MessageTextInput(name="input_value", display_name="Input Value", value="Hello, World!"),_10 ]_10_10 outputs = [_10 Output(display_name="Output", name="output", method="build_output"),_10 ]
-
-
- Implement Output Methods: Implement methods for each output, which contains the logic of your component. These methods can access input values usingÂ
self.<input_name>, return processed values and define what to be displayed in the component with theÂself.status attribute.
-
_10 def build_output(self) -> Data:_10 data = Data(value=self.input_value)_10 self.status = data_10 return data
-
-
- Use Proper Annotations: Ensure that output methods are properly annotated with their types. Langflow uses these annotations to validate and handle data correctly. For example, this method is annotated to output
Data.
-
_10 def build_output(self) -> Data:
-
-
- Click Check & Save to confirm your component works. -You now have an operational custom component. -
Add inputs and modify output methods​
-This code defines a custom component that accepts 5 inputs and outputs a Message.
-Copy and paste it into the Custom Component code pane and click Check & Save.
-
_55from langflow.custom import Component_55from langflow.inputs import StrInput, MultilineInput, SecretStrInput, IntInput, DropdownInput_55from langflow.template import Output, Input_55from langflow.schema.message import Message_55_55class MyCustomComponent(Component):_55 display_name = "My Custom Component"_55 description = "An example of a custom component with various input types."_55_55 inputs = [_55 StrInput(_55 name="username",_55 display_name="Username",_55 info="Enter your username."_55 ),_55 SecretStrInput(_55 name="password",_55 display_name="Password",_55 info="Enter your password."_55 ),_55 MessageTextInput(_55 name="special_message",_55 display_name="special_message",_55 info="Enter a special message.",_55 ),_55 IntInput(_55 name="age",_55 display_name="Age",_55 info="Enter your age."_55 ),_55 DropdownInput(_55 name="gender",_55 display_name="Gender",_55 options=["Male", "Female", "Other"],_55 info="Select your gender."_55 )_55 ]_55_55 outputs = [_55 Output(display_name="Result", name="result", method="process_inputs"),_55 ]_55_55 def process_inputs(self) -> Message:_55 """_55 Process the user inputs and return a Message object._55_55 Returns:_55 Message: A Message object containing the processed information._55 """_55 try:_55 processed_text = f"User {self.username} (Age: {self.age}, Gender: {self.gender}) " \_55 f"sent the following special message: {self.special_message}"_55 return Message(text=processed_text)_55 except AttributeError as e:_55 return Message(text=f"Error processing inputs: {str(e)}")
Since the component outputs a Message, you can wire it into a chat and pass messages to yourself.
Your Custom Component accepts the Chat Input message through MessageTextInput, fills in the variables with the process_inputs method, and finally passes the message User Username (Age: 49, Gender: Male) sent the following special message: Hello! to Chat Output.
By defining inputs this way, Langflow can automatically handle the validation and display of these fields in the user interface, making it easier to create robust and user-friendly custom components.
-All of the types detailed above derive from a general class that can also be accessed through the generic Input class.
Use MessageInput to get the entire Message object instead of just the text.
Input Types​
--
Langflow provides several higher-level input types to simplify the creation of custom components. These input types standardize how inputs are defined, validated, and used. Here’s a guide on how to use these inputs and their primary purposes:
-HandleInput​
-Represents an input that has a handle to a specific type (e.g., BaseLanguageModel, BaseRetriever, etc.).
Custom component inputs and outputs​
+Inputs and outputs define how data flows through the component, how it appears in the UI, and how connections to other components are validated.
+Inputs​
+Inputs are defined in a class-level inputs list. When Langflow loads the component, it uses this list to render fields and handles in the UI. Users or other components provide values or connections to fill these inputs.
An input is usually an instance of a class from langflow.io (such as StrInput, DataInput, or MessageTextInput). The most common constructor parameters are:
-
-
- Usage:Â Useful for connecting to specific component types in a flow. +
name: The internal variable name, accessed viaself.<name>.
+display_name: The label shown to users in the UI.
+info(optional): A tooltip or short description.
+value(optional): The default value.
+advanced(optional): IfTrue, moves the field into the "Advanced" section.
+required(optional): IfTrue, forces the user to provide a value.
+is_list(optional): IfTrue, allows multiple values.
+input_types(optional): Restricts allowed connection types (e.g.,["Data"],["LanguageModel"]).
DataInput​
-Represents an input that receives a Data object.
Here are the most commonly used input classes and their typical usage.
+Text Inputs: For simple text entries.
-
-
- Usage:Â Ideal for components that process or manipulate data objects. -
- Input Types:Â
["Data"]
+ StrInputcreates a single-line text field.
+MultilineInputcreates a multi-line text area.
StrInput​
-Represents a standard string input field.
+Numeric and Boolean Inputs: Ensures users can only enter valid numeric or boolean data.
-
-
- Usage:Â Used for any text input where the user needs to provide a string. -
- Input Types:Â
["Text"]
+ BoolInput,IntInput, andFloatInputprovide fields for boolean, integer, and float values, ensuring type consistency.
MessageInput​
-Represents an input field specifically for Message objects.
Dropdowns: For selecting from predefined options, useful for modes or levels.
-
-
- Usage:Â Used in components that handle or process messages. -
- Input Types:Â
["Message"]
+ DropdownInput
MessageTextInput​
-Represents a text input for messages.
+Secrets: A specialized input for sensitive data, ensuring input is hidden in the UI.
-
-
- Usage:Â Suitable for components that need to extract text from message objects. -
- Input Types:Â
["Message"]
+ SecretStrInputfor API keys and passwords.
MultilineInput​
-Represents a text field that supports multiple lines.
+Specialized Data Inputs: Ensures type-checking and color-coded connections in the UI.
-
-
- Usage:Â Ideal for longer text inputs where the user might need to write extended text. -
- Input Types:Â
["Text"]
- - Attributes:Â
multiline=True
+ DataInputexpects aDataobject (typically with.dataand optional.text).
+MessageInputexpects aMessageobject, used in chat or agent-based flows.
+MessageTextInputsimplifies access to the.textfield of aMessage.
SecretStrInput​
-Represents a password input field.
+Handle-Based Inputs: Used to connect outputs of specific types, ensuring correct pipeline connections.
-
-
- Usage:Â Used for sensitive text inputs where the input should be hidden (e.g., passwords, API keys). -
- Attributes:Â
password=True
- - Input Types:Â Does not accept input types, meaning it has no input handles for previous nodes/components to connect to it. +
HandleInput
IntInput​
-Represents an integer input field.
+File Uploads: Allows users to upload files directly through the UI or receive file paths from other components.
-
-
- Usage:Â Used for numeric inputs where the value should be an integer. -
- Input Types:Â
["Integer"]
+ FileInput
FloatInput​
-Represents a float input field.
+Lists: Set is_list=True to accept multiple values, ideal for batch or grouped operations.
This example defines three inputs: a text field (StrInput), a boolean toggle (BoolInput), and a dropdown selection (DropdownInput).
_10from langflow.io import StrInput, BoolInput, DropdownInput_10_10inputs = [_10 StrInput(name="title", display_name="Title"),_10 BoolInput(name="enabled", display_name="Enabled", value=True),_10 DropdownInput(name="mode", display_name="Mode", options=["Fast", "Safe", "Experimental"], value="Safe")_10]
Outputs​
+Outputs are defined in a class-level outputs list. When Langflow renders a component, each output becomes a connector point in the UI. When you connect something to an output, Langflow automatically calls the corresponding method and passes the returned object to the next component.
An output is usually an instance of Output from langflow.io, with common parameters:
-
-
- Usage:Â Used for numeric inputs where the value should be a floating-point number. -
- Input Types:Â
["Float"]
+ name: The internal variable name.
+display_name: The label shown in the UI.
+method: The name of the method called to produce the output.
+info(optional): Help text shown on hover.
BoolInput​
-Represents a boolean input field.
+The method must exist in the class, and it is recommended to annotate its return type for better type checking.
+You can also set a self.status message inside the method to show progress or logs.
Common Return Types:
-
-
- Usage:Â Used for true/false or yes/no type inputs. -
- Input Types:Â
["Boolean"]
+ Message: Structured chat messages.
+Data: Flexible object with.dataand optional.text.
+DataFrame: Pandas-based tables (langflow.schema.DataFrame).
+- Primitive types:
str,int,bool(not recommended if you need type/color consistency).
NestedDictInput​
-Represents an input field for nested dictionaries.
+In this example, the DataToDataFrame component defines its output using the outputs list. The df_out output is linked to the build_df method, so when connected in the UI, Langflow calls this method and passes its returned DataFrame to the next node. This demonstrates how each output maps to a method that generates the actual output data.
_37from langflow.custom import Component_37from langflow.io import DataInput, Output_37from langflow.schema import Data, DataFrame_37_37class DataToDataFrame(Component):_37 display_name = "Data to DataFrame"_37 description = "Convert multiple Data objects into a DataFrame"_37 icon = "table"_37 name = "DataToDataFrame"_37_37 inputs = [_37 DataInput(_37 name="items",_37 display_name="Data Items",_37 info="List of Data objects to convert",_37 is_list=True_37 )_37 ]_37_37 outputs = [_37 Output(_37 name="df_out",_37 display_name="DataFrame Output",_37 method="build_df"_37 )_37 ]_37_37 def build_df(self) -> DataFrame:_37 rows = []_37 for item in self.items:_37 row_dict = item.data.copy() if item.data else {}_37 row_dict["text"] = item.get_text() or ""_37 rows.append(row_dict)_37_37 df = DataFrame(rows)_37 self.status = f"Built DataFrame with {len(rows)} rows."_37 return df
Tool mode​
+You can configure a Custom Component to work as a Tool by setting the parameter tool_mode=True. This allows the component to be used in Langflow's Tool Mode workflows, such as by Agent components.
Langflow currently supports the following input types for Tool Mode:
-
-
- Usage:Â Used for more complex data structures where the input needs to be a dictionary. -
- Input Types:Â
["NestedDict"]
+ DataInput
+DataFrameInput
+PromptInput
+MessageTextInput
+MultilineInput
+DropdownInput
DictInput​
-Represents an input field for dictionaries.
+
_10inputs = [_10 MessageTextInput(_10 name="message",_10 display_name="Mensage",_10 info="Enter the message that will be processed directly by the tool",_10 tool_mode=True,_10 ),_10]
Typed annotations​
+In Langflow, typed annotations allow Langflow to visually guide users and maintain flow consistency.
+Typed annotations provide:
-
-
- Usage:Â Suitable for inputs that require a dictionary format. -
- Input Types:Â
["Dict"]
+ - Color-coding: Outputs like
-> Dataor-> Messageget distinct colors.
+ - Validation: Langflow blocks incompatible connections automatically. +
- Readability: Developers can quickly understand data flow. +
- Development tools: Better code suggestions and error checking in your code editor.
DropdownInput​
-Represents a dropdown input field.
+Common Return Types​
+Message
For chat-style outputs.
+
_10def produce_message(self) -> Message:_10 return Message(text="Hello! from typed method!", sender="System")
In the UI, connects only to Message-compatible inputs.
+Data
For structured data like dicts or partial texts.
+
_10def get_processed_data(self) -> Data:_10 processed = {"key1": "value1", "key2": 123}_10 return Data(data=processed)
In the UI, connects only with DataInput.
+DataFrame
For tabular data
+
_10def build_df(self) -> DataFrame:_10 pdf = pd.DataFrame({"A": [1, 2], "B": [3, 4]})_10 return DataFrame(pdf)
In the UI, connects only to DataFrameInput.
+Primitive Types (str, int, bool)
Returning primitives is allowed but wrapping in Data or Message is recommended for better UI consistency.
+
_10def compute_sum(self) -> int:_10 return sum(self.numbers)
Tips for typed annotations​
+When using typed annotations, consider the following best practices:
-
-
- Usage:Â Used where the user needs to select from a predefined list of options. -
- Attributes:Â
options to define the list of selectable options.
- - Input Types:Â
["Text"]
+ - Always Annotate Outputs: Specify return types like
-> Data,-> Message, or-> DataFrameto enable proper UI color-coding and validation.
+ - Wrap Raw Data: Use
Data,Message, orDataFramewrappers instead of returning plain structures.
+ - Use Primitives Carefully: Direct
strorintreturns are fine for simple flows, but wrapping improves flexibility.
+ - Annotate Helpers Too: Even if internal, typing improves maintainability and clarity. +
- Handle Edge Cases: Prefer returning structured
Datawith error fields when needed.
+ - Stay Consistent: Use the same types across your components to make flows predictable and easier to build.
FileInput​
-Represents a file input field.
--
-
- Usage:Â Used to upload files. -
- Attributes:Â
file_types to specify the types of files that can be uploaded.
- - Input Types:Â
["File"]
-
Generic Input​
--
Langflow offers native input types, but you can use any type as long as they are properly annotated in the output methods (e.g., -> list[int]).
The Input class is highly customizable, allowing you to specify a wide range of attributes for each input field. It has several attributes that can be customized:
-
-
field_type: Specifies the type of field (e.g.,Âstr,Âint). Default isÂstr.
-required: Boolean indicating if the field is required. Default isÂFalse.
-placeholder: Placeholder text for the input field. Default is an empty string.
-is_list: Boolean indicating if the field should accept a list of values. Default isÂFalse.
-show: Boolean indicating if the field should be shown. Default isÂTrue.
-multiline: Boolean indicating if the field should allow multi-line input. Default isÂFalse.
-value: Default value for the input field. Default isÂNone.
-file_types: List of accepted file types (for file inputs). Default is an empty list.
-file_path: File path if the field is a file input. Default isÂNone.
-password: Boolean indicating if the field is a password. Default isÂFalse.
-options: List of options for the field (for dropdowns). Default isÂNone.
-name: Name of the input field. Default isÂNone.
-display_name: Display name for the input field. Default isÂNone.
-advanced: Boolean indicating if the field is an advanced parameter. Default isÂFalse.
-input_types: List of accepted input types. Default isÂNone.
-dynamic: Boolean indicating if the field is dynamic. Default isÂFalse.
-info: Additional information or tooltip for the input field. Default is an empty string.
-real_time_refresh: Boolean indicating if the field should refresh in real-time. Default isÂNone.
-refresh_button: Boolean indicating if the field should have a refresh button. Default isÂNone.
-refresh_button_text: Text for the refresh button. Default isÂNone.
-range_spec: Range specification for numeric fields. Default isÂNone.
-load_from_db: Boolean indicating if the field should load from the database. Default isÂFalse.
-title_case: Boolean indicating if the display name should be in title case. Default isÂTrue.
-
Create a Custom Component with Generic Input​
-Here is an example of how to define inputs for a component using the Input class.
Copy and paste it into the Custom Component code pane and click Check & Save.
-
_76from langflow.template import Input, Output_76from langflow.custom import Component_76from langflow.field_typing import Text_76from langflow.schema.message import Message_76from typing import Dict, Any_76_76class TextAnalyzerComponent(Component):_76 display_name = "Text Analyzer"_76 description = "Analyzes input text and provides basic statistics."_76_76 inputs = [_76 Input(_76 name="input_text",_76 display_name="Input Text",_76 field_type="Message",_76 required=True,_76 placeholder="Enter text to analyze",_76 multiline=True,_76 info="The text you want to analyze.",_76 input_types=["Text"]_76 ),_76 Input(_76 name="include_word_count",_76 display_name="Include Word Count",_76 field_type="bool",_76 required=False,_76 info="Whether to include word count in the analysis.",_76 ),_76 Input(_76 name="perform_sentiment_analysis",_76 display_name="Perform Sentiment Analysis",_76 field_type="bool",_76 required=False,_76 info="Whether to perform basic sentiment analysis.",_76 ),_76 ]_76_76 outputs = [_76 Output(display_name="Analysis Results", name="results", method="analyze_text"),_76 ]_76_76 def analyze_text(self) -> Message:_76 # Extract text from the Message object_76 if isinstance(self.input_text, Message):_76 text = self.input_text.text_76 else:_76 text = str(self.input_text)_76_76 results = {_76 "character_count": len(text),_76 "sentence_count": text.count('.') + text.count('!') + text.count('?')_76 }_76_76 if self.include_word_count:_76 results["word_count"] = len(text.split())_76_76 if self.perform_sentiment_analysis:_76 # Basic sentiment analysis_76 text_lower = text.lower()_76 if "happy" in text_lower or "good" in text_lower:_76 sentiment = "positive"_76 elif "sad" in text_lower or "bad" in text_lower:_76 sentiment = "negative"_76 else:_76 sentiment = "neutral"_76_76 results["sentiment"] = sentiment_76_76 # Convert the results dictionary to a formatted string_76 formatted_results = "\n".join([f"{key}: {value}" for key, value in results.items()])_76_76 # Return a Message object_76 return Message(text=formatted_results)_76_76# Define how to use the inputs and outputs_76component = TextAnalyzerComponent()
In this custom component:
+Enable dynamic fields​
+In Langflow, dynamic fields allow inputs to change or appear based on user interactions. You can make an input dynamic by setting dynamic=True.
+Optionally, setting real_time_refresh=True triggers the update_build_config method to adjust the input's visibility or properties in real time, creating a contextual UI that only displays relevant fields based on the user's choices.
In this example, the operator field triggers updates via real_time_refresh=True.
+The regex_pattern field is initially hidden and controlled via dynamic=True.
_22from langflow.io import DropdownInput, StrInput_22_22class RegexRouter(Component):_22 display_name = "Regex Router"_22 description = "Demonstrates dynamic fields for regex input."_22_22 inputs = [_22 DropdownInput(_22 name="operator",_22 display_name="Operator",_22 options=["equals", "contains", "regex"],_22 value="equals",_22 real_time_refresh=True,_22 ),_22 StrInput(_22 name="regex_pattern",_22 display_name="Regex Pattern",_22 info="Used if operator='regex'",_22 dynamic=True,_22 show=False,_22 ),_22 ]
Implement update_build_config​
+When a field with real_time_refresh=True is modified, Langflow calls the update_build_config method, passing the updated field name, value, and the component's configuration to dynamically adjust the visibility or properties of other fields based on user input.
This example will show or hide the regex_pattern field when the user selects a different operator.
_10def update_build_config(self, build_config: dict, field_value: str, field_name: str | None = None) -> dict:_10 if field_name == "operator":_10 if field_value == "regex":_10 build_config["regex_pattern"]["show"] = True_10 else:_10 build_config["regex_pattern"]["show"] = False_10 return build_config
Additional Dynamic Field Controls​
+You can also modify other properties within update_build_config, such as:
-
-
The
+input_textinput is a required multi-line text field that accepts a Message object or a string. It's used to provide the text for analysis.required: Setbuild_config["some_field"]["required"] = True/False -
-
The
+include_word_countinput is an optional boolean field. When set to True, it adds a word count to the analysis results.advanced: Setbuild_config["some_field"]["advanced"] = True -
-
The
+perform_sentiment_analysisinput is an optional boolean field. When set to True, it triggers a basic sentiment analysis of the input text.options: Modify dynamic dropdown options.
The component performs basic text analysis, including character count and sentence count (based on punctuation marks). If word count is enabled, it splits the text and counts the words. If sentiment analysis is enabled, it performs a simple keyword-based sentiment classification (positive, negative, or neutral).
-Since the component inputs and outputs a Message, you can wire the component into a chat and see how the basic custom component logic interacts with your input.
Create a Custom Component with Multiple Outputs​
--
In Langflow, custom components can have multiple outputs. Each output can be associated with a specific method in the component, allowing you to define distinct behaviors for each output path. This feature is particularly useful when you want to route data based on certain conditions or process it in multiple ways.
--
-
- Definition of Outputs: Each output is defined in theÂ
outputs list of the component. Each output is associated with a display name, an internal name, and a method that gets called to generate the output.
- - Output Methods: The methods associated with outputs are responsible for generating the data for that particular output. These methods are called when the component is executed, and each method can independently produce its result. -
This example component has two outputs:
+Tips for Managing Dynamic Fields​
+When working with dynamic fields, consider the following best practices to ensure a smooth user experience:
-
-
process_data: Processes the input text (e.g., converts it to uppercase) and returns it.
-get_processing_function: Returns theÂprocess_data method itself to be reused in composition.
+- Minimize field changes: Hide only fields that are truly irrelevant to avoid confusing users. +
- Test behavior: Ensure that adding or removing fields doesn't accidentally erase user input. +
- Preserve data: Use
build_config["some_field"]["show"] = Falseto hide fields without losing their values.
+ - Clarify logic: Add
infonotes to explain why fields appear or disappear based on conditions.
+ - Keep it manageable: If the dynamic logic becomes too complex, consider breaking it into smaller components, unless it serves a clear purpose in a single node.
_33from typing import Callable_33from langflow.custom import Component_33from langflow.inputs import StrInput_33from langflow.template import Output_33from langflow.field_typing import Text_33_33class DualOutputComponent(Component):_33 display_name = "Dual Output"_33 description = "Processes input text and returns both the result and the processing function."_33 icon = "double-arrow"_33_33 inputs = [_33 StrInput(_33 name="input_text",_33 display_name="Input Text",_33 info="The text input to be processed.",_33 ),_33 ]_33_33 outputs = [_33 Output(display_name="Processed Data", name="processed_data", method="process_data"),_33 Output(display_name="Processing Function", name="processing_function", method="get_processing_function"),_33 ]_33_33 def process_data(self) -> Text:_33 # Process the input text (e.g., convert to uppercase)_33 processed = self.input_text.upper()_33 self.status = processed_33 return processed_33_33 def get_processing_function(self) -> Callable[[], Text]:_33 # Return the processing function itself_33 return self.process_data
This example shows how to define multiple outputs in a custom component. The first output returns the processed data, while the second output returns the processing function itself.
-The processing_function output can be used in scenarios where the function itself is needed for further processing or dynamic flow control. Notice how both outputs are properly annotated with their respective types, ensuring clarity and type safety.
Special Operations​
-Advanced methods and attributes offer additional control and functionality. Understanding how to leverage these can enhance your custom components' capabilities.
+Error handling and logging​
+In Langflow, robust error handling ensures that your components behave predictably, even when unexpected situations occur, such as invalid inputs, external API failures, or internal logic errors.
+Error handling techniques​
-
-
self.inputs: Access all defined inputs. Useful when an output method needs to interact with multiple inputs.
-self.outputs: Access all defined outputs. This is particularly useful if an output function needs to trigger another output function.
-self.status: Use this to update the component's status or intermediate results. It helps track the component's internal state or store temporary data.
-self.graph.flow_id: Retrieve the flow ID, useful for maintaining context or debugging.
-self.stop("output_name"): Use this method within an output function to prevent data from being sent through other components. This method stops next component execution and is particularly useful for specific operations where a component should stop from running based on specific conditions.
+- Raise Exceptions:
+If a critical error occurs, you can raise standard Python exceptions such as
ValueError, or specialized exceptions likeToolException. Langflow will automatically catch these and display appropriate error messages in the UI, helping users quickly identify what went wrong. ++_10def compute_result(self) -> str:_10if not self.user_input:_10raise ValueError("No input provided.")_10# ...
+ - Return Structured Error Data:
+Instead of stopping a flow abruptly, you can return a Data object containing an "error" field. This approach allows the flow to continue operating and enables downstream components to detect and handle the error gracefully.
++_10def run_model(self) -> Data:_10try:_10# ..._10except Exception as e:_10return Data(data={"error": str(e)})
Contribute Custom Components to Langflow​
-See How to Contribute to contribute your custom component to Langflow.