Skip to content
Open
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/docs/Develop/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,7 @@ See [Telemetry](/contributing-telemetry).
| `LANGFLOW_BUNDLE_URLS` | List[String] | `[]` | A list of URLs from which to load custom bundles. Supports GitHub URLs. If `LANGFLOW_AUTO_LOGIN=True`, flows from these bundles are loaded into the database. |
| `LANGFLOW_COMPONENTS_PATH` | String | Not set | Path to a directory containing custom components. Typically used if you have local custom components or you are building a Docker image with custom components. |
| `LANGFLOW_COMPONENTS_INDEX_PATH` | String | Not set | File path or URL (`http://` or `https://`) to a prebuilt component index JSON file used to populate built-in components in the visual editor. When not set, Langflow uses the included index. Useful for supplying a curated component index, for example in airgapped deployments. For more information, see [Block custom components](/deployment-block-custom-components). |
| `LANGFLOW_AGENTIC_EXPERIENCE` | Boolean | `True` | Whether [Langflow Assistant](/langflow-assistant) is available. Set to `false` to turn it off for a deployment, for example if you don't want model-generated component code running on your server. The Assistant's endpoints then return `404` and its `run_assistant` MCP tool is unavailable, but the rest of the MCP toolkit at `/api/v1/agentic/mcp` is unaffected. To block code execution itself, including hand-written custom components, use `LANGFLOW_ALLOW_CUSTOM_COMPONENTS`. |
| `LANGFLOW_ALLOW_CUSTOM_COMPONENTS` | Boolean | `True` | If `false`, disables custom components and in-editor editing of component code. This feature is in beta. For more information, see [Block custom components](/deployment-block-custom-components) and [Component hardening for untrusted users](/api-keys-and-authentication#multi-tenant-component-hardening). |
| `LANGFLOW_ALLOW_COMPONENTS_PATHS_OVERRIDE` | Boolean | `True` | When `false` alongside `LANGFLOW_ALLOW_CUSTOM_COMPONENTS=false`, components contributed by `LANGFLOW_COMPONENTS_PATH` and `LANGFLOW_COMPONENTS_INDEX_PATH` no longer bypass the block. Has no effect when `LANGFLOW_ALLOW_CUSTOM_COMPONENTS=true`. For more information, see [Block custom components](/deployment-block-custom-components). |
| `LANGFLOW_BLOCK_CODE_INTERPRETER_COMPONENTS` | Boolean | `False` | If `true`, blocks built-in code-execution components (Python Interpreter, REPL/Code tools, Smart Transform, and code-running agents). See [Component hardening for untrusted users](/api-keys-and-authentication#multi-tenant-component-hardening). |
Expand Down
48 changes: 48 additions & 0 deletions docs/docs/Flows/langflow-assistant.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ To give **Langflow Assistant** context for a different flow, switch to that flow
## Prerequisites

* Connect an LLM provider in the [Global model providers page](/components-models) for **Langflow Assistant** to use
* `LANGFLOW_AGENTIC_EXPERIENCE` must be `true` (default).

**Langflow Assistant** is available out of the box. Set this to `false` to turn it off for a deployment, for example if you don't want model-generated component code running on your server.
While it is off, the Assistant's endpoints return `404`.
For more information, see [Supported environment variables](/environment-variables#supported-variables).

* Custom component creation must be enabled and permitted for your user role:
* `LANGFLOW_ALLOW_CUSTOM_COMPONENTS` must be `true` (default).
* `LANGFLOW_CUSTOM_COMPONENT_ADMIN_ONLY` must be `false` (default) for non-superusers. For superusers, this option is irrelevant.
Expand Down Expand Up @@ -276,8 +282,50 @@ For example, to prompt **Langflow Assistant** to update the system prompt field
Update @Agent.System Prompt to always respond in bullet points.
```

## Use a local or OpenAI-compatible model

**Langflow Assistant** can run on a model served from your own machine or from any OpenAI-compatible endpoint, so your prompts never leave your environment.

To use a local model served by [Ollama](https://ollama.com), set the `OLLAMA_BASE_URL` global variable to your Ollama server, such as `http://localhost:11434`.
Ollama requires no API key.

To use an OpenAI-compatible server instead of OpenAI itself, set the `OPENAI_BASE_URL` global variable to your server's URL, and set `OPENAI_API_KEY` to the key your server expects.

You can set both values as [global variables](/configuration-global-variables) or as environment variables of the same name.
Global variables take precedence, and Langflow falls back to the environment variable when no global variable is set.

:::important
**Langflow Assistant** builds flows by calling tools, so it requires a model that supports tool calling.
Small local models often can't call tools reliably, which appears as an Assistant that only chats and never changes your canvas.
If the Assistant doesn't act on your prompts, try a larger model.
:::

## Connect an external client with MCP

**Langflow Assistant** and Langflow's flow-authoring tools are available to external MCP clients, such as Cursor, Claude Code, and Codex, over a [streamable HTTP](https://modelcontextprotocol.io/docs/concepts/transports) MCP server at `/api/v1/agentic/mcp`.

This lets a client build, inspect, patch, and run your flows without opening the visual editor, including a `run_assistant` tool that calls **Langflow Assistant** itself.
Changes are saved to your flows and appear in the visual editor.

The flow-authoring tools don't require `LANGFLOW_AGENTIC_EXPERIENCE`, because each one is a Langflow API call that your API key already authorizes.
Only `run_assistant` requires it: while the Assistant is disabled, that single tool isn't listed and returns an error explaining why, and the rest of the toolkit keeps working.

Authenticate with a Langflow API key, in the same way as Langflow's other MCP endpoints:

```bash
curl -X POST "$LANGFLOW_URL/api/v1/agentic/mcp" \
-H "x-api-key: $LANGFLOW_API_KEY" \
-H "Content-Type: application/json"
```

For an MCP client, point it at `$LANGFLOW_URL/api/v1/agentic/mcp` with your API key as an `x-api-key` header.
Every tool call is authorized as your own user, so a client can only reach the flows your API key can reach.

For more information on creating an API key, see [API keys](/api-keys-and-authentication).

## See also

- [Build flows](/concepts-flows)
- [Custom components](/components-custom-components)
- [MCP server](/mcp-server)
- [Trigger flows with the Langflow API](/concepts-publish)
17 changes: 16 additions & 1 deletion docs/features/langflow-assistant-mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@
> (9) **`ModelInputComponent` defensive `recoverModelOption`** — repairs doubly-encoded model values produced by the assistant's `flow_update` pipeline so the Agent node's Language Model dropdown trigger never renders literal JSON.
> (10) **Empty-state `ModelProviderModal` inline open** — the assistant's "Configure providers" CTA now opens the modal in-panel instead of navigating away.
> See ADR-023 through ADR-030 in `langflow-assistant.md` for full per-decision context; the MCP-specific impact is reflected in the glossary and behavior sections below.
>
> **2026-07-08 revision** — **Loop + conditional flow building lands on the MCP tool surface** (full breakdown in `langflow-assistant.md`'s 2026-07-08 revision):
> (1) **`add_connection` can now express the Loop feedback edge** — when the target port is an `allows_loop=True` OUTPUT (e.g. `Loop.item`), `lfx/graph/flow_builder/connect.py` emits the output-shaped targetHandle `{dataType, id, name, output_types}` the runtime's loop branch requires, with accepted types mirroring the canvas (`[selected ?? types[0], ...loop_types]`). Template inputs keep priority on name collisions; structural idempotency, `remove_connection`, and `list_connections` all recognize loop edges. Every builder tool inherits this: `connect_components`, `create_flow_from_spec`, `build_flow`, `update_flow_from_spec`.
> (2) **`describe_component` surfaces loop inputs** — `allows_loop` outputs are flagged on the output entry AND listed as inputs with `type: "loop"` and a description, so the agent can discover loop wiring instead of failing on "Input 'item' not found" (that error now also names the available loop inputs).
> (3) **"Loops and branching" prompt section** in `FLOW_BUILDER_PROMPT` — canonical one-shot loop spec (build in ONE `build_flow` call; do not re-discover the wiring) plus If-Else fan-out guidance (`ConditionalRouter.true_result`/`false_result`, `DataConditionalRouter` for Data). E2E-validated on a live instance: the assistant one-shots both a cyclic Loop flow (with a real loop-feedback edge) and a two-branch If-Else flow within the pinned 15-iteration budget.
> (4) **The lfx MCP toolkit over HTTP (consolidated, supersedes the two-server framing in ADR-MCP-007 for external access)** — `POST/GET/DELETE /api/v1/agentic/mcp` (streamable-http, stateless; `api/v1/agentic_mcp.py`) mounts the **single** Langflow MCP toolkit, `lfx.mcp.server`: the same 30+ authoring/execution tools the local `lfx-mcp` stdio bridge ships, plus `run_assistant`. Auth is the same `CurrentActiveMCPUser` dependency as the flows MCP endpoints. The mount is NOT gated on `LANGFLOW_AGENTIC_EXPERIENCE`: its tools are REST calls the API already authorizes and the `lfx-mcp` stdio bridge serves them ungated, so gating the mount would only make HTTP weaker than stdio while holding 31 ungated tools hostage to the one that needs the gate. The gate applies per-tool — `run_assistant` alone is withheld (and returns an explanatory error) while the assistant is off. The route also releases its auth DB session before dispatching: FastAPI holds a yield-dependency's session for the whole request, and every tool's loopback REST call then waits on that connection until SQLite's `busy_timeout` aborts it — the mount deadlocked for 30s on the default database until this was fixed. Every tool call goes through the REST API in loopback bound to the caller's own request headers, so authorization is enforced by the API on every operation and no tool touches the database directly — the `user_id`-injection machinery is gone (identity is the credential). The `login` tool is excluded over HTTP (credential-forwarding surface). The `langflow-agentic` stdio server is deprecated as an external surface, and its per-user auto-configuration (preload step `AGENTIC_MCP` + the `main.py` fallback) was **removed** — external clients connect to the HTTP mount with their own API key (`curl -X POST <server>/api/v1/agentic/mcp -H "x-api-key: <key>"`, or any streamable-http MCP client), and local-spawn clients keep using the `lfx-mcp` stdio bridge. Previously auto-registered `langflow-agentic` entries keep working (the stdio module remains for back-compat only).
> (5) **`run_assistant` in the lfx toolkit (auto-apply)** — `lfx.mcp.server.run_assistant` consumes the Assistant through the **headless** route `POST /api/v1/agentic/assist/run` with the caller's credentials (no `user_id` argument). The headless route exists because `/assist/stream` (the UI path) leaves a canvas change as a *proposal* for an approval card — an MCP caller has no card, so its edits would be silently dropped. `/assist/run` runs `run_assistant_and_persist` (`apply_edits_immediately`), so the canvas is **written**, and streams the same events, ending in `complete`. It forwards each assistant `progress` SSE event as an MCP progress notification (`send_progress_notification` with `related_request_id`, so the stateless streamable-http transport delivers it) plus a `ctx.info` log line. Forwarding failures are swallowed — progress can never break the tool. Verified live end-to-end: external MCP client → HTTP mount → assistant built a flow, with progress notifications streamed back on the same request.
> (6) **`use_template` / `list_templates` in the in-product toolkit** (`lfx/mcp/flow_builder_tools/template_tools.py`) — one-call starter-template instantiation through the SAME `set_flow` proposal gate as `build_flow` (Add/Replace card; canvas untouched without approval), emitting `tool_start`. `list_templates` returns only name + one-line description; `use_template` returns a compact summary (name, node/edge counts, node types) — the template's flow JSON never enters the LLM context (cost guard, test-enforced). Bare-lfx environments degrade gracefully ("Starter templates are not available"). Prompt: use ONLY on a clear template match. Also: `classify_intent` gains a whitespace-only/empty-input deterministic fast path (no LLM call; language-independent).
>
> **2026-07-09 revision** — **Model portability and streaming/tracing robustness across the MCP execution surface** (full breakdown in `langflow-assistant.md`'s 2026-07-09 revision). These land in the shared `lfx` model/streaming layer, so every MCP path that runs a flow (`run_flow`, `run_assistant`, and any `build_flow` + run turn) inherits them:
> (1) **Provider-agnostic model remediation** — a reactive, per-model cached layer (`lfx/base/models/model_remediation.py`) maps an error signature + provider to instantiation overrides. First entry: the OpenAI `/v1/responses` error marker → `{"use_responses_api": True}`, so gpt-5.6 (which rejects `tools` + `reasoning_effort` on chat/completions) auto-switches to the Responses API on the retry and is remembered for the session. `get_llm` pre-applies `cached_overrides(provider, model)`; the embedded `Agent` retries once with `_model_overrides` and `remember`s the fix. The assistant/MCP path bridges the same fix in `assistant_service.py`'s `FlowExecutionError` handler (before the model-swap fallback), so the shared `get_llm` cache carries the override into the Agent embedded in the assistant flow. Adding Anthropic/Ollama constraints is a new `Remediation` row, not code.
> (2) **Legacy / untagged content-block resilience** — `validate_content_blocks._parse_item` (`lfx/schema/message.py`) parses an untagged `{"text": ...}` block as `TextContent` before the discriminated-union adapter, and `BaseContent.serialize_model` (`content_types.py`) re-adds the discriminator through `exclude_unset`. Prevents a run/`run_assistant` turn from crashing while deserializing stored message history.
> (3) **Responses-API `[]` flash suppressed** — `event_consumer.py` drops a streamed token whose chunk strips to `"[]"` (the Responses API's empty-content-block-list starting state), so it never surfaces before the real answer on any streamed MCP/assistant turn.
> (4) **Langfuse callback is deep-copy safe** — with Langfuse configured, an Agent build (any `run_flow` / `run_assistant` / `build_flow`+run turn) crashed with `LangfuseResourceManager.__new__() missing 3 required keyword-only arguments`. Root cause: langflow deep-copies flow/graph state around the Agent build, and the langfuse LangChain `CallbackHandler` attached via `get_langchain_callbacks()` wraps a keyword-only-singleton client that `copy.deepcopy` (which calls `cls.__new__(cls)` with no args) cannot clone. Fix: langflow's `_RootRunReparentingCallbackHandler` (`services/tracing/langfuse.py`) implements `__deepcopy__` / `__copy__` returning `self`, so the shared observer is carried by reference. `TracingService.get_langchain_callbacks` additionally try/excepts callback creation as a belt-and-suspenders. Verified live on gpt-5.6.
> (5) **Bigger, tunable assistant iteration budget** — a compound build+run+report turn hit `Recursion limit of 35 reached`. The 35 is derived (`agent.py::_compute_recursion_limit` = `max_iterations * 2 + 5`) from the assistant Agent's pinned `max_iterations`. That pin is raised 15 → **30** in the embedded assistant flows (recursion_limit 65), and a `/iterations N` composer command overrides it per session (additive `AssistantRequest.iterations_limit`, `ge=1 le=200`, → `ITERATIONS_LIMIT` global var → `inject_iterations_into_flow` stamps the Agent's `max_iterations`, clamped `[1,200]`). Every MCP execution path that runs the assistant Agent (`run_assistant`, `build_flow`+run) inherits the larger budget. Verified live on gpt-5.6.

---

Expand Down Expand Up @@ -1337,7 +1352,7 @@ LLMs can produce flow specs where a component is declared but never wired. The r

### ADR-MCP-007: Two MCP Servers — `lfx/mcp` (canvas-aware) and `agentic/mcp` (DB-aware)

**Status**: Accepted
**Status**: Accepted — amended 2026-07-13: for EXTERNAL access the two-server split is superseded; the HTTP mount (`/api/v1/agentic/mcp`) serves only `lfx/mcp` (with `run_assistant` consuming the Assistant via REST), and `agentic/mcp` is deprecated to the internal per-user auto-configured entry. One toolkit, API-mediated, dual transport (stdio bridge + server HTTP).

#### Context

Expand Down
Loading
Loading