> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://respan.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://respan.ai/docs/_mcp/server.

# Langflow (tracing)

> Trace Langflow visual AI workflows with Respan — callback spans, gateway routing, and full observability.

[Langflow](https://www.langflow.org/) is a visual framework by DataStax for building multi-agent and RAG applications. It provides a drag-and-drop interface for composing LLM pipelines with components for models, prompts, tools, and data sources. Langflow is built on LangChain, so Respan tracing uses `respan-instrumentation-langchain` to capture component runs, underlying LangChain calls, tools, retrievers, and LLM generations — and gateway routing through the OpenAI-compatible Respan endpoint.

#### Set up Respan

Create an account at [platform.respan.ai](https://platform.respan.ai) and grab an [API key](https://platform.respan.ai/platform/gateway/api-keys).

Run `npx @respan/cli setup` to set up with your coding agent.

#### Use Respan Gateway

See [Langflow gateway setup](/docs/gateway/langflow) to route this integration through the Respan gateway.

#### Example projects

* [Example projects](https://github.com/respanai/respan-example-projects)

## Setup

#### Install packages

**`Python`**

```bash Python
pip install respan-ai respan-instrumentation-langchain langflow langchain langchain-openai python-dotenv
```

**`TypeScript`**

```bash TypeScript
npm install @respan/respan @respan/instrumentation-langchain @langchain/core langchain zod
```

#### Set environment variables

```bash
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
export RESPAN_BASE_URL="https://api.respan.ai/api"
```

`RESPAN_API_KEY` is used to export traces to Respan. Set `OPENAI_API_KEY` too when your Langflow components call provider-backed models.

#### Initialize and run

Pass `LangChainInstrumentor()` to `Respan(instrumentations=[...])`. Langflow is built on LangChain, so in Python component runs are traced automatically. Reuse one callback handler when you want independent component runs grouped into a single trace.

> **Note**
>
> There are two ways to run Langflow with tracing: run custom-component code directly (as below), or run a flow you built in the Langflow UI. A UI flow must be exported first (**Share → Export**) to a `flow.json` before `run_flow_from_json` can load it — this quickstart ships no standalone flow file, so the runnable example uses component code directly.

**`Python`**

```python Python

from langchain_core.runnables import RunnableLambda
from respan import Respan
from respan_instrumentation_langchain import (
    LangChainInstrumentor,
    add_respan_callback,
    get_callback_handler,
)

# Activates global instrumentation. Component runs are captured automatically;
# the shared handler groups independent component root runs into one trace.
respan = Respan(instrumentations=[LangChainInstrumentor()])

handler = get_callback_handler()

def langflow_config(name: str):
    return add_respan_callback(
        {
            "run_name": name,
            "tags": ["respan-langchain-example", "langflow", name],
            "metadata": {
                "example": name,
                "framework": "langflow",
                "langflow_component": "RoutingComponent",
            },
        },
        handler,
    )

route_department = RunnableLambda(
    lambda input: f"{input['department']}-workspace"
)
get_weather = RunnableLambda(
    lambda input: f"It is sunny in {input['city']}."
)

route = route_department.invoke(
    {"department": "security"},
    config=langflow_config("langflow_route_department"),
)
weather = get_weather.invoke(
    {"city": "Dublin"},
    config=langflow_config("langflow_get_weather"),
)
print(f"{route}: {weather}")
```

**`TypeScript`**

```typescript TypeScript
import { RunnableLambda } from "@langchain/core/runnables";
import { Respan } from "@respan/respan";
import {
  LangChainInstrumentor,
  addRespanCallback,
  getCallbackHandler,
} from "@respan/instrumentation-langchain";

const langflow = new LangChainInstrumentor();
const respan = new Respan({
  apiKey: process.env.RESPAN_API_KEY,
  baseURL: process.env.RESPAN_BASE_URL,
  instrumentations: [langflow],
});
await respan.initialize();

const componentHandler = getCallbackHandler();
const config = addRespanCallback(
  {
    runName: "routing_component",
    tags: ["langflow", "custom-component"],
    metadata: {
      framework: "langflow",
      langflow_component: "RoutingComponent",
    },
  },
  componentHandler
);

const routeDepartment = RunnableLambda.from((input: { department: string }) => {
  return `${input.department}-workspace`;
});

const result = await routeDepartment.invoke({ department: "security" }, config);
console.log(result);
```

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces) to see your Langflow workflow with component-level operations, LLM calls, retriever spans, and tool calls.

## Configuration

| Parameter                  | Type           | Default                             | Description                                                          |
| -------------------------- | -------------- | ----------------------------------- | -------------------------------------------------------------------- |
| `api_key`                  | `str \| None`  | `None`                              | Falls back to `RESPAN_API_KEY` env var.                              |
| `base_url`                 | `str \| None`  | `None`                              | Falls back to `RESPAN_BASE_URL` env var.                             |
| `instrumentations`         | `list`         | `[]`                                | Plugin instrumentations to activate, e.g. `LangChainInstrumentor()`. |
| `group_langflow_root_runs` | `bool`         | `True` via `get_callback_handler()` | Groups independent Langflow component root runs into one trace.      |
| `include_content`          | `bool`         | `True`                              | Includes component inputs and outputs on spans.                      |
| `include_metadata`         | `bool`         | `True`                              | Includes Langflow tags, metadata, and serialized runnable details.   |
| `customer_identifier`      | `str \| None`  | `None`                              | Default customer identifier for all spans.                           |
| `metadata`                 | `dict \| None` | `None`                              | Default metadata attached to all spans.                              |
| `environment`              | `str \| None`  | `None`                              | Environment tag, e.g. `"production"`.                                |

## Attributes

### In Respan()

Set defaults at initialization — these apply to all spans.

**`Python`**

```python Python
from respan import Respan
from respan_instrumentation_langchain import LangChainInstrumentor

respan = Respan(
    instrumentations=[LangChainInstrumentor()],
    customer_identifier="user_123",
    metadata={"service": "langflow-api", "version": "1.0.0"},
)
```

**`TypeScript`**

```typescript TypeScript
import { Respan } from "@respan/respan";
import { LangChainInstrumentor } from "@respan/instrumentation-langchain";

const respan = new Respan({
  instrumentations: [new LangChainInstrumentor()],
});
```

### With propagate_attributes

Override per-request using a context scope.

**`Python`**

```python Python
from langflow.load import run_flow_from_json
from respan import propagate_attributes

def handle_request(user_id: str, question: str):
    with propagate_attributes(
        customer_identifier=user_id,
        thread_identifier="conv_abc_123",
        metadata={"plan": "pro"},
    ):
        result = run_flow_from_json(flow="flow.json", input_value=question)
        print(result)
```

**`TypeScript`**

```typescript TypeScript
async function handleRequest(userId: string, department: string) {
  await respan.propagateAttributes(
    {
      customer_identifier: userId,
      thread_identifier: "conv_abc_123",
      metadata: { plan: "pro" },
    },
    async () => {
      const result = await routeDepartment.invoke(
        { department },
        config
      );
      console.log(result);
    }
  );
}
```

| Attribute             | Type   | Description                                           |
| --------------------- | ------ | ----------------------------------------------------- |
| `customer_identifier` | `str`  | Identifies the end user in Respan analytics.          |
| `thread_identifier`   | `str`  | Groups related messages into a conversation.          |
| `metadata`            | `dict` | Custom key-value pairs. Merged with default metadata. |

## Decorators (optional)

Decorators are not required. Langflow runs are traced through LangChain callbacks. Use `@workflow` and `@task` (Python) or `withWorkflow` and `withTask` (TypeScript) when you want to group one or more flow executions inside a named application workflow.

**`Python`**

```python Python
from respan import workflow, task

@task(name="run_langflow_flow")
def run_langflow_flow(question: str):
    return run_flow_from_json(flow="flow.json", input_value=question)

@workflow(name="langflow_request")
def pipeline(question: str):
    print(run_langflow_flow(question))

pipeline("What is the meaning of life?")
```

**`TypeScript`**

```typescript TypeScript
await respan.withWorkflow({ name: "langflow_request" }, async () => {
  const result = await respan.withTask({ name: "routing_component_task" }, async () => {
    return routeDepartment.invoke({ department: "security" }, config);
  });
  console.log(result);
});
```

## Examples

### Custom component callback grouping

Use one callback handler for the component invocation so multiple LangChain calls in the same custom component share a trace.

```python
from respan_instrumentation_langchain import add_respan_callback, get_callback_handler

handler = get_callback_handler()
config = add_respan_callback(
    {
        "run_name": "langflow_component",
        "tags": ["langflow", "custom-component"],
        "metadata": {
            "framework": "langflow",
            "langflow_component": "RoutingComponent",
        },
    },
    handler,
)

result = chain.invoke({"question": "Route this request"}, config=config)
```

### Exported flows

Export the flow from the Langflow UI (**Share → Export**) to a `flow.json` first. Exported flows can then be run normally after Respan telemetry is initialized. For custom components inside the flow, pass `add_respan_callback(...)` when invoking LangChain runnables.

```python
from langflow.load import run_flow_from_json

result = run_flow_from_json(
    flow="path/to/your/flow.json",
    input_value="Summarize this support request.",
)
print(result)
```