This page describes how to write custom components for Langflow: the base classes to subclass, how to declare inputs and outputs, how the build method is invoked by the execution engine, and how custom component files are discovered at startup.
For the overall component lifecycle and how built-in components are registered, see Component Lifecycle. For the full catalog of input types and their mixin architecture, see Input Type System. For how components are discovered and loaded from the filesystem at server startup, see Component Loading.
All components in Langflow are Python classes that inherit from one of two base classes. Both live in the lfx package and are re-exported through langflow for backward compatibility.
| Class | Import path | Usage |
|---|---|---|
Component | langflow.custom.custom_component.component (re-exports from lfx) | Modern style. Outputs are declared via outputs list and resolved by method name. |
CustomComponent | langflow.custom.custom_component.custom_component (re-exports from lfx) | Legacy style. Requires a single build() method. |
The re-export wrapper files are:
Prefer Component for all new development. The engine handles both via the union type CustomComponent | Component in the loading layer.
Diagram: Base Class Hierarchy
Sources: src/backend/base/langflow/custom/custom_component/component.py src/backend/base/langflow/interface/initialize/loading.py
Inputs are declared as class-level attributes using typed input classes imported from langflow.inputs or langflow.io. Each input class is a thin wrapper that carries metadata used both for execution and for driving the frontend UI.
Available input types:
| Input Class | Data type | Notes |
|---|---|---|
StrInput | str | Single-line text |
MultilineInput | str | Multi-line text area |
SecretStrInput | str | Password-masked, stored encrypted |
MultilineSecretInput | str | Multi-line secret |
BoolInput | bool | Toggle switch |
IntInput | int | Integer field |
FloatInput | float | Float field |
DropdownInput | str | Single-select dropdown with options |
MultiselectInput | list[str] | Multi-select |
MessageInput | Message | Accepts a connected Message object |
MessageTextInput | str | Text content of a Message |
DataInput | Data | Accepts a connected Data object |
DataFrameInput | DataFrame | Pandas DataFrame |
HandleInput | connection | Typed connection port |
ModelInput | LLM model | Connects to a model component |
PromptInput | str | Prompt with variable highlighting |
CodeInput | str | Monaco-editor code field |
FileInput | file path | File upload |
DictInput | dict | Key-value dict |
NestedDictInput | dict | Hierarchical dict |
TableInput | list[dict] | Tabular data |
SliderInput | float | Slider with range_spec |
TabInput | str | Tab selector |
ToolsInput | tools list | Tools for agents |
McpInput | MCP config | MCP server configuration |
AuthInput | credentials | Authentication config |
LinkInput | URL | Clickable link field |
All types are importable from:
langflow.inputs — src/backend/base/langflow/inputs/__init__.pylangflow.io — src/backend/base/langflow/io/__init__.pylangflow.inputs.inputs (full list) — src/backend/base/langflow/inputs/inputs.pyDiagram: Input class and mixin relationships (code entity view)
Sources: src/backend/base/langflow/inputs/input_mixin.py src/backend/base/langflow/inputs/inputs.py
Outputs are declared in a class-level outputs list using Output objects imported from langflow.io or lfx.template.
Each Output specifies:
| Field | Purpose |
|---|---|
name | Internal identifier, also used to call the matching method |
display_name | Human-readable label shown in the UI |
method | Name of the Python method on the component to invoke |
type | Return type annotation string (e.g. "Message", "Data", "str") |
required | Whether this output must be connected |
The execution engine resolves which output method to call based on which output port is connected by edges in the flow graph.
Sources: src/backend/base/langflow/io/__init__.py src/backend/base/langflow/interface/initialize/loading.py147-155
Component subclass)class MyComponent(Component):
display_name = "My Component"
description = "Does something useful."
icon = "tool"
inputs = [
MessageTextInput(name="input_text", display_name="Input"),
StrInput(name="prefix", display_name="Prefix", value="Hello"),
]
outputs = [
Output(name="output", display_name="Output", method="process"),
]
def process(self) -> Message:
return Message(text=self.prefix + " " + self.input_text)
Key points:
self.<name> after set_attributes() is called by the engine.type field.async.build_results() is called by the engine and dispatches to the appropriate output method based on connected edges.CustomComponent subclass)class MyLegacyComponent(CustomComponent):
display_name = "Legacy Component"
def build(self, input_text: str) -> str:
return input_text.upper()
The build() method receives input values as keyword arguments. The engine inspects its signature and passes matching parameters directly.
Sources: src/backend/base/langflow/interface/initialize/loading.py147-202
The diagram below maps the execution path from flow run request to component output, referencing the actual functions involved.
Diagram: Component instantiation and build sequence
Sources: src/backend/base/langflow/interface/initialize/loading.py25-202
update_build_config)A component can define an update_build_config method to change the configuration of its fields dynamically when a field value changes in the UI. This is called via the POST /api/v1/custom_component/update endpoint.
def update_build_config(self, build_config: dict, field_value: Any, field_name: str) -> dict:
if field_name == "model_name":
build_config["api_key"]["required"] = True
return build_config
The engine calls update_component_build_config from lfx.custom.utils, which is imported in the API layer at src/backend/base/langflow/api/v1/endpoints.py17-22
The UpdateCustomComponentRequest schema carries field, field_value, and template — the full current template — so the component can make decisions about other fields based on existing values.
Sources: src/backend/base/langflow/api/v1/schemas.py204-211 src/backend/base/langflow/api/v1/endpoints.py17-22
Input fields marked with SecretStrInput or load_from_db=True are resolved through the variable service at build time via update_params_with_load_from_db_fields. The component can also look up variables explicitly using self.get_variable(name, field, session).
The resolution order when fallback_to_env_vars=True is set:
Sources: src/backend/base/langflow/interface/initialize/loading.py111-144
COMPONENTS_PATHLangflow discovers custom components from additional directories specified in the LANGFLOW_COMPONENTS_PATH environment variable (a colon-separated list of paths). At server startup, the component loading system scans these directories for Python files, evaluates each one, and registers any Component or CustomComponent subclasses found.
Diagram: Component discovery and registration flow
When a component file is loaded:
eval_custom_component_code(code) executes the string in a sandboxed scope and returns the class object.inputs, outputs, display_name, description, and icon.build_custom_component_template from lfx.custom.utils.GET /api/v1/all.Sources: src/backend/base/langflow/interface/initialize/loading.py25-51 src/backend/base/langflow/api/v1/endpoints.py97-111
The frontend uses two endpoints when a user edits component code in the code editor:
| Method | Endpoint | Purpose |
|---|---|---|
POST | /api/v1/custom_component | Validate code and return a frontend template |
POST | /api/v1/custom_component/update | Update a field's build config after a value changes |
Both endpoints are defined in src/backend/base/langflow/api/v1/endpoints.py and use utilities from lfx.custom.utils:
build_custom_component_template — parses component code and produces the full frontend node template.add_code_field_to_build_config — ensures the code field is always present in the template.update_component_build_config — calls the component's update_build_config method and returns the modified template.The request and response schemas involved are CustomComponentRequest, CustomComponentResponse, and UpdateCustomComponentRequest defined in src/backend/base/langflow/api/v1/schemas.py193-214
The following class-level attributes are read by the engine and frontend when processing a component:
| Attribute | Type | Purpose |
|---|---|---|
display_name | str | Human-readable label in UI |
description | str | Tooltip / documentation |
icon | str | Lucide icon name |
name | str | Internal component type identifier |
inputs | list | Ordered list of input definitions |
outputs | list | Ordered list of output definitions |
trace_type | str | Trace category used by tracing service |
CONFIG_ATTRIBUTES and BACKWARDS_COMPATIBLE_ATTRIBUTES exported from langflow.custom.custom_component.component list the attributes managed by the engine internally and those kept for backward compatibility respectively.
Sources: src/backend/base/langflow/custom/custom_component/component.py src/backend/base/langflow/services/tracing/service.py374-416
During build, the TracingService.trace_component async context manager wraps each component execution. The component's trace_type attribute is used to categorize the trace entry. Components can emit structured logs to the active tracer by returning structured data from output methods — the engine collects these as artifacts and forwards them to any configured tracers (LangSmith, LangFuse, etc.).
No changes are needed in custom component code to participate in tracing; it is applied automatically by the engine.
Sources: src/backend/base/langflow/services/tracing/service.py373-416
Refresh this wiki
This wiki was recently refreshed. Please wait 3 days to refresh again.