deepseek-harness-sdk-go
Discovered★ 3Go SDK for driving DeepSeek Harness
DeepSeek Harness Go SDK
English | 中文
Go SDK for driving DeepSeek Harness. The SDK starts the Harness runtime as a subprocess and speaks the line-delimited JSON-RPC 2.0 protocol over stdio. It is a clean-room Go implementation of the protocol and mirrors the layering and activity semantics of the upstream Python SDK.
Requirements
- Go 1.26 or newer.
- macOS arm64/x64, Linux amd64/arm64, or Windows amd64 when using the bundled runtime downloader.
- An explicit
DSHHomeor non-emptyDSH_HOMEenvironment variable. - A
DEEPSEEK_API_KEYenvironment variable, unless the selected profile uses another credential path or a local model proxy.
Install
go get github.com/theoneLee/deepseek-harness-sdk-go
The SDK targets the single-file runtime published by the DeepSeek Harness
project. With no explicit executable, the first Start or Run resolves the
matching platform wheel from a PyPI-style index, verifies SHA-256, extracts it
into a cache, and reuses it on later starts. The default target is runtime
0.1.5-alpha.1, corresponding to upstream tag dsh-v0.1.5-alpha.1.
The matching public runtime wheel must be available before automatic download
can start this version; use DSHBin or RuntimeIndexURL when consuming a
private or pre-publication wheel.
Quick start
package main
import (
"fmt"
deepseekharness "github.com/theoneLee/deepseek-harness-sdk-go"
)
func main() {
harness := deepseekharness.NewDeepSeekHarness(deepseekharness.DeepSeekHarnessConfig{
DSHHome: "/absolute/path/to/dsh-home",
})
defer harness.Close()
result, err := harness.Run("Say hi.")
if err != nil {
panic(err)
}
fmt.Println(result.FinalResponse)
}
DeepSeekHarness starts lazily and keeps the subprocess alive across runs.
Always call Close when the harness is no longer needed so the runtime is
reaped promptly.
Configuration
harness := deepseekharness.NewDeepSeekHarness(deepseekharness.DeepSeekHarnessConfig{
Provider: "deepseek-official",
Model: "deepseek-v4-flash",
ReasoningEffort: "max",
MaxTokens: 49_152,
DSHHome: "/absolute/path/to/dsh-home",
Profile: "sdk",
Patches: []string{"/absolute/path/to/patch.yml"},
})
defer harness.Close()
The runtime inherits the parent environment. Env overlays it for the child;
BaseURL and APIKey are convenience fields for
DEEPSEEK_BASE_URL and DEEPSEEK_API_KEY. CWD is sent in the initialize
payload; RuntimeCWD controls the subprocess working directory. DSHHome
overrides the child DSH_HOME; without it, the child must inherit a non-empty
DSH_HOME. Profile defaults to sdk, and each Patches entry becomes an
absolute --patch argument. ReasoningEffort becomes reasoningEffort in
initialize, while MaxTokens == 0 omits maxTokens.
The initialize handshake has its own 30-second default timeout through
InitializeTimeoutSeconds; RequestTimeoutSeconds controls ordinary
requests.
Launch channels are resolved from most explicit to least explicit:
LaunchArgsOverride.CommandwithArgs.DSHBin.RuntimeBinorBridgeBin(deprecated compatibility aliases).DSH_RUNTIME_BIN(deprecated compatibility override).- The bundled runtime downloader.
DSHBin and the bundled downloader append --profile <Profile> and ordered
--patch <absolute path> arguments, and require an explicit Harness home. The
new runtime has no downloaded default cordis.yml; its profile owns runtime
configuration. LaunchArgsOverride remains an internal-style escape hatch for
fake runtimes and bypasses the home check.
Sessions and results
session, err := harness.StartSession("session-reuse")
if err != nil {
panic(err)
}
result, err := session.Run(
deepseekharness.BlocksInput([]deepseekharness.JSONObject{
{"type": "text", "text": "Inspect this task."},
}),
func(notification deepseekharness.Notification) {
if notification.Method == "session.event" {
// Render or persist the event as needed.
}
},
)
Run waits for the prompt's durable agent/inbox/spliced receipt, then
collects notifications until the root session reaches its next idle state.
Notifications from known descendant sessions are included through
subagent.started lineage edges. RunResult.Events contains root-session
events only. FinalResponse is the last committed root assistant text in the
interval, and FinishReason is the last turn/end reason kind when present.
Those values describe the owned activity interval, not an output causally
assigned to only the submitted prompt.
The callback is invoked for each collected notification after the inbox
receipt. FinishReason is a *string; it is nil when no turn ended.
Low-level client
HarnessClient exposes the protocol surface used by advanced integrations:
client := deepseekharness.NewHarnessClient(deepseekharness.HarnessClientOptions{
DSHBin: "/path/to/dsh",
DSHHome: "/absolute/path/to/dsh-home",
Profile: "sdk",
})
defer client.Close()
if err := client.Start(); err != nil {
panic(err)
}
_, err := client.Initialize(deepseekharness.InitializeParams{
CWD: "./workspace", Provider: "deepseek-official", Model: "deepseek-v4-flash",
ReasoningEffort: "max",
})
The client supports Request, Notify, SessionPrompt, Subscribe,
SubscribeSessionTree, NextNotification, NextRequest, Respond, and
RespondError. Server-to-client requests are queued until the caller answers
them. Notifications that no subscription matched are available through
NextNotification.
Errors
Errors are concrete types suitable for errors.As: JsonRpcError,
RequestTimeoutError, ProtocolError, TransportClosedError,
RuntimeResolveError, and IOError. TransportClosedError includes the
process exit code when available and the last 400 stderr lines.
Development
gofmt -w *.go
go vet ./...
go test -race ./...
GitHub Actions runs formatting, vet, race-enabled tests, and the regular test
suite on Linux and macOS. Releases are created from matching v* tags; see
docs/ROADMAP.md for planned parity work.
For the next upstream tag update, follow the tag update runbook.
Code Contribution Guide
| Area | Requirement |
|---|---|
| Scope | Keep changes focused on the Go SDK and its compatibility with the upstream Python SDK. |
| Implementation | Follow existing package patterns, preserve raw protocol data, and add comments only for non-obvious behavior. |
| Tests | Add or update mechanism tests for protocol, lifecycle, and runtime-resolution changes. |
| Validation | Run gofmt, go vet ./..., and go test -race ./... before opening a pull request. |
| Documentation | Update the relevant English and Chinese docs in docs/ when public behavior changes. |
| Pull request | Explain the behavior change, compatibility impact, and verification commands. Do not include API keys or runtime artifacts. |
The full contributor workflow, including branch, commit, and pull request
guidance, is in docs/CONTRIBUTING.md.
Relationship to DeepSeek Harness
This repository owns the Go SDK. The runtime is published by the
DeepSeek Harness project as
deepseek-harness-runtime-bin. The SDK follows the documented
stdio JSON-RPC protocol
and tracks the Python SDK's public behavior as that implementation evolves.
Comments
Loading…
Similar plugins
by CJYLZS
auto sync opencode-go models in dsh
★ 3
JavaScript
Sep 4, 2026
dsh plugin --profile web add dsh-opencode-go-autosyncby sugarforever
DeepSeek Harness Plugin for Lark Integration
★ 27
↓ 271/wk
MIT
TypeScript
Sep 7, 2026
dsh plugin --profile web add @sugarforever/dsh-larkby goatliamia
Plugin development toolkit for DeepSeek Harness with scaffolding, contract checks, plugin vetting, impact analysis, and upstream compatibility tracking.
★ 2
MIT
JavaScript
Sep 18, 2026
dsh plugin --profile web add dsh-plugin-makerby xia-sc
DeepSeek Harness LLM provider plugin for OpenCode Go (zen-go route)
★ 0
MIT
JavaScript
Sep 10, 2026
dsh plugin --profile web add @dsh-plugins/dsh-opencode-goby bobby-sheng
Search, inspect, update, and install DeepSeek Harness plugins from DSH Get.
★ 0
MIT
JavaScript
Aug 19, 2026
dsh plugin --profile web add dshget-pluginby lilwhich
for better dsh
★ 9
MIT
JavaScript
Sep 9, 2026
dsh plugin --profile web add my_better-dsh