DeepSeek Harness SDK 集成:把 Agent 嵌进你的应用

DeepSeek Harness SDK 集成:把 Agent 嵌进你的应用

上一篇讲清楚了 dsh 的三种运行形态,最后预告说「最值得深挖的是 sdk」。这一篇就兑现它------怎么把 DeepSeek Harness 当成一个库,嵌进你自己写的程序里

Harness 的 SDK 分两条线:Python SDK 走一个开箱即用的 DeepSeekHarness 上下文管理器;TypeScript SDK 走一套叫 Typert 的 API Gateway,用 @Remote 装饰器把业务服务暴露成可远程调用的方法。两条线面向不同的人,但底层共享同一个「sdk profile + JSON-RPC 服务器」的运行时。

一、Python SDK:一个上下文管理器搞定

Python 这边做得很顺滑。先装:

sh 复制代码
python -m venv .venv
. .venv/bin/activate
python -m pip install deepseek-harness-sdk

装完自带一个匹配的原生 runtime wheel 和 dsh 命令,正常运行 SDK 不需要系统里装 Node.js(只有仓库贡献者构建产物时才需要)。

在你自己的程序里,核心就一个 DeepSeekHarness 上下文管理器:

python 复制代码
from pathlib import Path
from deepseek_harness import DeepSeekHarness

workspace = Path("/absolute/path/to/disposable-workspace").resolve()
dsh_home = Path("/absolute/path/to/example-dsh-home").resolve()

with DeepSeekHarness(
    provider="deepseek-official",
    model="deepseek-v4-flash",
    max_tokens=49_152,
    cwd=str(workspace),
    dsh_home=str(dsh_home),
    profile="sdk-minimal",
) as harness:
    result = harness.run(
        "Inspect the repository and fix the failing tests.",
        session_id="example-001",
    )

print(result.final_response)

几个关键点:

  • SDK 会惰性启动 dsh --profile sdk-minimal 这个子进程,并在上下文管理器退出前一直复用它;
  • profile、它的持久 patch、home 级 patch,以及 patches 元组里传入的有序 patch,共同构成应用配置;
  • 没有单独的 Python runtime bin,也没有「完整配置」这一说------一切还是走 profile 那套。

二、sdk-minimal:一个「极简到极致」的 profile

SDK 默认或例子常选的 sdk-minimal 值得单独看一眼,因为它清楚展示了「最小可用」长什么样:

项目
系统提示词 DSH_SYSTEM_PROMPT,兜底 You are a helpful software engineer assistant.
模型 --modelDSH_MODELdeepseek-v4-flash
面向模型的工具 持久 bash(Linux/macOS)或 pwsh(Windows),加 str_replace_editor
Shell 超时 300 秒
编辑器输出上限 16000 字符
运行时上下文与压缩
会话持久化 <dsh_home>/sessions 下的未压缩 JSONL

它只有一个 bundle,把整棵树插在空 root 上,不包含 dsh-base ,所以后面 base-profile 的工具不会隐式出现。settings、托管凭据、遥测、Web 工具、子 agent、本地指令发现、压缩------这些统统不在里面。它 pin 了 danger-full-access,意味着持久 shell 和编辑器能改运行时可见的任何路径------所以官方反复强调:用一次性 checkout 或容器跑

三、TypeScript SDK:Typert 的 @Remote 编程模型

TS 这边不是「start 一个进程」,而是声明式地把业务服务暴露成 Remote 方法 。核心是 @Remote / @RemoteScope 两个装饰器:

ts 复制代码
import type { Agent } from '@deepseek-ai/dsh-agent'
import { TypertRemoteService, Remote, RemoteScope } from '@deepseek-ai/dsh-typert-protocol'
import type { Context } from '@deepseek-ai/cordis'

export interface CreateGoalRequest { objective: string }
export interface CreateGoalResult { accepted: boolean }

export class GoalService extends TypertRemoteService {
  constructor(ctx: Context) {
    super(ctx, 'goals')            // 绑定 cordis service key + Remote namespace
  }

  @Remote('create')
  createForClient(agent: Agent, request: CreateGoalRequest, signal: AbortSignal): CreateGoalResult {
    signal.throwIfAborted()
    return this.create(agent, request)
  }

  @RemoteScope('agent', 'current')
  currentForClient(): CreateGoalResult {
    return { accepted: true }
  }

  private create(_agent: Agent, request: CreateGoalRequest): CreateGoalResult {
    return { accepted: request.objective.length > 0 }
  }
}
  • @Remote 表示调用 root Host Context 上的 cordis service;@RemoteScope 先把身份解析成 scoped Context 再拿 service 调用;
  • 复杂对象(比如 Agent)不能直接过线,要用 TypertLookupMap 声明「wire 身份」→ Host 对象的映射,Gateway 会按 agentId 这种 wire 字段去解析回真实对象;
  • 方法最后一个参数必须是 signal: AbortSignal,用于协作式取消。

