Skip to content

DeepSeek Harness

@telemai/dsh-plugin adds telem_search and telem_fetch as native tools in DeepSeek Harness, registered globally so every agent preset sees them.

  • Node.js 22+
  • pnpm on your PATH — dsh plugin installs into a profile through pnpm.
  • DSH installed — dsh on your PATH, with the profile you use (web or headless) initialized.
  1. Get an API key in the Telem console, under API keys in your project — see Authentication.

  2. Install into your profile. DSH installs plugins per profile; repeat with --profile headless if you use that one too.

  3. Set your key. Export TELEM_API_KEY, add it to $DSH_HOME/.credentials.yaml, or run npm create @telemai — the plugin reads all three (see Credentials).

Terminal window
dsh plugin --profile web add @telemai/dsh-plugin
export TELEM_API_KEY=... # your key (or run `npm create @telemai`)

Confirm: dsh --profile web --dump-config lists a telem row, and the model now has telem_search and telem_fetch.

Two tools:

  • telem_search — runs one or more search queries as a single Telem interaction and returns every provider’s results, provider-attributed, in one normalized envelope.
  • telem_fetch — reads up to 5 whole web pages in one call, fetched as one interaction and rendered one section per URL.

Both run through DSH’s own tool runtime: arguments are validated by DSH, cancellation and DSH’s tool timeout policy apply, and oversized results follow DSH’s spill policy. Each result carries the backend session id in the tool’s durable metadata (visible in DSH’s session log and UI), never in the model text.

The plugin tells the model to prefer telem_search over an overlapping public-web search tool unless you ask otherwise, Telem is unavailable, or the task needs a capability Telem does not expose. That is soft preference only — the plugin does not disable DSH’s built-in web_search. To make Telem the only search tool:

  • headless / TUI profiles: tool-web is a host row in DSH’s base bundle — add - id: tool-web with disabled: true to your profile’s cordis.patch.yml.
  • Web profile: the host row is already off there and each shipped, read-only preset mounts tool-web per session — copy the preset you use into $DSH_HOME/.agent-presets/ without that row.

DSH’s built-in web_fetch is off by default.

One file, every harness. Telem options live in .telem/telem.json — a project one you can commit so the whole team inherits it, and a user one at ~/.telem/telem.json — the same pair the opencode, pi, Hermes and Claude Skill surfaces read. On DSH the project is the calling agent’s session directory.

{
"tier": "extended",
"providersInclude": ["exa", "brave"]
}

The three keys most people reach for:

File key Env fallback Meaning
tier TELEM_TIER Named result-field tier: minimalist, default, extended, or max
fields TELEM_FIELDS (comma-separated) Explicit normalized fields; mutually exclusive with tier
providersInclude TELEM_PROVIDERS_INCLUDE (comma-separated) Replace the deployment’s provider set

Full parameter reference → — every key, its env fallback and how the levels compose.

DSH resolves per key and per call, with one level above the files that no other surface has — the plugin’s own row in your profile patch:

  1. this plugin’s row config in your profile patch;
  2. <project>/.telem/telem.json;
  3. ~/.telem/telem.json;
  4. TELEM_* environment variables.

Edit a file and the next search picks it up, no restart. Nothing configured means the server’s defaults; a malformed file or an ignored key is reported on stderr once per edit. Unlike opencode and pi, DSH has no deprecated host-specific config file — there was never one to keep reading.

Plugin-level config is the telem row in ~/.dsh/profiles/<profile>/cordis.patch.yml (or $DSH_HOME/cordis.patch.yml for every profile). A patch replaces the row’s whole config, so restate every key you keep:

- id: telem
config:
tier: max
searchTimeoutMs: 60000 # enforced by DSH's timeout policy (default 60000)
fetchTimeoutMs: 60000
apiKeyEnv: TELEM_API_KEY # a credential NAME, never a value

TELEM_BASE_URL (or the plugin’s baseUrl) defaults to the hosted service at https://router.telem.ai. Credentials have no config-file key and are resolved on every call, in this order:

  1. DSH’s credential service, asked for TELEM_API_KEY (or the apiKeyEnv you configure) — process environment, then $DSH_HOME/.credentials.yaml, then .env files;
  2. TELEM_API_KEY in the environment;
  3. ~/.telem/credentials.json, the file npm create @telemai writes (it may also set baseUrl).

A rotated key reaches the next call with no restart. The key is never written to cordis.patch.yml, argv, logs, or tool output.

In-process subagents (spawn/fork) inherit the tools, and every search they make carries a frozen snapshot of the parent conversation as trajectory lineage. Out-of-process backends (subagent-acp, subagent-claude-code, subagent-codex, subagent-dsh-sdk) run without this plugin — no Telem tools there and no lineage.

Nothing in the credential chain resolved a key. Export TELEM_API_KEY, add it to $DSH_HOME/.credentials.yaml, or run npm create @telemai.

answered without the V2 normalized contract

Section titled “answered without the V2 normalized contract”

The backend at TELEM_BASE_URL predates the normalized search response the plugin reads. Upgrade the backend, or point TELEM_BASE_URL at a current deployment — this is a deliberate hard stop rather than a silent empty result.

pnpm is not on your PATH. DSH installs plugins into a profile through pnpm.

The child composition’s toolFilter hides global tools, or the child runs out of process — the out-of-process backends listed under Subagents never load this plugin.