DeepSeek Harness Python SDK 调用
Web UI 适合人盯着看,但你要在程序里调用 dsh 时,需要的是 SDK。
本章节介绍 Python SDK:怎么装、怎么跑仓库内置示例、怎么在自己的程序里调用。
Python SDK 解决什么问题
SDK 把 dsh 变成你程序里的一行调用,而不是浏览器里的一个页面。
DeepSeekHarness 是 Python SDK 的核心类,用上下文管理器管理运行时的生命周期。
进入 with 块时延迟启动内置运行时,退出时自动释放,中间可反复调用 run。
适合的场景:批处理任务、把 dsh 集成进自己的产品、在测试里驱动 Agent。
SDK 装好之后,运行时不需要系统提供 Node.js,Python 进程自己带着一份。
前置要求
SDK 对系统有明确要求,先对照确认。
| 依赖 | 要求 |
|---|---|
| Python | 3.10 或更高版本 |
| Git | 已安装 |
| 操作系统 | Linux x64、Linux arm64、macOS 14+(Apple 芯片)、Windows x64 |
| API 端点 | DeepSeek 兼容的 API 端点与凭据 |
| 工作区 | agent 可以修改的隔离 workspace 与隔离的 dsh home |
安装 SDK
克隆仓库拿到可运行示例,建虚拟环境,再安装 SDK 与同版本内置运行时。
$ git clone https://github.com/deepseek-ai/deepseek-harness.git $ cd deepseek-harness $ python -m venv .venv $ . .venv/bin/activate $ python -m pip install deepseek-harness-sdk
Windows PowerShell 使用 py -3.10 -m venv .venv 创建环境,再用 .venv\Scripts\Activate.ps1 激活。
虚拟环境让 SDK 与系统其它 Python 包隔离,是官方推荐的姿势。
安装后的运行时不需要系统提供 Node.js。
示例与 SDK 绝不会静默读取
~/.dsh,必须显式传入 home 路径。
运行仓库内置示例
仓库里带了一个 minimal.py 示例,位于 python/sdk/examples/ 目录,跑通它等于验证整条 SDK 链路。