客户端这边,调用是具体函数,不是 JS Proxy

ts 复制代码
await ctx.remote.goals.create(agentId, { objective: 'ship it' })
await agentCtx.remote.goals.create({ objective: 'ship it' })

每个 namespace 是一个 trace 过的 cordis child service,注册成 remote.<namespace>;装配通过 ctx.remote.$mount() 挂载贡献,namespace 最后一个方法卸载后自动回收。

四、调用链:JSON-RPC 承载在 /api 路由上

Remote 调用走 Connection 的 /api 路由:客户端 connection.rpc.call('/api', '<namespace>/<method>', { args }, signal),HTTP 层映射成 POST /api/<namespace>/<method>,payload 只带一个命名的 args 对象。

Gateway 对每一次调用都会:解析描述符和「当前注册表里的 live service」(不缓存业务对象)、用 codec 校验 wire 值、通过 lookup/Context provider 解析对象、调用目标方法、再校验返回值。缺 provider、身份未知、参数对不上、schema 失败、方法不存在,都在进业务代码前或出业务代码后失败------这套严格校验是 TS SDK 比「裸 RPC」更值钱的地方。

五、插件持久化安装

不管哪条线,想把插件 bundle 持久装进 SDK profile,都用运行时自带的 dsh CLI:

sh 复制代码
export DSH_HOME=/absolute/path/to/isolated-dsh-home
dsh --profile sdk --dump-default-config     # 先初始化 profile
dsh plugin --profile sdk add file:/absolute/path/to/my-plugin-bundle

第一条初始化 profile,第二条把包管理转发给 pnpm 并记录下所有导出 dsh.bundle 层的包。只有这个管理命令需要 pnpm,启动已装好的 SDK 不需要。

六、避坑清单

  1. Python SDK 别默认它会读 ~/.dsh 。例子和 SDK 从不静默读取 ~/.dsh,workspace 和 home 都要显式给绝对路径,否则它不知道去哪找。
  2. sdk-minimal 是全访问,隔离优先 。它 pin danger-full-access,用一次性 checkout 或容器跑,别拿它直接啃你的真实仓库。
  3. TS SDK 换传输不改契约。Remote 描述符和客户端接口独立于 Connection 载体,换 carrier 不需要动 Remote 定义------但反过来,别把 Remote 方法和流式/增量数据混为一谈,那些得走单独的数据协议。
  4. 改了 @Remote 签名要重建 。增删装饰器、改导出名/namespace/参数/返回值/lookup,都得 pnpm run build:lib 让 Host 先生成严格契约,客户端才能编译到新贡献;只改方法体不用重建。
  5. web 是独立 CLI,不能服务 Python SDK 客户端 。想浏览器界面就单独 dsh web,别指望同一个进程又当 web 又当 Python SDK server。

小结

SDK 集成的本质,是把前八篇反复强调的「seam」再往外推一层:对内,插件是 seam;对外,SDK 本身也是 seam 。Python 用 DeepSeekHarness 一个对象包住整个 agent 进程,TS 用 @Remote 装饰器把业务服务暴露成可远程调用的方法------两条路殊途同归,都是「把 Agent 变成你程序里的一个能力」。

下一篇我们往里收一步,讲怎么改行为而不碰源码------这就是 Harness 的配置与 Patch 体系。


参考:deepseek-ai/deepseek-harness 官方仓库 docs/user/guide/python-sdk.mddocs/api-gateway.md

相关推荐
ly-272531 小时前
IEEE PDF eXpress终稿检测踩坑记录:PDF图片字体未嵌入与LaTeX参考文献编译异常解决方法
服务器·人工智能·算法
陕西企来客1 小时前
2026年8月咸阳家用雨棚上门测量怎么选
大数据·人工智能·咸阳家用雨棚上门测量
志栋智能1 小时前
凌晨3点的告警,如何用AI在5分钟内完成定界?
运维·服务器·数据库·人工智能·自动化
joinwell521 小时前
工信部414号文深度解读:从模型供给走向应用交付
人工智能·企业数字化·行业分析
流浪0011 小时前
大模型技术全景(五):开源大模型生态指南,Hugging Face 与魔搭社区
人工智能·深度学习·llm
yangmu32031 小时前
DLSS 5:从“AI提帧”到“AI定义画质”的渲染革命
人工智能
Li Ming&1 小时前
基于OpenCV+MediaPipe+PyGame的手势控制音乐播放器(Python实现)
人工智能·python·计算机视觉
晴天161 小时前
Chrome WebMCP 让网站学会向 AI「自我介绍」
前端·人工智能·chrome
yyywxk1 小时前
ICLR 2026 目标检测(object detection)方向上接收论文总结
人工智能·目标检测·目标跟踪