diff --git a/docs/css/code.css b/docs/css/code.css index 2f10e8fa60..57791dc4cb 100644 --- a/docs/css/code.css +++ b/docs/css/code.css @@ -1,3 +1,9 @@ +/* Geist Mono (and other ligature-enabled fonts) merge ~= into one glyph in inline code */ +code, +pre code { + font-variant-ligatures: none; +} + .docusaurus-highlight-code-line { background-color: rgba(0, 0, 0, 0.1); display: block; diff --git a/docs/docs/Deployment/deployment-lfx-compatibility.mdx b/docs/docs/Deployment/deployment-lfx-compatibility.mdx new file mode 100644 index 0000000000..51ea8ab09f --- /dev/null +++ b/docs/docs/Deployment/deployment-lfx-compatibility.mdx @@ -0,0 +1,105 @@ +--- +title: LFX and Langflow version compatibility +slug: /lfx-compatibility +--- + +Langflow and LFX are versioned together on the same `major.minor` line, so you can always tell which LFX release runs which flows. + +## Compatibility contract + +**LFX `X.Y.N` is guaranteed compatible with any flow exported from Langflow `X.Y.M`.** + +The major and minor numbers must match. +The patches `.N` for LFX and `.M` for Langflow are released independently. An LFX patch fix does not require a Langflow patch release, and vice versa. + +When LFX and a flow share the same `major` version but differ on `minor`, such as a flow exported from Langflow 1.9.x run with LFX 1.10.x, individual components may have been updated since the flow was saved. +Use `lfx upgrade` to check compatibility and apply safe automatic fixes before running or serving such a flow. +For more information, see [Check and upgrade flows with lfx upgrade](#check-and-upgrade-flows-with-lfx-upgrade). + +## Compatibility matrix + +| Langflow version | Compatible LFX version | Notes | +|---|---|---| +| 1.10.x | 1.10.x | Fully compatible. Same `major.minor` line. | +| 1.11.x | 1.11.x | Fully compatible. Same `major.minor` line. | +| 1.9.x or earlier | 1.10.x | Use `lfx upgrade --upgrade-flow=safe` to apply safe component schema upgrades before running. | +| Any 1.x.x | 0.5.x | LFX 0.5.x was a standalone release before version alignment. It is no longer compatible with Langflow 1.10+ flows. | + +## Check and upgrade flows with `lfx upgrade` + +The `lfx upgrade` command inspects a flow against the built-in component registry and reports any components that have become incompatible or that have safe automatic upgrades available. + +`lfx upgrade` compares each component in the flow against a bundled index at `_assets/component_index.json` that ships with the LFX release. + +Run it with no flags to get a read-only compatibility report. The command reads your flow JSON, walks through every component node, and prints one line per node with its status. It does not modify the file. + +```bash +lfx upgrade my-flow.json +``` + +Example output: + +```text + [SAFE] Agent (AgentComponent) - id: abc123 + [OK] Chat Output (ChatOutput) - id: def456 +``` + +| CLI output | What it means | Example | +|---|---|---| +| `[OK]` | Component matches the current registry. | No action needed. | +| `[SAFE]` | Component code changed, but ports and fields your flow uses still line up. `lfx upgrade --write` can apply this update automatically. | An output that previously emitted only `Message` now also supports `Data`. | +| `[BREAKING]` | A port or field your flow relies on was removed. | An input that accepted `Message` and `Data` now accepts only `Message` and your flow uses a `Data` component. | +| `[BLOCKED]` | The component type no longer exists in this LFX build. | A bundle-only component is not installed in your environment. | + +To apply fixes or enforce stricter checks, run: + +```bash +# Apply all safe upgrades and overwrite the file +lfx upgrade my-flow.json --write + +# Fail if any safe upgrades are still pending (use after a dry run before running `--write`) +lfx upgrade my-flow.json --strict +``` + +## Inline compatibility checking with `--upgrade-flow` + +Both `lfx run` and `lfx serve` accept an `--upgrade-flow` option so you can apply compatibility checks at execution without a separate `lfx upgrade` step. + +```bash +# Check only — fail if any component is blocked +lfx run my-flow.json --upgrade-flow=check "Hello world" + +# Apply safe upgrades in memory, then run +lfx run my-flow.json --upgrade-flow=safe "Hello world" + +# Same options for serve +lfx serve my-flow.json --upgrade-flow=safe +``` + +| Mode | Behavior | +|---|---| +| `check` | Reports compatibility issues and exits non-zero if any component is blocked. No changes are written to disk. | +| `safe` | Applies all safe upgrades in memory, then runs or serves the flow. Blocked components still cause a non-zero exit. | + +## Pin versions + +Pin `lfx~=1.10.0` in `requirements.txt` to track all patch releases for a given Langflow minor without crossing into the next minor automatically. + +```text +# requirements.txt — allows 1.10.1, 1.10.2, … but not 1.11.0 +lfx~=1.10.0 +``` + +## Migrating from LFX 0.5.x to 1.10.0 + +LFX was realigned from its standalone `0.5.x` line onto Langflow's `major.minor` line, so the version number jumps from `0.5.0` to `1.10.0` in one release. This is a version-numbering change, not 95 minor releases of new features. + +This jump can affect existing dependency pins in unexpected ways: + +| Pin style | Effect | +|---|---| +| `lfx==0.5.x` or `lfx<1.0` | Does not upgrade. The deployment stays on 0.5.x. | +| `lfx>=0.5,<1` | Does not upgrade. The upper bound excludes 1.10.0. | +| `lfx>=0.5` (no upper bound) | Upgrades automatically to 1.10.0 on the next install. | + +Going forward, pin with `lfx~=1.10.0` so you receive compatible patches without silently crossing minor lines. \ No newline at end of file diff --git a/docs/sidebars.js b/docs/sidebars.js index 1fd1a241a8..468a622443 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -298,6 +298,11 @@ module.exports = { id: "Deployment/deployment-multi-worker", label: "Deploy Langflow with multiple workers", }, + { + type: "doc", + id: "Deployment/deployment-lfx-compatibility", + label: "LFX and Langflow version compatibility", + }, { type: "doc", id: "Deployment/deployment-block-custom-components", diff --git a/src/lfx/README.md b/src/lfx/README.md index 4b40bf85e9..a95c17b524 100644 --- a/src/lfx/README.md +++ b/src/lfx/README.md @@ -18,7 +18,7 @@ If the `langflow` package is installed in the same Python environment as `lfx` a | Command | Description | |---------|-------------| -| [`lfx serve`](#serve-the-simple-agent-starter-flow-with-lfx-serve) | Serve a flow as a FastAPI endpoint at `/flows/{flow_id}/run` | +| [`lfx serve`](#serve-the-simple-agent-starter-flow-with-lfx-serve) | Serve one or more flows as FastAPI endpoints at `/flows/{flow_id}/run` | | [`lfx run`](#run-the-simple-agent-flow-with-lfx-run) | Execute a flow locally and stream results to `stdout` | | [`lfx-mcp`](#lfx-mcp) | Start an MCP server that connects to a running Langflow instance | @@ -112,7 +112,9 @@ Run LFX without installing it locally using `uvx`. ## Serve the simple agent starter flow with `lfx serve` -To serve a flow as a REST API endpoint, set a `LANGFLOW_API_KEY` and run the flow JSON. +`lfx serve` starts a FastAPI server that hosts one or more flows. You can load flows at startup from files or a directory, or start with an empty registry and upload flows via the API. Once running, flows are available at `POST /flows/{flow_id}/run`. + +`lfx serve` accepts a `.json` flow file or a `.py` Python script (same as `lfx run`), as well as inline JSON via `--flow-json` or piped input via `--stdin`. `lfx serve` accepts a `.json` flow file or a `.py` Python script (same as `lfx run`), as well as inline JSON via `--flow-json` or piped input via `--stdin`. @@ -202,25 +204,11 @@ This example uses the **Agent** component's built-in OpenAI model, which require 5. The startup process displays a `flow_id` value in the output. Copy the `flow_id` to use in the test API call in the next step. In this example, the `flow_id` is `c1dab29d-3364-58ef-8fef-99311d32ee42`: ``` - ╭───────────────────────────── LFX Server ─────────────────────────────╮ - │ 🎯 Single Flow Served Successfully! │ - │ │ - │ Source: /Users/mendonkissling/Downloads/simple-agent-flow.json │ - │ Server: http://127.0.0.1:8000 │ - │ API Key: sk-... │ - │ │ - │ Send POST requests to: │ - │ http://127.0.0.1:8000/flows/c1dab29d-3364-58ef-8fef-99311d32ee42/run │ - │ │ - │ With headers: │ - │ x-api-key: sk-... │ - │ │ - │ Or query parameter: │ - │ ?x-api-key=sk-... │ - │ │ - │ Request body: │ - │ {'input_value': 'Your input message'} │ - ╰──────────────────────────────────────────────────────────────────────╯ + LFX Server + Flow loaded: simple-agent-flow.json (c1dab29d-3364-58ef-8fef-99311d32ee42) + Server: http://127.0.0.1:8000 + Run flows at: POST /flows/{flow_id}/run + API key: x-api-key header or ?x-api-key= query parameter ``` 6. To send a test request to the server, open a new terminal and export your `flow_id` and Langflow API key values as variables: @@ -262,6 +250,7 @@ The LFX server exposes the following endpoints. All `/flows/{flow_id}` routes re | Endpoint | Method | Description | |----------|--------|-------------| | `/flows` | GET | List all served flows and their metadata | +| `/flows/upload/` | POST | Upload a flow JSON to the registry (accepts full Langflow export format) | | `/flows/{flow_id}/run` | POST | Run the flow and return a single response | | `/flows/{flow_id}/stream` | POST | Run the flow and stream output as server-sent events | | `/flows/{flow_id}/info` | GET | Return flow metadata (title, description, input/output types) | @@ -319,18 +308,136 @@ The LFX server's response schema is different from the Langflow API `/run` endpo The `/stream` endpoint returns the same fields as server-sent events, with one event per component output. +### Serve multiple flows at startup + +You can pass a directory, multiple file paths, or a mix of both to load several flows at startup. Each flow is registered under its own ID. + +```bash +# Serve every .json file in a directory (top-level only, not recursive) +uv run lfx serve flows/ + +# Serve specific files +uv run lfx serve flow-a.json flow-b.json + +# Mix directory and individual files +uv run lfx serve flows/ extra-flow.json +``` + +Python `.py` script flows are also supported when using a single worker: + +```bash +uv run lfx serve my_flow.py +``` + +### Start with no flows + +`lfx serve` starts with an empty registry when no flow path is provided. Flows can then be uploaded via the API: + +```bash +uv run lfx serve --env-file .env +``` + +### Upload flows dynamically + +While the server is running, upload flows with `POST /flows/upload/`. + +The endpoint accepts the full Langflow export JSON directly, the same format you get from the Langflow UI's **Export** button: + +```bash +# Upload a flow JSON file +curl -X POST http://localhost:8000/flows/upload/ \ + -H "x-api-key: $LANGFLOW_API_KEY" \ + -H "Content-Type: application/json" \ + -d @my-flow.json + +# Upload and replace an existing flow with the same ID +curl -X POST "http://localhost:8000/flows/upload/?replace=true" \ + -H "x-api-key: $LANGFLOW_API_KEY" \ + -H "Content-Type: application/json" \ + -d @my-flow.json +``` + +The server returns a `409 Conflict` error if you upload a flow whose ID is already registered and `replace=true` is not set. + +### Multi-worker deployment + +Use `--workers N` to start multiple uvicorn worker processes, and `--flow-dir` to point all workers at a shared directory so they serve the same flows. + +```bash +# 4 workers, flows shared via a local temp directory +uv run lfx serve flows/ --workers 4 --flow-dir /tmp/lfx-flows + +# Cross-pod sharing (Kubernetes PVC or similar network volume) +uv run lfx serve flows/ --workers 4 --flow-dir /mnt/shared-flows +``` + +How it works: + +- Each startup flow file is persisted to `--flow-dir` as `{flow_id}.json` when the server starts. +- Uploads via `POST /flows/upload/` are also written to `--flow-dir`, making them visible to every worker on the next request. +- Deletes propagate across workers: each worker detects a missing file on the next request to that flow and returns `404`. +- Without `--flow-dir`, each worker maintains an isolated in-memory registry. Uploads reach only the worker that received the request. + +> **Note:** `--workers > 1` with `--flow-dir` does not support `.py` script flows — Python graphs cannot be serialized to the filesystem store. + +A warning is printed when `--workers > 1` is used without `--flow-dir`, because in that case each worker has its own isolated in-memory registry. + +### Isolate credentials with `--no-env-fallback` _(experimental)_ + +By default, `lfx serve` resolves component credentials from the process environment (`os.environ`). In multi-tenant deployments, this means every request shares the same credentials. + +Use `--no-env-fallback` to disable process-environment fallback. With this flag set, credentials must be supplied per-request in the `global_vars` field of the request body: + +```bash +uv run lfx serve my-flow.json --no-env-fallback --env-file .env +``` + +Pass per-request credentials in the `global_vars` map under `LANGFLOW_REQUEST_VARIABLES`: + +```bash +curl -X POST http://localhost:8000/flows/$FLOW_ID/run \ + -H "Content-Type: application/json" \ + -H "x-api-key: $LANGFLOW_API_KEY" \ + -d '{ + "input_value": "Hello world", + "global_vars": { + "LANGFLOW_REQUEST_VARIABLES": { + "OPENAI_API_KEY": "sk-per-request-key" + } + } + }' +``` + +Credentials supplied in `LANGFLOW_REQUEST_VARIABLES` are scoped to the current request using Python `contextvars`. Langflow's built-in components do not write them to `os.environ`, so they do not bleed into other concurrent requests on the same worker. Custom components that explicitly write to `os.environ` are outside this guarantee. + +### Check or upgrade flow compatibility at startup + +Use `--upgrade-flow` to check compatibility between a flow and the current LFX version before serving it. See [LFX and Langflow version compatibility](https://docs.langflow.org/lfx-compatibility) for details on the version model. + +```bash +# Fail at startup if any component is incompatible +uv run lfx serve my-flow.json --upgrade-flow=check + +# Apply safe upgrades in memory, then start serving +uv run lfx serve my-flow.json --upgrade-flow=safe +``` + ### LFX serve options | Option | Description | |--------|--------------| | `--check-variables` / `--no-check-variables` | Check global variables for environment compatibility. Default: `--check-variables`. | | `--env-file` | Path to the `.env` file containing environment variables. | +| `--flow-dir` | Directory for the filesystem-backed flow store shared across workers. When set, startup flows and uploads are persisted here. | +| `--flow-json` | Read inline flow JSON content as a string. Example: `uv run lfx serve --flow-json '{...}'`. | | `--host`, `-h` | Host to bind the server to. Default: `127.0.0.1`. | | `--log-level` | Logging level. One of: `debug`, `info`, `warning`, `error`, `critical`. Default: `warning`. | +| `--no-env-fallback` / `--env-fallback` | Disable process-environment fallback for credential resolution. Use with per-request `LANGFLOW_REQUEST_VARIABLES`. Default: `--env-fallback`. | | `--port`, `-p` | Port to bind the server to. Default: `8000`. | -| `--verbose`, `-v` | Show diagnostic output and execution details. | -| `--flow-json` | Read inline flow JSON content as a string. Example: `uv run lfx serve --flow-json '{...}'`. | | `--stdin` | Read JSON flow content from `stdin`. Example: `cat flow.json | uv run lfx serve --stdin`. | +| `--upgrade-flow` | Compatibility mode: `check` reports issues and fails, `safe` applies safe upgrades in memory. | +| `--verbose`, `-v` | Show diagnostic output and execution details. | +| `--workers`, `-w` | Number of uvicorn worker processes. Default: `1`. Use with `--flow-dir` for multi-worker flow sharing. | ## Run the simple agent flow with `lfx run` @@ -433,6 +540,7 @@ uv run lfx run --flow-json '{"data": {"nodes": [...], "edges": [...]}}' \ | `--session-id` | Session ID for conversation tracking. Agent and Memory components use this to maintain history across runs. Auto-generated if not set. | | `--stdin` | Read JSON flow content from `stdin`. | | `--timing` | Include detailed timing information in output. | +| `--upgrade-flow` | Compatibility mode: `check` reports issues and fails, `safe` applies safe upgrades in memory before running. | | `--verbose`, `-v` | Show basic progress and diagnostic output. | | `-vv` | Show detailed progress and debug information. | | `-vvv` | Show full debugging output including component logs. |