Preface¶
For developers who have already built applications with the Vercel AI SDK, the typical entry point for orchestration is generateText / streamText: you only need to swap the provider to switch models, and tools, streaming output, and cancellation signals all follow the same set of interfaces. DeepSeek Harness (command name dsh) takes a different approach—it is an open-source agent runtime developed by DeepSeek AI, whose official repository deepseek-ai/deepseek-harness states its core philosophy as “everything is a plugin”: agent loops, tools, skills, and sessions can all be combined at the configuration layer. The two frameworks operate independently, and the common outcome is either migrating your business into dsh or writing another process wrapper on your own.
The community package ai-sdk-provider-dsh does something straightforward: it wraps a dsh runtime behind the AI SDK’s LanguageModel interface. The calling method is identical to that of a regular language model, but what actually runs is the agent loop inside the harness, with tools executed internally within the harness. The repository README compares it to how ai-sdk-provider-claude-code powers Claude Code, keeping the orchestration surface within the AI SDK.
There is also an independent plugin directory deepseek-harness-plugin.com. It has no official affiliation with DeepSeek / HyperMind and should not be treated as an official app store. This article is compiled after cross-checking the directory’s detail pages, GitHub repository READMEs, package.json, source code, and npm pages.
What is this¶
ai-sdk-provider-dsh is an open-source community AI SDK provider maintained by krislavten, with its repository at krislavten/ai-sdk-provider-dsh. It uses the MIT license and is primarily written in TypeScript. The directory lists it under “Models and Providers”, with an inclusion date of 2026-08-14. The current npm version is 0.2.0 (CHANGELOG dated 2026-08-14; npm publish time 2026-08-13). As of the time of this article’s review, the GitHub star count is 2 (the directory page showed 1 at the time, so refer to the repository instead).
It solves the following types of tasks:
- Existing applications already orchestrated with the AI SDK that want to call dsh’s full agent instead of just making a single chat completion call
- Need harness capabilities such as bash, file read/write, subagents, and session persistence, while not wanting to replace the streamText layer
- Want the same build to run on both AI SDK v6 and v7
In terms of implementation, each provider instance will lazily start a dsh child process, with the two parties communicating via stdio JSON-RPC (the dsh SDK protocol). doGenerate / doStream converts the AI SDK’s LanguageModelV3CallOptions into a dsh prompt, then maps the runtime’s session.event back to the AI SDK’s streaming chunks.
Two points need clarification first. The installation command given on the directory page is dsh plugin add github:krislavten/ai-sdk-provider-dsh; after checking package.json, this package does not declare a dsh.bundle. The main installation path in the README is npm install ai-sdk-provider-dsh: it starts a bundled runtime in a Node application, rather than attaching a model card to an existing dsh process. Both commands will be listed below, and the usage shall prevail per the repository README.
Core Features¶
One build supports both AI SDK v6 and v7¶
The language model implementation in the source code uses specificationVersion: 'v3', adhering to the AI SDK’s LanguageModelV3 interface. The compatibility matrix given in the README is as follows:
| AI SDK | @ai-sdk/provider |
Status |
|---|---|---|
ai@^6 |
@ai-sdk/provider@^3 |
Supported |
ai@^7 |
@ai-sdk/provider@^4 |
Supported (v7 treats V3 models as first-class citizens) |
The peer dependencies in package.json match the table above: ai is ^6.0.0 || ^7.0.0, and @ai-sdk/provider is ^3.0.0 || ^4.0.0. The runtime requires Node.js >=22.19, and only ESM module format is supported.
Runtime bundled into the package, version pinned¶
dsh is currently in developer preview (0.1.0-rc.x), and the official README notes that breaking changes will occur. This provider pins exactly the harness family to 0.1.0-rc.6, with exact versions for packages like @deepseek-ai/dsh-sdk-jsonrpc-demo, @deepseek-ai/dsh-bash-local, and @deepseek-ai/dsh-tool-fs in its dependency list, rather than using version ranges. The README’s stance is that upgrading the pinned version must be an explicit decision, not relying on range drift.
The package includes a default combination runtime/cordis.yml, as well as the dsh-jsonrpc-agent executable entry point. Creating a provider instance will start a working runtime without needing to install the dsh CLI separately.
The model-side tools exposed by the default combination are:
- bash (foreground execution, background runs are disabled in the default combination)
- read / write / edit (local file system)
- subagent
- todo_write
There is also JSONL session persistence and automatic context compression. Tools are executed inside the harness: the stream will include a tool chunk with providerExecuted: true, and the AI SDK will not execute them again. This is the biggest difference between it and a regular “model provider”: you are calling an agent with tools, not a bare model.
The default cordis.yml has skills.enabled set to false. To enable skills, use dsh’s native mechanism: discover SKILL.md files from .dsh/skills, .agents/skills, and $DSH_HOME/skills; the README explicitly states that reskill’s skills.json / skills.lock will not be applied. MCP, mentioned in the directory’s introduction, has no corresponding plugin in this default combination and is not available out of the box.
Multi-turn conversations, metadata, and error classification¶
Each provider instance corresponds to one runtime child process. The sessionId defaults to a new UUID; if you set a fixed value, subsequent calls will continue the same harness session (the runtime persists session logs). The repository’s examples/multi-turn.ts has an end-to-end validation using “write a secret code in the first round, then ask for it in the second round”.
Each response will include data under providerMetadata['dsh']:
| Field | Meaning |
|---|---|
sessionId |
Which harness session this call ran on |
turnId |
The last observed turn number (optional) |
terminalReason |
The reason when the termination type is not completed: aborted, error, max-tokens, blocked, interrupted |
The location to retrieve metadata varies by major version: For AI SDK v7, look at result.finalStep.providerMetadata (for streamText, use await stream.finalStep); for v6, look at result.providerMetadata.
Failures at the runtime boundary will be categorized as AI SDK’s APICallError, with a cleaned-up tail of stderr attached to the error message. Transport disconnections and request timeouts are retryable; protocol violations and runtime request rejections are not retryable. When selecting deepseek-official but not having a DEEPSEEK_API_KEY, an error mapped to LoadAPIKeyError will be thrown promptly, rather than silently returning empty output (except in replay mode with DSH_SNAPSHOT_FILE).
Installation and Activation¶
The installation command on the directory page is as follows, to be run in the DeepSeek Harness terminal:
dsh plugin add github:krislavten/ai-sdk-provider-dsh
For reproducible installations, the directory page recommends pinning to a specific commit hash:
dsh plugin add github:krislavten/ai-sdk-provider-dsh#commit
Replace commit with the actual hash. The plugin runs with the permissions of the current dsh process, and may execute code during installation. Please check the source repository and license before installing.
For the main use case of “calling dsh in an AI SDK application”, the repository README recommends using npm:
npm install ai-sdk-provider-dsh
Credentials use runtime environment variables:
export DEEPSEEK_API_KEY=sk-...
export DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_API_KEY is required when using deepseek-official. DEEPSEEK_BASE_URL is optional and can point to any OpenAI-compatible gateway.
The default combination on Linux depends on node-pty, which will be compiled locally during installation with no prebuilt packages available. If compilation fails in minimal containers, WSL without libc6-dev, or similar environments, use the package’s included runtime/cordis.minimal.yml (no bash support). package.json also lists node-pty and @deepseek-ai/node-addon-landlock-run as onlyBuiltDependencies, which will run native builds during installation and require similar caution.
Typical Usage¶
All examples below are from the repository README and examples/ directory; replace the import path with the published package name. After use, call await dsh.close() to tear down the child process (idempotent); the teardown sequence is EOF → SIGTERM → SIGKILL.
AI SDK v7: streamText¶
v7 uses instructions to write system prompts:
import { streamText } from "ai";
import { createDsh } from "ai-sdk-provider-dsh";
const dsh = createDsh({
runtime: { provider: "deepseek-official", model: "deepseek-v4-flash" },
});
const result = streamText({
model: dsh.languageModel("deepseek-v4-flash"),
instructions: "You are a coding agent.",
prompt: "run the tests",
});
const text = await result.text;
console.log(text);
The object returned by createDsh can be used as dsh.languageModel("deepseek-v4-flash"), or directly as dsh("deepseek-v4-flash"), which is the conventional alias for AI SDK providers. Both runtime.provider and runtime.model will be passed to dsh during runtime handshake; provider can be deepseek-official, or a router from the pi-ai directory.
AI SDK v6: Different field names¶
v6 does not have instructions, and the system prompt field is called system:
import { streamText } from "ai";
import { createDsh } from "ai-sdk-provider-dsh";
const dsh = createDsh({
runtime: { provider: "deepseek-official", model: "deepseek-v4-flash" },
});
const result = streamText({
model: dsh.languageModel("deepseek-v4-flash"),
system: "You are a coding agent.",
prompt: "run the tests",
});
generateText¶
Retrieve the full text in one go:
import { generateText } from "ai";
import { createDsh } from "ai-sdk-provider-dsh";
const dsh = createDsh({
runtime: { provider: "deepseek-official", model: "deepseek-v4-flash" },
});
const { text } = await generateText({
model: dsh.languageModel("deepseek-v4-flash"),
prompt: "say hello",
});
Fixed sessionId for multi-turn conversations¶
The core of the repository example examples/multi-turn.ts is: using the same provider and the same sessionId, the second call can read the context written in the first call.
import { streamText } from "ai";
import { createDsh } from "ai-sdk-provider-dsh";
const dsh = createDsh({
runtime: {
provider: "deepseek-official",
model: "deepseek-v4-flash",
sessionId: "example-session-1",
},
});
async function ask(prompt: string): Promise<string> {
const result = streamText({
model: dsh.languageModel("deepseek-v4-flash"),
prompt,
});
return (await result.text).trim();
}
const t1 = await ask("The secret code is X7Q9. Reply: stored");
const t2 = await ask("What is the secret code? Reply with only the code.");
When no sessionId is passed, each provider instance will still reuse its own child process, but the session ID will be a new one. Explicitly pass a fixed ID when you need to retain context across calls.
Use a minimal runtime configuration¶
If you cannot compile node-pty, point configPath to the minimal combination included in the package:
runtime: {
provider: "deepseek-official",
model: "deepseek-v4-flash",
configPath: require.resolve("ai-sdk-provider-dsh/runtime/cordis.minimal.yml"),
}
The exports field in package.json includes the ./runtime/* subpath, so this require.resolve syntax is officially supported by the package. Other common override options include: cwd (default process.cwd()), env (defaults to inheriting process.env, you can pass DSH_CWD and DSH_SESSION_ROOT), and maxTokens (the output token limit per request for the root agent).
Read stderr from errors¶
import { generateText } from "ai";
import { createDsh, getErrorMetadata, isAPICallError } from "ai-sdk-provider-dsh";
try {
await generateText({
model: dsh.languageModel("deepseek-v4-flash"),
prompt: "Hello!",
});
} catch (error) {
if (isAPICallError(error)) {
console.error(getErrorMetadata(error)?.stderr);
console.error("retryable:", error.isRetryable);
}
}
Applicable Scenarios and Notes¶
It is most suitable for:
- Users already orchestrating with the AI SDK who want to embed dsh as a “language model that runs tools”
- Need harness-side bash / file editing / subagent / session logging while retaining the generateText / streamText calling interface
- Need the same code to be compatible with both AI SDK v6 and v7
It is not suitable as glue code for “passing any AI SDK tools to dsh for execution”. The README explicitly states: AI SDK’s tools / toolChoice will not be executed by the AI SDK; to modify tools, edit cordis.yml or use $DSH_* environment variables. Sampling parameters such as temperature, topP, topK, stopSequences, and seed will be accepted by the interface but will not be forwarded to the harness—sampling is managed by the harness itself.
Other boundaries already documented in the README:
- Only ESM is supported, Node.js must be >=22.19
- There is no “mid-turn cancellation” in the SDK: aborting will reject the current call, the child process and session log remain intact, and subsequent turns can continue; to tear down the process, call dsh.close()
- dsh is still in developer preview, and breaking changes are part of its release policy; both the provider version and the harness family (currently 0.1.0-rc.6) should be explicitly pinned
- The default runtime requires the ability to compile node-pty on Linux; if this fails, switch to cordis.minimal.yml (no bash support)
Whether you use the directory’s dsh plugin add or npm, installation may run build scripts and native plugins. Review the source code and license before installing; for reproducible installations, pin git installations to a specific commit and pin npm dependencies to exact versions.
Summary¶
ai-sdk-provider-dsh wraps the dsh runtime into a LanguageModelV3: on the AI SDK side, you still use the familiar generateText / streamText, while on the other side is a full agent loop pinned to 0.1.0-rc.6. Tools are executed inside the harness, sessions can be resumed with a fixed sessionId, and errors are wrapped into AI SDK’s familiar APICallError.
It solves the problem of unified orchestration surfaces, not adding another model provider for the dsh Web UI. The default combination supports bash and file tools, but skills and MCP are not enabled out of the box. dsh is still in preview, so you need to monitor its version updates yourself.
Directory page: https://deepseek-harness-plugin.com/zh-CN/plugins/ai-sdk-provider-dsh/
GitHub: https://github.com/krislavten/ai-sdk-provider-dsh
npm: https://www.npmjs.com/package/ai-sdk-provider-dsh