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 | full
  • toolMetaAllowlist: whitelists top-level keys from tool/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.

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:

  1. 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.
  2. LANGFUSE_HOST determines 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.
  3. Use dsh --profile web --dump-config to view the synthesized configuration; you should see the # == dsh-plugin-langfuse layer and the session-telemetry-langfuse entry.
  4. After the next conversation turn, traces should appear in the corresponding region’s console.
  5. To uninstall: dsh plugin --profile web remove dsh-plugin-langfuse will 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 content policy). 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.json engines).

Region and Keys

  • Ensure LANGFUSE_HOST (or exporter.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