{"slug": "deepseek-harness-observability-monitoring-with-opentelemetry", "title": "DeepSeek Harness Observability & Monitoring with OpenTelemetry", "summary": "DeepSeek's open-source agent harness, DeepSeek Harness, now supports observability and monitoring through a new Apache-2.0 plugin, @loongsuite/dsh-plugin, which exports OpenTelemetry traces to SigNoz. The plugin, compatible with DeepSeek Harness 0.1.0-rc.6 to below 0.2.0, captures every turn as a trace, including reasoning rounds, model calls with token counts, and tool executions. By default, prompts and responses are not captured, but enabling captureContent increases payload size from 6,350 bytes to 73,078 bytes for a single-tool turn.", "body_md": "## What is DeepSeek Harness Observability?\n\n[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`\n\n) is DeepSeek's open-source agent harness. It has no OpenTelemetry export of its own, so instrumenting it means installing one plugin. Once installed, every turn becomes a trace: the agent loop, each reasoning round, each model call with its token counts and time to first token, and each tool execution.\n\nWith full DeepSeek Harness observability in SigNoz, you can see how much your team is spending in tokens and on which models, how many round trips a single request actually takes, which tools the agent reaches for, and where turns fail.\n\n## Prerequisites\n\n- SigNoz setup (choose one):\n[SigNoz Cloud account](https://signoz.io/teams/)with an active ingestion key- Self-hosted SigNoz instance\n\n- DeepSeek Harness 0.1.0-rc.6 or later, below 0.2.0. See the\n[DeepSeek Harness repository](https://github.com/deepseek-ai/deepseek-harness) - Node.js 22.19.0 or later\n- A\n`DEEPSEEK_API_KEY`\n\n, or another provider configured in your profile\n\n## Monitor DeepSeek Harness with OpenTelemetry\n\nInstrumentation comes from [ @loongsuite/dsh-plugin](https://github.com/loongsuite/dsh-plugin), an Apache-2.0 plugin that hooks the harness lifecycle and exports OTLP over HTTP.\n\n**Step 1:** Install the plugin into each profile you use\n\n```\ndsh plugin --profile headless add @loongsuite/dsh-plugin\ndsh plugin --profile web add @loongsuite/dsh-plugin\n```\n\nPlugins are installed per profile, so a plugin added to `headless`\n\ndoes nothing when you launch `web`\n\n. Confirm it loaded:\n\n```\ndsh --profile headless --dump-config | grep loongsuite\n```\n\nYou should see `id: loongsuite-observability`\n\n.\n\n**Step 2:** Point the plugin at SigNoz\n\n```\nexport OTEL_SERVICE_NAME=dsh-agent\nexport OTEL_EXPORTER_OTLP_ENDPOINT=\"https://ingest.<region>.signoz.cloud:443\"\nexport OTEL_EXPORTER_OTLP_HEADERS=\"signoz-ingestion-key=<your-ingestion-key>\"\n```\n\n**Verify these values:**\n\n`<region>`\n\n: Your[SigNoz Cloud region](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).`<your-ingestion-key>`\n\n: Your SigNoz[ingestion key](https://signoz.io/docs/ingestion/signoz-cloud/keys/).\n\n**Step 3:** Run the harness\n\n```\ndsh --profile headless \"list the files in this directory and summarise the project\"\n```\n\nSpans are batched, so allow a few seconds after the turn finishes before looking in SigNoz.\n\n## View DeepSeek Harness Traces in SigNoz\n\nOpen the Traces explorer and filter on `gen_ai.agent.system = 'deepseek-harness'`\n\n. Each turn arrives as its own trace.\n\nOpen any `enter_ai_application_system`\n\nspan to see the full turn. The waterfall shows each reasoning round, the model call inside it, and every tool the agent executed.\n\nThe plugin tags every span with `gen_ai.span.kind`\n\n, which is the attribute to filter and group by:\n\n`gen_ai.span.kind` | Span name | What it covers |\n|---|---|---|\n`ENTRY` | `enter_ai_application_system` | One turn, the root span |\n`AGENT` | `invoke_agent deepseek-harness` | The agent loop, with turn-level token totals |\n`STEP` | `react step` | One reasoning round |\n`LLM` | `chat <model>` | One model call, with tokens and time to first token |\n`TOOL` | `execute_tool <tool>` | One tool execution |\n\nFilter on `gen_ai.span.kind`\n\nrather than on the span name, since names embed the model and tool name and change per call.\n\n## Prompts and Responses Are Not Captured by Default\n\n`captureContent`\n\nis `false`\n\n, so spans carry structure, timings, and token counts but no prompt or completion text. Enable it with `captureContent: true`\n\nin the profile config, or `OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_ONLY`\n\n.\n\nTwo things to weigh before turning it on. Anything in the context window, including source code and file contents, is written to your backend. And the payload grows sharply: the same single-tool turn measured 6,350 bytes with capture off and 73,078 bytes with it on, mostly because `gen_ai.tool.definitions`\n\nrepeats the full schema of every registered tool on each model call.\n\nNote that `dsh.session.cwd`\n\nrecords the absolute working directory on every span even with content capture off.\n\n## DeepSeek Harness Observability Dashboard\n\nThe [DeepSeek Harness dashboard](https://signoz.io/docs/dashboards/dashboard-templates/deepseek-harness-dashboard/) gives you token spend and cache efficiency, turn and session volume, model latency, tool activity, and error breakdown out of the box.\n\n## Troubleshooting DeepSeek Harness Observability\n\n### No data in SigNoz\n\nAn expired or wrong ingestion key fails silently. The harness prints a normal answer and exits successfully while the exporter receives a 401, so nothing in the terminal tells you anything is wrong. Test the key directly:\n\n```\ncurl -i -X POST \"https://ingest.<region>.signoz.cloud/v1/traces\" \\\n  -H \"content-type: application/json\" \\\n  -H \"signoz-ingestion-key: <your-ingestion-key>\" \\\n  -d '{\"resourceSpans\":[]}'\n```\n\nA working key returns `200`\n\nwith `{\"partialSuccess\":{}}`\n\n. An expired one returns `401`\n\nwith `Expired key`\n\n.\n\n### The plugin does not appear in the config\n\nPlugins are per profile. Run `dsh --profile <profile> --dump-config | grep loongsuite`\n\nfor the profile you actually launch, and add the plugin to that profile if it is missing.\n\n### Subagent work is missing from the parent trace\n\nA spawned subagent opens its own trace with its own root span, rather than nesting under the parent turn. There is no span link between them. Join them on attributes instead: the subagent's spans carry `dsh.session.parent_id`\n\n, `dsh.session.origin = 'subagent'`\n\n, and `dsh.session.delegation_depth`\n\n.\n\n### A failing tool shows as a successful span\n\nOnly tools that report failure explicitly, such as an MCP tool returning `isError`\n\n, set the span status to error and add `error.type = 'TOOL_ERROR'`\n\n. A shell command exiting non-zero still records a successful span, so tool error counts based on span status will undercount.\n\n### Do not confuse this with the built-in telemetry plugin\n\nDeepSeek Harness ships its own `dsh-session-telemetry-otel`\n\nplugin, disabled by default through `DSH_TELEMETRY_MODE`\n\n, which sends OTLP logs to DeepSeek's own endpoint. That is DeepSeek's product analytics and is unrelated to this setup.\n\n## Related integrations\n\nInstrument the other AI coding agents your team runs, using the same OpenTelemetry pipeline:\n\n[Monitor Claude Code with OpenTelemetry](https://signoz.io/docs/claude-code-monitoring/)- track token usage, cost, session activity, and tool decisions[OpenCode observability with OpenTelemetry](https://signoz.io/docs/opencode-observability/)- another agent that instruments through a plugin rather than natively[Monitor OpenAI Codex with OpenTelemetry](https://signoz.io/docs/codex-monitoring/)- trace Codex runs from the IDE extension and the CLI[Grok Build observability with OpenTelemetry](https://signoz.io/docs/grok-build-observability/)- token usage, tool activity, and startup latency from its native exporter[Monitor GitHub Copilot with OpenTelemetry](https://signoz.io/docs/github-copilot-monitoring/)- trace Copilot chat requests, models, and token spend\n\nBrowse [all LLM observability integrations](https://signoz.io/docs/llm-observability/) to instrument the rest of your stack.", "url": "https://wpnews.pro/news/deepseek-harness-observability-monitoring-with-opentelemetry", "canonical_source": "https://signoz.io/docs/deepseek-harness-observability", "published_at": "2026-08-19 00:00:00+00:00", "updated_at": "2026-08-20 07:13:03.325706+00:00", "lang": "en", "topics": ["developer-tools", "ai-agents", "ai-infrastructure"], "entities": ["DeepSeek", "DeepSeek Harness", "@loongsuite/dsh-plugin", "SigNoz", "OpenTelemetry"], "alternates": {"html": "https://wpnews.pro/news/deepseek-harness-observability-monitoring-with-opentelemetry", "markdown": "https://wpnews.pro/news/deepseek-harness-observability-monitoring-with-opentelemetry.md", "text": "https://wpnews.pro/news/deepseek-harness-observability-monitoring-with-opentelemetry.txt", "jsonld": "https://wpnews.pro/news/deepseek-harness-observability-monitoring-with-opentelemetry.jsonld"}}