# Conflicts: # apps/cli/cordis.yml # apps/web/tests/snapshots/code-mode-round/session.jsonl # apps/web/tests/snapshots/cordis-tool-round/session.jsonl # apps/web/tests/snapshots/fresh-round-trip/session.jsonl # apps/web/tests/snapshots/lifecycle-chrome/session.jsonl # apps/web/tests/snapshots/live-interactions/session.jsonl # apps/web/tests/snapshots/navigation-panes/seed.jsonl # apps/web/tests/snapshots/question-composer/session.jsonl # apps/web/tests/snapshots/seeded-history/seed.jsonl # apps/web/tests/snapshots/steering/session.jsonl # docs/cordis-catalog/events.md # docs/cordis-catalog/services.md # docs/core-data-structures/core.i18n.yaml # docs/core-data-structures/settings.i18n.yaml # docs/event-producer-consumer.md # docs/module-graph.md # examples/acp-agent/tests/snapshots/workspace-context/session.jsonl # packages/client/connection/README.i18n.yaml # packages/client/connection/src/index.ts # packages/client/connection/tests/node-half.spec.ts # packages/client/runtime/README.i18n.yaml # packages/client/runtime/README.md # packages/client/runtime/README.zh.md # packages/client/runtime/src/client/index.ts # packages/client/runtime/tests/fake-api.ts # packages/client/ui-models/README.i18n.yaml # packages/examples/tui-demo/README.i18n.yaml # packages/host/apiproxy/README.i18n.yaml # packages/host/apiproxy/package.json # packages/host/apiproxy/src/api-proxy.ts # packages/host/apiproxy/src/api/rpc.schema.ts # packages/host/apiproxy/src/api/rpc.ts # packages/llm/llm-deepseek/README.i18n.yaml # packages/llm/llm-deepseek/README.zh.md # packages/llm/llm-pi-ai/README.i18n.yaml # packages/llm/llm/README.i18n.yaml # packages/llm/llm/README.zh.md # packages/sdk/sdk-client/README.i18n.yaml # packages/settings/settings/README.i18n.yaml # packages/settings/settings/README.md # packages/settings/settings/README.zh.md # packages/subagent/subagent-dsh-sdk/README.i18n.yaml # packages/subagent/subagent-dsh-sdk/README.zh.md # packages/support/llm-replay/README.i18n.yaml # packages/ui/jsonrpc/README.i18n.yaml # packages/ui/jsonrpc/README.zh.md # packages/ui/tui/tests/snapshots/model-selector.expected.txt # packages/ui/tui/tests/snapshots/model-switching.expected.txt # packages/ui/tui/tests/snapshots/resume-sessions.expected.txt # packages/ui/tui/tests/snapshots/status-diagnostics-narrow.expected.txt # packages/ui/tui/tests/snapshots/status-diagnostics.expected.txt # packages/ui/tui/tests/tui.snapshot.ts # pnpm-lock.yaml # python/sdk/README.i18n.yaml # scripts/snapshots/translation-prompt-v4/request-response.expected.json
DeepSeek Harness Python SDK
English | 中文
Python subprocess SDK for driving DeepSeek Harness over JSON-RPC stdio. The
runtime inherits normal DeepSeek Harness environment variables such as
DEEPSEEK_BASE_URL and DEEPSEEK_API_KEY, so callers can use real model
endpoints directly or point those variables at a local proxy during
benchmark runs.
Installing deepseek-harness installs the exact same-version deepseek-harness-runtime-bin platform wheel. The normal entry point therefore needs no executable argument:
from deepseek_harness import DeepSeekHarness
with DeepSeekHarness() as harness:
result = harness.run("Say hi.")
DeepSeekHarness keeps its lazily started runtime subprocess for reuse across calls. Use it as a context manager, as above, or call close() explicitly when finished.
By default, the SDK launches the bundled single-file dsh-jsonrpc-agent executable from the deepseek-harness-runtime-bin package and injects that package's default configuration (the stdio JSON-RPC server, agent core, preloaded DeepSeek adapter, JSONL session persistence with an explicitly composed semantic checkpoint policy, local bash) via DSH_CORDIS_CONFIG. To run a plugin composition of your own, keep the @deepseek-ai/dsh-jsonrpc entry in the config and pass the Cordis config path.
from deepseek_harness import DeepSeekHarness
with DeepSeekHarness(
provider="deepseek-official",
model="deepseek-v4-flash",
max_tokens=49_152,
cordis="examples/jsonrpc-agent/cordis.yml",
) as harness:
result = harness.run("Make the requested code change.")
provider selects a provider route registered by the chosen Cordis composition; model is the model id resolved by that adapter. max_tokens is an optional positive per-request output-token cap for the root agent and its in-process descendants; omission leaves the provider default in control. Compaction summaries keep the separate limit configured by their compaction plugin. The bundled default composition registers deepseek-official. A custom composition can mount llm-pi-ai, configure provider-specific credentials/endpoints there, and select any provider/model present in pi-ai's installed catalog.
HarnessClient retains discovered subagent ancestry for the lifetime of the runtime process. During each Session.run(), TurnResult.notifications and on_notification receive the root session and all known descendant notifications in wire order, including nested subagent lifecycle and session events. TurnResult.events remains the root session's complete event stream, and TurnResult.final_response is the text content from its last assistant/message; descendant messages therefore cannot replace the root response.
The same behavior can be selected for the runtime subprocess with DSH_CORDIS_CONFIG. The injection lives in HarnessClient.start(), so the low-level client's default launch gets it too: when the launch resolves to the bundled runtime and neither cordis nor a non-empty DSH_CORDIS_CONFIG is set (the runtime treats an empty value as absent, and so does the injection check), the bundled default configuration is used; an explicit runtime_bin, bridge_bin, or launch_args_override disables the injection entirely. See the sdk-runtime README for the runtime carriers (production exe vs dev-only node closure) and how to obtain them.
cwd and runtime_cwd are resolved to absolute paths before subprocess launch, environment injection, and the wire handshake. The public API exposes only applied options: deployment persona and persistence belong in cordis.yml, while session_root remains the high-level convenience that sets DSH_SESSION_ROOT.