CodeVetter · Repo Unpack · Extension points
langflow-ai/langflow
Langflow is built to be extended at five seams: (1) component/extension bundles via the `langflow.extensions` entry point + extension.json manifests + seed dirs + components_path; (2) service replacement via `lfx.services` entry points and lfx.toml/pyproject config (auth SSO, authorization/RBAC, catalog policy, model-provider policy, policy bundle); (3) HTTP route plugins via the `langflow.plugins` entry point with conflict-protected registration; (4) CLI plugins via register_cli_command_plugins; (5) enterprise hooks via the lifespan hook registry. Custom components subclass lfx Component and are discovered from directories.
- Route plugins: distributions registering a `langflow.plugins` entry point get a callable register(app) invoked with a _PluginAppWrapper that reserves every existing (path, method), refuses shadowing (RouteConflictError), and rolls back a half-registered plugin's routes on failure.
- Service plugins: the `lfx.services` entry-point group registers service classes (override=False) and `lfx.toml`/`pyproject.toml [tool.lfx.services]` entries register with override=True; precedence is config > decorator > entry point, SETTINGS_SERVICE can never be overridden, and misconfigured MODEL_PROVIDER_POLICY/POLICY_BUNDLE services refuse to boot rather than fall back.
- The OSS authorization layer is a designed plugin seam: LangflowAuthorizationService is a registered pass-through (every check allows) replaced by listing a real plugin class under `authorization_service` in lfx.toml — the same pattern documented for SSO via `auth_service`.
- Component/extension bundles: lfx-* packages ship an extension.json manifest inside the wheel and register a `langflow.extensions` entry point; discovery also scans LANGFLOW_SEED_DIR (default /opt/langflow/bundles) directories; inline bundles can come from components_path parents.
- Custom components: subclass lfx.custom.custom_component.component.Component (re-exported as langflow.custom.Component), declare display_name/inputs/outputs, drop the file under a components_path directory; LFX_DEV=1 / LFX_DEV=<modules> enables dynamic hot loading; directory_reader scans the paths.
- Enterprise lifespan hooks: modules can append async callables to _enterprise_lifespan_hooks['startup'|'shutdown'] at app-construction time; startup hooks run after all services init, shutdown hooks run first in teardown; failures are logged and never block boot.
- CLI plugins: lfx.cli.command_plugins.register_cli_command_plugins is invoked by the langflow Typer app so installed packages can add CLI subcommands; lfx's own commands are modular register(app) functions per group.
- Deployment adapters/mappers: register_builtin_adapters + register_builtin_deployment_mappers import provider modules (e.g. watsonx_orchestrate) which register onto AdapterRegistry singletons — gated behind FEATURE_FLAGS.wxo_deployments.
- Sandbox backend plugins: LANGFLOW_SANDBOX_BACKEND_PLUGINS whitelists which entry-point plugins may load an executor backend for code-execution components; the default backend is 'none'.
- Frontend white-label seams: CustomRoutesStore/CustomAuthRoutesStore/CustomRoutesStorePages in routes.tsx let deployments override routes/pages, and icons register via lazyIconImports; the frontend only talks to the backend over HTTP/WS.