先在环境中设置凭据。
$ export DEEPSEEK_API_KEY=sk-your-key-here # export DEEPSEEK_BASE_URL=http://127.0.0.1:8000/v1 # export DSH_MODEL=deepseek-v4-flash # export DSH_SYSTEM_PROMPT='You are a helpful software engineer assistant.'
如果模型不是由默认 DeepSeek 端点提供,而是通过 OpenAI 兼容代理提供,还需要设置 DEEPSEEK_BASE_URL。
随后针对隔离的 workspace 和 dsh home 运行一个任务。
$ python python/sdk/examples/minimal.py \ --workspace /absolute/path/to/disposable-workspace \ --dsh-home /absolute/path/to/example-dsh-home \ --session-id example-001 \ "Inspect the repository and fix the failing tests."
脚本会打印 assistant 的最终回复。
指定的 home 下会保存生成的 sdk-minimal profile、已安装插件,以及 sessions/ 目录下的未压缩 JSONL 会话日志。
在自己的程序中使用 SDK
仓库内置示例其实是下面这段 SDK 调用的轻量包装,核心只有两步。
实例
from pathlib import Path
from deepseek_harness import DeepSeekHarness
# agent 可访问的 workspace,必须是绝对路径
workspace = Path("/absolute/path/to/disposable-workspace").resolve()
# 隔离的 dsh home:保存 profile、插件与会话日志,必须是绝对路径
dsh_home = Path("/absolute/path/to/example-dsh-home").resolve()
# 上下文管理器:进入时延迟启动内置运行时,退出时自动释放
with DeepSeekHarness(
provider="deepseek-official", # 使用 DeepSeek 官方提供方
model="deepseek-v4-flash", # 模型名,SDK 默认也是它
max_tokens=49_152, # 单次回复的最大 token 数
cwd=str(workspace), # 把 workspace 设为 agent 的工作目录
dsh_home=str(dsh_home), # 隔离的 dsh home
profile="sdk-minimal", # 随附的极简 profile
) as harness:
# 发送一个任务;session_id 用于标识这段持久化对话
result = harness.run(
"Inspect the repository and fix the failing tests.",
session_id="example-001",
)
# 打印 assistant 的最终回复
print(result.final_response)
DeepSeekHarness 会延迟启动内置的 dsh --profile sdk-minimal 进程,并持续复用,直至退出上下文管理器。
同一个 harness 可以在 with 块里多次调用 run,运行时就启动一次。
profile、它的持久 patch、home patch 与传入的 patches 参数共同组成应用配置;要换自定义 profile,配置里必须包含一个 JSON-RPC server 插件(如 @deepseek-ai/dsh-sdk-app),否则启动会失败。
复用 session id:保留 Bash 进程
这是 SDK 最容易被忽略、也最有用的一条规则。
复用同一个 harness 与 session id,会保留该会话拥有的 Bash 进程。
包括它的工作目录、已导出的变量与 shell 函数,全都延续到下一次调用。
实例
result = harness.run(
"Run `cd /repo && export RUNOOB_MODE=dev` and confirm.",
session_id="runoob-session",
)
print(result.final_response)
# 第二次调用:复用同一个 session id,那个导出的变量还在
result = harness.run(
"Print the value of RUNOOB_MODE.",
session_id="runoob-session",
)
print(result.final_response)
独立任务应使用新的 session id;只有下一次调用需要延续同一段持久化对话时,才复用原有 id。
示例组合一览
minimal.py 背后的 sdk-minimal 组合是一份刻意精简的配置,逐项看清它做了什么。
| 属性 | 值 |
|---|---|
| 系统提示词 | DSH_SYSTEM_PROMPT;未设置时使用 You are a helpful software engineer assistant. |
| minimal.py 使用的模型 | --model,其次为 DSH_MODEL,最后为 deepseek-v4-flash |
| 面向模型的工具 | 持久 bash(Windows 为 pwsh)、read_image 与 working_directory |
| Bash 超时 | 300 秒 |
| 上下文压缩 | 自动执行:达到阈值时通过额外模型请求生成较早历史的摘要 |
| 持久化检查点 | 已启用:模型请求前等待历史刷盘,保证崩溃后恢复一致 |
| 会话持久化 | <dsh_home>/sessions 下未压缩的 JSONL |
| 权限 | 固定 danger-full-access,只能在可丢弃环境中运行 |
该组合的唯一组合包在空根之上插入完整配置树,不包含 dsh-base,因此基础 profile 以后新增的工具不会隐式出现。
它省略了 harness 身份、workspace 提示词文本、skill、任务工具、subagent、Web 工具与本地指令发现等插件。
整体调用流程如下。
显式启用 str_replace_editor
随附运行时包含 str_replace_editor,但 sdk-minimal 的默认配置树不挂载它。
需要文件编辑工具时,把下面的配置存成 editor.patch.yml:
实例
# insert 会添加编辑器工具,并复用已有的文件系统后端
- insert:
- id: tool-str-replace-editor
name: '@deepseek-ai/dsh-tool-str-replace-editor'
构造 DeepSeekHarness 时传入 patches 参数即可单次生效:
实例
profile="sdk-minimal",
patches=("/absolute/path/to/editor.patch.yml",), # 单次启动追加的 patch
# ...其余参数同上
) as harness:
...
想持久生效,就把这段 patch 写进 $DSH_HOME/profiles/sdk-minimal/cordis.patch.yml。这个 patch 也适用于标准 sdk profile。
插件管理用 dsh plugin 命令:先设置 DSH_HOME 并执行一次 dsh --profile sdk-minimal --dump-default-config 初始化 profile,再用 dsh plugin --profile sdk-minimal add file:/path/to/my-plugin-bundle 安装——只有管理命令需要 pnpm,启动 SDK 本身不需要。
会话日志上传与关闭
sdk-minimal 默认带一个会话日志贡献器:每次 DeepSeek 请求会随请求上传未落定的事件,每次最多 maxBytes(默认 8 MiB)。
它用于平台侧诊断,不在 messages、系统提示词或工具 schema 之内,不增加模型输入 token。它仍涉及会话数据发送,使用前应按自己的数据要求决定是否关闭。
不希望上传时,在 profile patch 中关闭:
实例
# 按 id 覆盖该行配置,关闭会话日志上传
- id: session-log-deepseek
config:
enabled: false
danger-full-access 的边界
这个示例组合固定使用 danger-full-access 权限预设,必须清楚它的边界。
danger-full-access 只能在可丢弃的 checkout 或容器内运行。
Bash 与文件访问可以修改运行时进程有权访问的任何路径,没有沙箱兜底。
Windows 上持久 shell 使用 pwsh,同样没有任何路径限制。
换句话说,拿它跑真实项目之前,先确认这个环境弄坏了也不心疼。
小结自测
一句话总结:Python SDK 用 DeepSeekHarness 上下文管理器包住运行时,用 run(prompt, session_id) 发任务。
用三个小问题检验理解。
- 复用同一个 session id 会保留什么?
- 什么情况下应该使用新的 session id?
- sdk-minimal 默认给模型开放了哪些工具?
参考答案:会保留该会话的 Bash 进程,包括工作目录、已导出变量与 shell 函数。
独立任务用新 id;只有需要延续同一段持久化对话时才复用。
持久 bash(Windows 为 pwsh)、read_image 与 working_directory;str_replace_editor 需要显式 patch 启用。
