Foreword¶
When running agents with DeepSeek Harness (DSH), a single conversation often involves interwoven model calls, tool executions, and sub-agent forks. When issues arise and you need to trace back to “which step was slow” or “which tool call returned an error,” terminal logs alone often struggle to form a complete chain. The official harness includes built-in session telemetry seams based on OpenTelemetry, with default support for OTLP logs export. If you are already using Langfuse for LLM observability and prefer traces to land directly in the Langfuse console, you need a backend that bridges this seam.
This article introduces the community plugin dsh-plugin-langfuse (maintained by linyp). It implements the harness-exposed @deepseek-ai/dsh-session-telemetry interface, exporting each turn as an OpenTelemetry trace and mapping it to Langfuse’s OTLP endpoint following GenAI semantic conventions. The plugin is categorized as an “online tool” in the SkillHub directory, currently has 11 GitHub stars, is licensed under MIT, and the latest version is 0.5.1.
What Is This¶
dsh-plugin-langfuse is a community plugin for DSH (with the dsh-plugin topic), and is not part of the official deepseek-harness repository. Its positioning can be summarized as:
Langfuse observability for DeepSeek Harness: Export agent conversations as OpenTelemetry trace trees (GenAI semconv) and write them to the Langfuse OTLP endpoint.
Specific behaviors include:
- Each turn corresponds to a trace: model steps are mapped to generation spans, and tool calls to tool spans.
- Aggregates multiple conversation turns by session.
- Records canonical user feedback as Langfuse Scores.
- Preserves fork/subagent lineage relationships.
It serves as an alternative backend to the official OTLP-logs exporter; only one telemetry backend can be mounted in the same context, and duplicate loading will throw an error.
Core Functionality¶
Trace Structure and Semantics¶
The plugin translates harness session events into OpenTelemetry traces, adhering to GenAI-related conventions, and sends them via OTLP/HTTP to Langfuse. By default, the exporter includes the x-langfuse-ingestion-version: 4 header to accommodate the Langfuse v4 data model. If you explicitly provide a header with the same name in your configuration, your configuration takes precedence.
Export Mode (mode)¶
| Mode | Meaning |
|---|---|
FULL |
Real-time export of every conversation |
FEEDBACK_ONLY |
Only replays and exports canonical session logs when the user records feedback |
DISABLED |
Default; no exporter is constructed, and no data is sent from the process |
Terminology and consent semantics are consistent with the official telemetry backend. When installed via the profile bundle and configured with Langfuse keys, the bundle layer enables FULL if a key is present, otherwise DISABLED. Setting LANGFUSE_TELEMETRY_MODE=FEEDBACK_ONLY narrows the scope to feedback-triggered export only.
Feedback Scores¶
Optionally exports canonical feedback/record events as Langfuse TEXT Scores. When installed via the bundle path, it is automatically enabled if both LANGFUSE_PUBLIC_KEY and LANGFUSE_SECRET_KEY exist. In an explicit cordis.yml line, you need to enable feedbackScores.enabled yourself.
Content and Privacy Controls¶
The content section can limit exported fields:
turnInputMode:none|user(default, aggregates only human messages) |user-and-context(includes plugin-injected context)cwdMode:omit(default) |basename|fulltoolMetaAllowlist: whitelists top-level keys fromtool/result.meta
Additionally, maxAttributeChars (default 32768) truncates span attributes, while full bytes are still retained in the canonical session log.
Correlation with Host¶
If DSH is embedded in another host, you can use correlation to write userId / sessionId into langfuse.user.id / langfuse.session.id, facilitating merging with host traces on the Langfuse side.
Delivery Status¶
LangfuseSessionTelemetryBackend.status() returns a synchronous snapshot, including overall and per-channel status (disabled / starting / healthy / degraded / stopped), trace batch count, consecutive failure count, Score queue statistics, etc., allowing you to determine if export is degraded during runtime.
Installation and Enabling¶
The following assumes dsh CLI is installed. If running from the deepseek-harness source, execute pnpm run build in the checkout root directory, then replace dsh in the commands with pnpm dsh; the profile remains web.
Install as a Profile Bundle (Recommended)¶
The plugin includes a cordis.patch.yml that disables the base profile’s session-telemetry-otel line and mounts this backend:
dsh plugin --profile web add dsh-plugin-langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-…
export LANGFUSE_SECRET_KEY=sk-lf-…
# Optional, default is https://cloud.langfuse.com (EU); the plugin reads LANGFUSE_HOST, not the SDK's LANGFUSE_BASE_URL
export LANGFUSE_HOST=https://us.cloud.langfuse.com
dsh web
Notes:
- The bundle layer and environment variables are read at process startup; running instances need to be restarted in a shell with exported variables for changes to take effect.
LANGFUSE_HOSTdetermines which region’s Langfuse console the data lands in; project keys are region-bound, so traces from US projects will not appear in the EU console.- Use
dsh --profile web --dump-configto view the synthesized configuration; you should see the# == dsh-plugin-langfuselayer and thesession-telemetry-langfuseentry. - After the next conversation turn, traces should appear in the corresponding region’s console.
- To uninstall:
dsh plugin --profile web remove dsh-plugin-langfusewill remove both dependencies and the patch layer.
Explicit cordis.yml Configuration¶
If not using the bundle, you can add a line (excerpt) to cordis.yml:
- id: session-telemetry-langfuse
name: dsh-plugin-langfuse
config:
mode: FULL
exporter:
url: https://cloud.langfuse.com/api/public/otel/v1/traces
auth:
publicKey: !!js process.env.LANGFUSE_PUBLIC_KEY
secretKey: !!js process.env.LANGFUSE_SECRET_KEY
feedbackScores:
enabled: true
url: https://cloud.langfuse.com/api/public/scores
exporter.url must be the complete traces path (…/api/public/otel/v1/traces); auth is mutually exclusive with an Authorization header in an explicit exporter.headers. Configuration errors (missing URL, credential conflicts, illegal mode, etc.) will throw an error directly during the plugin loading phase, avoiding silent failures.
Typical Usage¶
Minimal Loop: Install → Configure Keys → Run Web¶
dsh plugin --profile web add dsh-plugin-langfuse
export LANGFUSE_PUBLIC_KEY=pk-lf-…
export LANGFUSE_SECRET_KEY=sk-lf-…
dsh web
After completing one or two conversation turns in the web interface, open the Langfuse project to view the trace tree: you should see generation, tool spans, and session grouping.
Export Only When User Feedback Exists¶
Suitable for scenarios where real-time export is more sensitive:
export LANGFUSE_TELEMETRY_MODE=FEEDBACK_ONLY
dsh web
After the user records canonical feedback via the harness, the plugin replays the session log and exports it.
Check Synthesized Configuration (Without Starting an Instance)¶
dsh --profile web --dump-config
Verify that the mode and exporter address of session-telemetry-langfuse meet expectations.
Applicable Scenarios and Considerations¶
Who Is This For
- Teams already using Langfuse in production or staging environments for LLM tracing, scoring, and debugging.
- Developers who need to string DSH multi-turn agent conversations and tool calls into a queryable chain and care about fork/subagent lineage.
- Users who want to reuse the harness’s official telemetry seams but do not wish to build an OTLP pipeline themselves.
Runtime Environment and Permissions
- The plugin runs with the permissions of the current dsh process; export requests carry the Langfuse keys you configure and may include conversation inputs and tool metadata (depending on the
contentpolicy). Before installation, it is recommended to read the source code and MIT license to confirm the export scope complies with your organization’s requirements. - Requires Node.js
^22.19 || >=24(see package.jsonengines).
Region and Keys
- Ensure
LANGFUSE_HOST(orexporter.url) matches the Langfuse region where the keys belong.
Relationship with the Official Backend
- This plugin is mutually exclusive with the official
session-telemetry-otel; the bundle will automatically disable the latter. Do not manually mount two telemetry backends simultaneously.
Ecosystem Note
- DSH follows an “everything is a plugin” philosophy; the plugin directory on SkillHub is maintained by the community and has no official affiliation with DeepSeek / High-Flyer. The installation commands in this article are based on the README and directory registration; do not self-assemble undocumented
dsh plugin add github:…forms.
Conclusion¶
dsh-plugin-langfuse connects the DSH session telemetry seam to Langfuse: OpenTelemetry traces, feedback scores, session aggregation, and fork lineage can all be viewed in a single chain within the Langfuse console. If you are already using Langfuse, install via the profile bundle, configure the keys for the corresponding region, and restart dsh web to verify.
- SkillHub directory page: https://www.skillhub.cn/plugins/linyp/dsh-plugin-langfuse
- GitHub repository: https://github.com/linyp/dsh-plugin-langfuse