---
title: DeepSeek Harness Provider
---

# DeepSeek Harness Provider

> **Two different DeepSeek things, and only one of them is new.** `DeepSeek` runs DeepSeek
> **models** inside the Claude Code harness. `DeepSeek Harness` runs DeepSeek's **own** agent
> harness — a separate product with its own tools, skills and runtime modes. If you are looking
> for cheaper DeepSeek models, you want the first one.

## What it is

**DeepSeek Harness** is DeepSeek's own agent harness, published as the `dsh` CLI. Omniscio runs
it as a session provider the same way it runs Gemini and Kimi Code: a kept-alive child process
speaking the **Agent Client Protocol** (ACP) over stdio.

- The engine spawns `dsh --profile acp`.
- It is a **persistent-external** engine — one long-lived process per session, not one process
  per turn.
- Sessions stream as they work, and a second message continues the same conversation.

Verified live against `dsh` 0.1.5-rc.2: the handshake, creating a session, sending a prompt,
streaming the answer back, and a clean `end_turn` finish.

## Where to find it

### Enabling it

Two things must be in place, and Omniscio reports the first gap it finds:

1. **Settings → Accounts → Allow DeepSeek Harness sessions** — the opt-in toggle, **off by
   default**. Nothing spawns until you turn it on.
2. **The `dsh` CLI on your PATH.** The account card links to the install page when it is missing.
3. **A DeepSeek API key** in Settings → Accounts. This is the **same key** the existing DeepSeek
   provider uses — you do not add a second one.

> **DeepSeek Harness is a developer preview.** DeepSeek ships it as `dsh` 0.1.x and says so. It
> is offered here as a normal pickable engine rather than hidden behind a flag, so treat it as
> preview-quality; the opt-in toggle above is always your off switch.

## How it behaves

### Choosing a model

Pick a model and a reasoning effort on the session, like any other engine. dsh selects both through
the **protocol session** rather than a command-line flag, so Omniscio asks the engine what it offers
on the session it just created and sets the choice there — the picker only ever sends a value the
running `dsh` advertised. The four models offered are the same four the DeepSeek provider offers
(V4.1 Flash is the default), and the effort offers Low, High and Max.

The choice takes effect **when the session starts**. Changing it on an running session is saved for
the next one: the `dsh` process is kept alive for the session's whole life, and no Omniscio engine
re-configures a running child.

If a choice cannot be applied — the engine no longer offers that model, or it refuses the value —
the session still starts on the engine's default and says so in the transcript.

### Cost

Turns on this engine report **no cost figure**. The protocol sends a usage frame, but it carries
*context-window occupancy* — how full the conversation is — not a billable per-turn input/output
split, so there is nothing to price. Omniscio surfaces this as "cost not reported" rather than a
misleading `$0`.

### A slow first start is normal

The first time a `dsh` session starts, the CLI resolves its plugin profile — a few hundred
modules. On a busy machine that measured **over two minutes**. Omniscio deliberately allows a
long first start rather than declaring the engine broken, and later starts are fast.

### Running out of room

If a turn is rejected because dsh's own working memory outgrew the model's window (usually a
command that printed a huge amount of output), the message says it ran out of room and that the
conversation is saved. Omniscio has already replaced the overflowed `dsh` process, so your next
message starts fresh on a compact copy of the conversation — usually no new session is needed.
If it still runs out of room, the conversation may be too long for the model, so start a new session.

### What v1 does not do

Stated plainly, because each is a real limit rather than an oversight:

- **No image input.** dsh itself reports it does not accept images.
- **A server whose command cannot be resolved to a real, spawnable path.** The project's MCP servers
  do ride the session, but this engine refuses the WHOLE session over one server it cannot start, so
  Omniscio resolves each command first and holds back only what it cannot — naming those servers in
  the transcript rather than losing the session, or the other servers with it.
- **No SSH / remote sessions.**
- **No automatic resume after a crash.** The protocol offers resume, but it has not been proven
  here, so dsh is deliberately left out of the crash-recovery path rather than promising a
  resume that might not arrive.
- **Permissions auto-approve.** A plain turn never asks, and the tool-approval path has not been
  characterised, so v1 claims nothing.

## For agents

### How it works under the hood

`DshAcpClient` extends the shared `SlimAcpSessionClient` (the same base Kimi Code and Hermes
use), so the child spawn, handshake, session creation, prompt/cancel/stop and event dispatch are
shared code. The client supplies only the per-engine parts: the binary resolver, the
`--profile acp` arguments, the environment, and the ACP config-option delivery that carries the
per-session model + reasoning effort (it issues `session/new` itself, because the shared base
returns only the session id and would discard the `configOptions` the choice must be matched
against). The ladder that decides WHAT to send lives once in a services-side resolver the client
imports, so Kimi Code and Hermes override nothing and stay byte-identical.

Three seams were added to that shared base for this engine, and all three are additive:

- **`buildSpawnEnv()`** — an overridable hook for engine-specific environment. Most ACP engines
  authenticate from their own config and inject nothing; dsh is the first that Omniscio holds a
  credential for, so it injects `DEEPSEEK_API_KEY`. dsh advertises no ACP auth methods, which
  makes the environment the only channel.
- **`startHandshakeTimeoutMs`** — the handshake deadline was a fixed 30 seconds, which a
  multi-minute cold start would fail outright. It is now per-engine, still 30 seconds by
  default, with dsh asking for a longer one.
- **`requiresAbsoluteMcpCommands`** — off by default, and set only by this engine: its
  `session/new` rejects the WHOLE session when one MCP server's command is not an absolute path,
  so the base resolves each command to a spawnable absolute path and holds back (naming) what it
  cannot.

The `session/update` frames are mapped to Omniscio events by the shared, pure
`acp-update-translator`.

### Contract

This engine's quirks are a section of the provider-registry contract family — never a
freestanding peer contract ([provider-registry-contract.md](../../.claude/memory/contracts/provider-registry-contract.md)).

## Related

[Kimi Code](kimi-provider.md) and [Gemini](gemini-provider.md) are the other engines that speak
the Agent Client Protocol the same way, so their pages describe the same session behaviour.
[DeepSeek](deepseek-provider.md) covers the DeepSeek **models** provider — the different thing
this page opens by warning about — and [Who pays & who serves](model-vendors.md) covers who pays
for those model sessions and which company serves them. The harness is not on that list: it always
runs on your own DeepSeek key.
