Dify (tracing)
Dify 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.
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.
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.
Set up Respan
Create an account at platform.respan.ai and grab an API key .
Packages and example projects
Paste this into your coding agent:
Help me set up Respan tracing with the Dify integration.
Follow https://www.respan.ai/docs/integrations/dify.mdAvailability
| 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
pip install respan-ai respan-instrumentation-dify "dify-client>=0.1.10,<0.2.0"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
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
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 . 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
npm install @respan/respan @respan/instrumentation-dify@0.1.0 dify-client@3.1.0Set environment variables
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
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 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.
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.
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()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:
DifyInstrumentor(include_content=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_URLathttps://api.respan.ai/api; keep Dify requests routed to Dify and use this instrumentor for tracing. - PyPI’s released
dify-client0.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.