> 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.

# Dify (tracing)

> Trace official Dify Service API clients with Respan in Python and JavaScript.

[Dify](https://dify.ai/) exposes chat, completion, workflow, conversation, file, Knowledge Base, and Workspace operations through its Service API clients. Respan's Dify instrumentation observes those client requests and converts them into canonical chat, text, workflow, or task spans without changing where the Dify request is sent.

> **Warning**
>
> `respan-instrumentation-dify` exists on PyPI at 0.1.1, but the refreshed Python instrumentation described on this page is pending its next minor release. In particular, do not assume 0.1.1 contains the new 0.1.12-source async, Knowledge Base, Workspace, stream-lifecycle, and credential-redaction coverage. Use the linked Python source checkout for that refreshed behavior until its release is confirmed.

> **Note**
>
> This integration is client-side tracing, not gateway routing. Respan Gateway does not expose a Dify Service API-compatible route. Keep `DIFY_BASE_URL` pointed at Dify (or your self-hosted Dify instance); do not repoint a Dify client to the Respan gateway URL. To route Dify's internal LLM calls through Respan instead, use the separate [Dify Gateway setup](/docs/integrations/gateway/dify).

#### 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.

#### Packages and example projects

* [Python instrumentation source and README](https://github.com/respanai/respan/tree/main/python-sdks/instrumentations/respan-instrumentation-dify)
* [JavaScript / TypeScript instrumentation source and README](https://github.com/respanai/respan/tree/main/javascript-sdks/instrumentations/respan-instrumentation-dify)
* [Runnable Python examples](https://github.com/respanai/respan-example-projects/tree/main/python/tracing/dify)
* [Runnable JavaScript / TypeScript examples](https://github.com/respanai/respan-example-projects/tree/main/typescript/tracing/dify)

## Availability

| Language                | Availability                                             | Supported client                                                                                                                                                                                             |
| ----------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Python baseline         | `respan-instrumentation-dify` 0.1.1 is available on PyPI | Use for the already-released integration only; the refreshed coverage below has not been published yet.                                                                                                      |
| Python refreshed source | Pending the next minor release                           | Python 3.11-3.13 and `dify-client >=0.1.10,<0.2.0`. The released `dify-client` 0.1.10 surface is synchronous; current instrumentation source also recognizes the refreshed 0.1.12 source API when installed. |
| JavaScript / TypeScript | `@respan/instrumentation-dify` 0.1.0 is available on npm | Node.js 18+ and `dify-client >=3.1.0,<4.0.0`; tested with 3.1.0.                                                                                                                                             |

This integration is explicit-only. Add `DifyInstrumentor` to `Respan`; Dify is not enabled as a zero-configuration leaf-model integration.

## Python setup

#### Install packages

**`Python released baseline`**

```bash Python released baseline
pip install respan-ai respan-instrumentation-dify "dify-client>=0.1.10,<0.2.0"
```

**`Python refreshed source preview`**

```bash Python refreshed source preview
git clone https://github.com/respanai/respan.git

python -m pip install \
  "dify-client @ git+https://github.com/langgenius/dify-python-sdk.git@a3ce501021906e23535c268f0b60fea3864864a6" \
  -e ./respan/python-sdks/respan-sdk \
  -e ./respan/python-sdks/respan-tracing \
  -e ./respan/python-sdks/respan \
  -e ./respan/python-sdks/instrumentations/respan-instrumentation-dify
```

The editable install selects the current, unreleased instrumentation source and pins the official Dify Python SDK's 0.1.12 source commit so the async, Knowledge Base, and Workspace examples are runnable. Replace the source-checkout workflow with registry packages only after the refreshed release is confirmed.

#### Set environment variables

```bash
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
export DIFY_CHAT_API_KEY="YOUR_DIFY_CHAT_APP_KEY"

# Optional for self-hosted Dify or a test endpoint; this must remain a Dify URL.
export DIFY_BASE_URL="https://api.dify.ai/v1"
```

Use the API key for the Dify app or service surface you instantiate. For example, the runnable suites also recognize `DIFY_COMPLETION_API_KEY`, `DIFY_WORKFLOW_API_KEY`, and `DIFY_DATASET_API_KEY`. `DIFY_BASE_URL` is read by the sample code and must be passed to the Dify client using the syntax supported by that client version.

#### Initialize, call Dify, and shut down

```python
import os

from dify_client import ChatClient
from respan import Respan
from respan_instrumentation_dify import DifyInstrumentor

respan = Respan(
    api_key=os.environ["RESPAN_API_KEY"],
    instrumentations=[DifyInstrumentor()],
)

base_url = os.getenv("DIFY_BASE_URL")
try:
    client = ChatClient(
        api_key=os.environ["DIFY_CHAT_API_KEY"],
        **({"base_url": base_url} if base_url else {}),
    )
except TypeError:
    # Released dify-client 0.1.10 accepts only api_key; set its mutable URL.
    client = ChatClient(os.environ["DIFY_CHAT_API_KEY"])
    if base_url:
        client.base_url = base_url.rstrip("/")

try:
    response = client.create_chat_message(
        inputs={},
        query="Summarize tracing in one sentence.",
        user="respan-user",
        response_mode="blocking",
    )
    response.raise_for_status()
    print(response.json()["answer"])
finally:
    respan.flush()
    respan.shutdown()
```

Python activates the instrumentor when `Respan` is created. Always call shutdown so buffered spans are exported; `respan.flush()` is also available when an explicit flush is useful.

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces). Chat and completion calls include prompt, response, model, and real token-usage fields when Dify returns them. Workflow and other Service API calls retain their operation, status, endpoint metadata, inputs, and outputs according to the content setting.

## JavaScript setup

#### Install packages

```bash
npm install @respan/respan @respan/instrumentation-dify@0.1.0 dify-client@3.1.0
```

#### Set environment variables

```bash
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
export DIFY_CHAT_API_KEY="YOUR_DIFY_CHAT_APP_KEY"

# Optional for self-hosted Dify; this must remain a Dify URL.
export DIFY_BASE_URL="https://api.dify.ai/v1"
```

#### Initialize, call Dify, and shut down

```javascript
import { ChatClient } from "dify-client";
import { Respan } from "@respan/respan";
import { DifyInstrumentor } from "@respan/instrumentation-dify";

const respanApiKey = process.env.RESPAN_API_KEY;
const difyApiKey = process.env.DIFY_CHAT_API_KEY;
if (!respanApiKey || !difyApiKey) {
  throw new Error("RESPAN_API_KEY and DIFY_CHAT_API_KEY are required");
}

const respan = new Respan({
  apiKey: respanApiKey,
  instrumentations: [new DifyInstrumentor()],
});
await respan.initialize();

const client = new ChatClient({
  apiKey: difyApiKey,
  baseUrl: process.env.DIFY_BASE_URL,
});

try {
  const response = await client.createChatMessage({
    inputs: {},
    query: "Summarize tracing in one sentence.",
    user: "respan-user",
    response_mode: "blocking",
  });
  if (Symbol.asyncIterator in response) {
    throw new Error("Expected a blocking response");
  }
  console.log(response.data?.answer);
} finally {
  await respan.shutdown();
}
```

Call `await respan.initialize()` before constructing or using Dify clients. Keep the `finally` block so buffered spans are flushed when the application exits.

Run the example as an ES module: save it with an `.mjs` extension or set `"type": "module"` in the application's `package.json`.

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces) and inspect the chat span's prompt, answer, status, model, token usage, and Dify correlation metadata.

## Confirmed API coverage

Both implementations patch the official client's shared HTTP boundary, so a high-level SDK method and its underlying request produce one Dify span rather than duplicates.

> **Note**
>
> This table describes the refreshed Python source and the published JavaScript / TypeScript 0.1.0 package. It is not a statement that every row is present in the currently published Python 0.1.1 package.

| Surface                      | Python client methods                                                                                                             | JavaScript / TypeScript client methods                                                                  | Span mapping                                                                                                       |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Chat                         | `ChatClient.create_chat_message`                                                                                                  | `ChatClient.createChatMessage`                                                                          | Chat span with prompt, answer, model, token usage, user, conversation, task, and message correlation when present. |
| Completion                   | `CompletionClient.create_completion_message`                                                                                      | `CompletionClient.createCompletionMessage`                                                              | Text span with Dify's answer-shaped prompt/completion data and token usage.                                        |
| Workflow                     | `WorkflowClient.run`, `run_specific_workflow` on the refreshed source API                                                         | `WorkflowClient.run`, `runById`                                                                         | Workflow span for `/workflows/*` and pipeline-run endpoints.                                                       |
| Conversations and feedback   | `get_conversations`, `get_conversation_messages`, `rename_conversation`, `message_feedback`                                       | `getConversations`, `getConversationMessages`, `renameConversation`, `messageFeedback`                  | Task spans with request/response content and correlation metadata.                                                 |
| Application and files        | `get_application_parameters`, `file_upload`, plus generic `DifyClient` requests                                                   | `getApplicationParameters`, `fileUpload`, plus generic `DifyClient` requests                            | Task spans; multipart/binary calls retain status and safe request metadata.                                        |
| Knowledge Base and Workspace | Refreshed source examples use `KnowledgeBaseClient.list_datasets`, `run_rag_pipeline`, and `WorkspaceClient.get_available_models` | Confirmed with `KnowledgeBaseClient.listDatasets`, `runPipeline`, and `WorkspaceClient.getModelsByType` | RAG pipeline runs map to workflow spans; control/query operations map to tasks.                                    |

The runnable Python suite also covers propagated Respan context and async chat/workflow behavior when the installed Dify source exposes async clients. The JavaScript / TypeScript suite covers blocking and SSE chat, completion, workflow, Knowledge Base/Workspace, multipart upload, and a controlled HTTP error.

## Streaming and async behavior

The lifecycle behavior in this section describes the refreshed Python source and the published JavaScript / TypeScript 0.1.0 package. The refreshed Python behavior remains pending its corresponding release.

A streaming span stays open until the returned stream is exhausted, closed early, leaves its context manager, or raises. Consume or close streams explicitly; abandoning a stream without either action cannot produce an exact completion timestamp.

**`Python sync stream`**

```python Python sync stream
response = client.create_chat_message(
    inputs={},
    query="Stream one sentence.",
    user="respan-user",
    response_mode="streaming",
)

try:
    for line in response.iter_lines():
        if line:
            print(line)
finally:
    response.close()
```

**`Python async source API`**

```python Python async source API
import os
from dify_client import AsyncChatClient

async with AsyncChatClient(
    os.environ["DIFY_CHAT_API_KEY"],
    base_url=os.getenv("DIFY_BASE_URL", "https://api.dify.ai/v1"),
) as client:
    response = await client.create_chat_message(
        inputs={},
        query="Stream one sentence.",
        user="respan-user",
        response_mode="streaming",
    )
    try:
        async for line in response.aiter_lines():
            if line:
                print(line)
    finally:
        await response.aclose()
```

**`JavaScript`**

```javascript JavaScript
const stream = await client.createChatMessage({
  inputs: {},
  query: "Stream one sentence.",
  user: "respan-user",
  response_mode: "streaming",
});
if (!(Symbol.asyncIterator in stream)) throw new Error("Expected a Dify stream");

for await (const event of stream) {
  console.log(event);
}
```

In JavaScript / TypeScript, consuming the documented `AsyncIterable`, calling `toText()`, or consuming `data`/`toReadable()` completes the span without replacing the original stream API. Binary streams are also observed. In Python, sync `iter_lines`/content methods and async `aiter_lines`/byte/text methods are preserved by response proxies.

If a blocking call throws or a stream fails, the instrumentation records the exception and error status and then preserves the SDK's normal exception behavior. HTTP error responses retain their status; continue using `raise_for_status()` in Python or normal `try`/`catch` handling in JavaScript / TypeScript.

## Content capture and privacy

The options and recursive credential redaction in this section describe the refreshed Python source and the published JavaScript / TypeScript 0.1.0 package. The refreshed Python behavior remains pending its corresponding release.

Content capture is on by default. Disable it when prompts, inputs, outputs, or streamed content must not be exported:

**`Python`**

```python Python
DifyInstrumentor(include_content=False)
```

**`JavaScript`**

```javascript JavaScript
new DifyInstrumentor({ includeContent: false })
```

With content capture disabled, the span still retains the operation, HTTP/error status, correlation fields, and token usage that Dify reports. Credential-like keys are recursively redacted from captured requests and echoed responses even when content capture is enabled, including Workspace credential-validation payloads.

Use `respan.propagate_attributes(...)` in Python to attach customer, thread, trace-group, prompt, or custom metadata context to Dify spans. Propagated metadata and Dify operation details are merged into the single canonical `respan.metadata` JSON attribute.

## Limitations

* This is client-side Service API tracing. It does not expose Dify server-internal model, retrieval, or workflow-node spans unless Dify returns that information through the client response.
* Respan Gateway has no Dify Service API-compatible route. Do not point `DIFY_BASE_URL` at `https://api.respan.ai/api`; keep Dify requests routed to Dify and use this instrumentor for tracing.
* PyPI's released `dify-client` 0.1.10 is sync-only. Python async, dedicated Workflow, Knowledge Base, and Workspace clients require the compatible refreshed source API and should be feature-detected by applications.
* Only calls that pass through the patched official Dify client boundary are traced. Direct HTTP calls and unrelated Dify clients are outside this integration.
* When multiple instrumentor instances overlap, the first active instance's content policy remains in effect until the last one is deactivated.