DeepSeek Harness 集成实战(一):架构解析与内嵌方案

DeepSeek Harness架构解析:构建可验证AI智能体系统的工程实践 在AI工程化领域,分布式架构和Agent架构正成为构建复杂智能系统的关键技术范式。分布式架构通过将计算任务分解到多个节点协同处理,实现了系统的高可用性和可扩展性;而Agent架构则赋予AI系统自主规划、决策和执行任务的能力。这两种架构的结合,为开发高可靠性AI应用提供了坚实基础。其技术价值在于能够将大语言模型的生成能力与结构化的工作流相结合,确保每个输出都有可追溯的来源和验证机制。在金融分析、法律文档处理、代码生成等对准确性要求极高的场景中,这种可验证性尤为重要。DeepSeek Harness正是基于这一 阅读详情

8 月 13 号晚上 DeepSeek 把 DeepSeek Harness(下面简称 dsh)开源的时候,我正在给一个客户远程配机器人。那天晚上我干了两件事:一边在企业微信里教客户"先去聊天配置里把提示词填上,再去工具管理里把 set_friend_remark_tag 勾上,然后回到规则配置……",一边看着 dsh 的 star 数十几个小时涨过五万。

看完它的架构文档,我脑子里冒出来的问题和大多数人不太一样。大家讨论的是"它和 Claude Code 谁写代码更强",我想的是:

能不能把这个 harness 整个装进冰石机器人里?让客户用一句话提要求,剩下的拆解、配置、验证,让它自己干。

冰石机器人是我们团队做的一套微信智能客服系统。功能越做越多,配置也越来越复杂——提示词式的营销 SOP、客户生命周期规则 JSON、20 多个内置工具的白名单、风控参数、按渠道区分的各种开关。老客户用得很顺,新客户上手第一周基本都在打电话问"这个在哪配"。

这个痛点我们不是没解决过。系统里早就有一个"智能体助手",21 个配置和查询工具,能在对话里帮用户建关键词、改群提示词、查订单;还有一个"创建工具"功能,用大模型生成扩展插件。但它们都是单轮或短循环的——助手最多 5 轮工具调用,不会先做计划,不会自己验证,干到一半出错了就停在那里。

dsh 给了一个现成的、工业级的"长循环"。这个系列就是讲怎么把它集成进来。

本系列共三篇:

  1. (本篇)架构解析与内嵌方案——dsh 是什么、怎么嵌、怎么打进 exe
  2. 一句话配置与自动创建工具——让 harness 拆解配置任务、自己写扩展
  3. 操纵业务系统与安全边界——让冰石通过 harness 连上 ERP、CRM 和各种老系统

先说清楚:这个系列是架构设计 + 示意代码,不是已上线功能的复盘。dsh 目前还是预览版(写这篇时是 v0.1.7-rc.2),README 里明确写着会有破坏性变更。文中所有 dsh 的接口细节我都对照了官方仓库的文档和源码,但代码片段请当设计稿看。


一、先把概念说清:harness 到底是什么

“harness"直译是"挽具”——套在马身上、把马的力气变成车往前走的那套东西。放在 AI 里,模型是马,harness 是让模型能干活的那一整套外围软件。

一个模型本身只会做一件事:输入一段文字,输出一段文字。要让它"干活",外面至少得有这些:

组件干什么没有它会怎样
循环(agent loop)调模型 → 执行工具 → 把结果喂回去 → 再调模型,直到完成只能一问一答
工具读文件、跑命令、调 API只能说不能做
上下文管理拼提示词、压缩历史、控制 token长任务跑到一半爆上下文
会话持久化记录每一步,能恢复、能重放进程一挂全白干
权限与沙箱决定哪些操作能做、哪些要问人要么什么都不敢做,要么什么都敢做
规划与委派先想后做、拆子任务、派给子代理大任务一口吞,吞不下

Claude Code、Codex CLI 都是 harness。dsh 也是,而且是 DeepSeek 官方出的。

这里有个我自己的认识转变,值得单独说一句:

模型决定能力上限,harness 决定能力能不能落地。

DeepSeek 自己的数据很能说明问题。他们 API 更新日志里 Terminal-Bench 2.1 的分数,从 7 月底的 82.7 一路到 9 月 10 号的 90.6——这期间模型有迭代,harness 也在迭代,7 月底那次还特意注明用的是"DeepSeek Harness minimal mode"。同一个模型,套不同的 harness,分数能差出一截。

回头看冰石的"智能体助手",其实它就是一个迷你 harness:

冰石现有的智能体助手dsh
循环最多 5 轮工具调用按 turn/step 组织,可配 Goal 跨轮持续推进
工具协议自定义 JSON(reply_content + tool_calls)原生工具调用 / Code 模式(模型写 TS 程序串工具)
工具来源独立的 assistant_tool_registry,21 个插件注册 + MCP + 子代理
规划无Plan mode、Goal、Workflow
持久化无,会话由前端持有append-only JSONL,可恢复、分叉、重放
权限靠提示词自律权限预设 + 审批链 + 沙箱
上下文压缩强制 FAQ 检索 + 截断compaction 插件

左边那列是我们两年里一点点攒出来的,能用,但每加一个能力都得自己写。右边那列是一个二十多万 star 的开源项目,有专职团队维护。这就是集成的动机:把"循环"这层交出去,我们只管业务工具。


二、dsh 的架构拆解

我把 dsh 的仓库和 docs/ 下面的架构文档过了一遍,挑和"集成"最相关的讲。

2.1 一切皆插件:Cordis 内核

dsh 的官方定位是"everything-is-a-plugin architecture powered by Cordis"。Cordis 是它的插件内核,模型、工具、Skills、会话、沙箱、存储、调度、UI,甚至 agent loop 本身,全都是插件。

插件对外提供三样东西:

  • 服务(service):比如 ctx.tools、ctx.sandbox、ctx.approval;
  • 事件(event):扩展点,比如 tools/pre-execute;
  • 可撤销的副作用(effect):插件卸载时自动清理。

插件怎么组合?用 profile。profile 是一组有序的插件包,官方内置了 dsh-base、dsh-web-app、dsh-headless、dsh-sdk-app、dsh-sdk-minimal 等。在 profile 之上,再用 YAML 的 patch 文件(*.cordis.yml)做增删改。

这个设计对集成方非常友好:

你不需要 fork dsh,只需要写一个 patch 文件,告诉它"加上我的 MCP 服务器、关掉这个插件、把权限设成只读"。

2.2 一次任务是怎么跑起来的

dsh 把一次用户请求叫一个 turn,一个 turn 由若干 step 组成,一个 step 就是"一次模型请求 + 它发起的工具调用"。每个阶段都是一个可挂钩子的事件:

工具执行 模型 agent-loop 插件 用户/宿主程序 工具执行 模型 agent-loop 插件 用户/宿主程序 loop [每个工具调用(串行)] loop [每个 step] session/prompt turn/start agent/pre-step → step/start agent/request(拼装提示词) 请求(流式) 文本 + 工具调用 tools/pre-execute(可 allow/deny/ask) tools/execute tools/post-execute(可替换结果) step/end agent/turn-stopping → turn/end 最终回复 + 事件流

这里有两个细节,是我读文档时专门记下来的,后面设计权限时会用到:

  1. tools/pre-execute 可以返回 allow / deny / cancel / ask——插件可以在这里拦截任何工具调用。
  2. 工具参数不能改写。官方文档的原话是:参数不能被改写,因为历史记录、审计、UI 和执行必须一致。只有结果可以在 tools/post-execute 里替换。

第二条很多人会忽略。它意味着你不能在中间偷偷"修正"模型传错的参数——要么放行,要么拒绝并告诉模型为什么,让它自己重来。这个约束是对的,审计日志里看到的就是实际执行的。

2.3 四种模式

模式特点对集成方的意义
Standard完整编程智能体:改文件、Shell、搜索、工作流默认形态
Code(PTC)模型写一段 TypeScript,在里面 await tools.xxx(args) 串多个工具多步配置可以一次写完,少很多轮往返
Minimal只有 bash + 文件编辑器跑基准用
Creator能检查运行中的系统、在内存里试装插件、组合出新模式智能体扩展 harness 自己

Code 模式值得多说一句。传统工具调用是"模型说调 A → 执行 → 结果回去 → 模型说调 B",每一步都要一次模型往返。Code 模式让模型直接写:

// 模型生成的 run_code 内容(示意)
const groups = await tools.mcp__icestone__query_groups({ keyword: '汽服' })
const report = []
for (const g of groups.items) {
  const kw = await tools.mcp__icestone__query_keywords({ group_id: g.id })
  report.push({ group: g.name, keywords: kw.items.length })
}
return report

一次往返干完一个循环。官方说明每次 run_code 都起一个新的 Node 进程,受和 Bash 一样的沙箱策略约束。开启方式是在 preset 里配 dsh-agent-tool-presentation 的 mode: ptc|both,或者进程级设环境变量 DSH_TOOLS_MODE。

2.4 规划、目标、工作流、子代理

这几个是"让它能干大活"的关键,逐个看:

  • Plan mode:先探索、再出计划,通过 exit_plan_mode 工具提交一份完整的 markdown 计划等用户批准。注意,官方文档明确说 Plan mode 是"soft guidance"——它靠提示词引导模型只读,并不真的禁止写操作,真正的限制靠沙箱模式和审批策略。
  • Goal:一个跨 turn、跨会话恢复、跨进程重启都持续存在的"完成目标",可以创建、暂停、恢复、完成、阻塞。自动续跑默认上限 256 轮。
  • Workflow:让模型写一段 JavaScript 编排脚本,用 agent()、parallel()、pipeline() 把活派给一群子代理,最后返回一个 JSON。
  • Subagent:把子任务委派给子代理。有 one-shot(等它干完)和 continuable(后台常驻、返回 id)两种。提供方可以是 dsh 自己,也可以是 Claude Code、Codex。

Plan mode 是"软"的这一点,我觉得是整份文档里对集成方最重要的一句话。**如果你的产品要"先给用户看计划、批准了再动手",不能只靠开 Plan mode,得在工具层面把写操作管住。**这个第七节细说。

2.5 会话日志:一切可重放

dsh 把所有东西写进一个 append-only 的 JSONL 会话日志,原则是"模型请求可以从日志重建"。会话可以恢复、分叉、搜索、重放。默认用 Zstandard 压缩,存在 $DSH_HOME/sessions/ 下面。

对业务软件来说,这就是现成的审计日志。客户问"你那个 AI 到底改了我什么",翻日志就行。

2.6 权限与沙箱

权限预设内置三档:

预设沙箱审批策略
read-only只读ask
workspace-write工作区可写ask
danger-full-access完全访问never

沙箱在 Linux 上用 bwrap/Landlock,macOS 用 Seatbelt,Windows 用 ACL 受限令牌。**但官方自己也写得很清楚:沙箱只管文件系统,不管网络和进程;Windows 上的 ACL 限制是部分生效的;读操作不受限。**仓库里的 SAFETY.md 直接说沙箱"不保证隔离"。

冰石的客户几乎全是 Windows。这意味着:别把安全押在 dsh 的沙箱上。


三、集成方式:有哪几条路

dsh 给宿主程序提供了好几种接入方式:

方式原理适合
TypeScript SDK @deepseek-ai/dsh-sdk-client拉起 dsh 子进程,stdio 上跑换行分隔的 JSON-RPCNode / Electron 应用
Python SDK deepseek-harness-sdk同上,Python 版Python 后端
Web UInpx @deepseek-ai/dsh web,本地 3080 端口给人用,不适合嵌入
Headless / ACP / HTTP 网关一次性运行、Agent Client Protocol、HTTP 服务自动化、跨语言

冰石后端是 Python(FastAPI + uvicorn,PyInstaller 打包),自然选 Python SDK。官方示例长这样:

from deepseek_harness import DeepSeekHarness

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",
    )

run() 返回 RunResult,包含 session_id、final_response、finish_reason、events、notifications。流式可以传 on_notification 回调,收 session.event、session.status、subagent.started、subagent.finished 这几类通知。

但读 SDK 的协议文档时,我发现了三个会直接决定架构的限制:

限制一:协议只有三个方法。 SDK 和 dsh 之间只有 initialize、session/prompt、shutdown。没有"切换到 Plan mode"、没有"中途取消"之类的方法。想改行为,只能在启动时通过 profile 和 patch 定好。

限制二:宿主程序收不到审批请求。 协议文档原话:“Server→client requests are a dead capability”——传输层支持,但服务端从来不发;Python SDK 里预留的 responder 是"为将来的审批流程准备的"。也就是说,dsh 想问"这个操作能不能做"的时候,没法问到冰石的界面上来。

限制三:不能从 Python 直接注册工具。 工具要么写成 dsh 的 TS 插件,要么通过 MCP 服务器接入,都是通过 patch 配置进去。

这三条放在一起,结论几乎是唯一的:

冰石的能力必须以 MCP 服务器的形式暴露给 dsh;所有"改东西"的操作都必须经过冰石自己的工具,由冰石自己做审批。dsh 本身只给最小权限。

这是整个系列的架构基石,后面两篇都建立在它上面。

冰石机器人 exe 进程

stdio JSON-RPC

Streamable HTTP
localhost + token

HTTPS

管理后台
AI 配置助手面板

FastAPI 后端

HarnessService

/mcp 端点
冰石 MCP 服务器

配置服务 / 工具注册表
扩展管理器 / 业务数据

dsh 子进程
read-only 预设

DeepSeek / 客户自己的
OpenAI 兼容端点


四、为什么选"内嵌",而不是让客户自己装

写这个系列之前我认真纠结过要不要把 dsh 打进安装包——它会让安装包大一圈。最后还是决定内嵌,原因都来自冰石客户的实际情况:

第一,用户不是程序员。 冰石的客户是汽服门店老板、电商客服主管、HR 专员。让他们装 Node.js 22、配 PATH、跑 pnpm——不可能。GeekPark 的报道里也提到 dsh 的界面对非程序员不友好。对他们来说,功能必须是"点一下就有"的。

第二,部署环境千奇百怪。 很多冰石跑在门店前台那台电脑上,因为个人微信要做 UI 自动化。那台电脑可能三年没更新过,公司网络可能访问不了 npm。安装时"顺便在线下载"一个 70MB 的运行时,失败率会很高。

第三,白标交付。 我们给合作伙伴做品牌定制版,build_mv.py 一条命令打出带对方名字、图标、Logo 的 exe。交付物必须是自包含的,不能附一句"另外请安装以下依赖"。

第四,版本必须锁死。 dsh 是预览版,接口会变。如果让客户自己装,客户装到哪个版本我们控制不了。打进 exe 里,版本跟着冰石的版本走,我们测过哪个就发哪个。

最后一条其实是最关键的。预览版的软件,内嵌反而是更保守的选择——它把不确定性关在了我们自己的构建流程里。


五、内嵌进 exe 的工程方案

5.1 先算体积账

dsh 没有发官方的单文件 exe。Python SDK 依赖一个平台相关的运行时包 deepseek-harness-runtime-bin,里面打包了 dsh 命令行和它的 Node 依赖——Python 程序不需要另外装 Node,就是靠这个包。实测体积:

包大小
deepseek-harness-sdk(Python SDK 本身)13.7 KB
deepseek-harness-runtime-bin Windows x64 wheel约 72 MB(压缩)
同一个包的其他平台 wheel75–81 MB

注意 72MB 是 wheel 压缩后的大小,解压安装后会更大,具体多大我建议各位打包时自己实测一下。作为参照,社区做的 Electron 版 dsh 桌面程序,安装包约 148MB,解压后 264MB——那是连 UI 一起打的,我们不需要它的 UI。

所以对冰石来说,结论是:安装包大约增加 70–100MB。冰石现在的安装包里本来就有 pandas、openpyxl、lxml 这些大件,这个增量能接受。

还有一个版本上的坑:写这篇时 PyPI 上 deepseek-harness-sdk 最新是 0.1.5rc1,而仓库主干已经到 0.1.7-rc.2。PyPI 落后仓库两个小版本,文档里的新特性,PyPI 版本上不一定有。

5.2 目录布局:跟着扩展目录的思路走

冰石的扩展管理器有个现成的约定:开发环境下扩展在 backend/extensions/;打包成 exe 后,扩展放在 exe 所在目录的 extensions/ 下,而不是打进 exe 内部。这样客户可以热插拔扩展,不用重新打包。

dsh 运行时我也按这个思路放:

冰石机器人/
├── 冰石机器人.exe
├── extensions/            # 已有:业务扩展,热插拔
├── harness/               # 新增:dsh 运行时(来自 runtime-bin)
│   └── ...                # dsh 入口 + Node 依赖
└── data/
    └── harness_home/      # 新增:DSH_HOME,放 profile、patch、会话日志
        ├── profiles/icestone/cordis.patch.yml
        ├── sessions/
        └── logs/

为什么不打进 exe 内部?冰石的 build_mv.py 支持 onefile 和 onedir 两种模式。onefile 模式下,PyInstaller 每次启动都要把内部文件解压到临时目录——多一个几十兆、文件数上千的 Node 依赖树,启动会明显变慢,而且杀毒软件扫描临时目录时经常误报。放在 exe 旁边,只解压一次(安装时),启动不受影响。

5.3 打包:加一个开关

build_mv.py 已经有 --version、--name、--icon、--logo、--mode 这些参数。加一个 --with-harness:

# build_mv.py(示意)
parser.add_argument(
    '--with-harness',
    action='store_true',
    help='内嵌 DeepSeek Harness 运行时(安装包约增加 70–100MB)'
)

def copy_harness_runtime(dist_dir: Path):
    """把 runtime-bin 里的 dsh 运行时拷到 exe 旁边的 harness/ 目录"""
    import deepseek_harness_runtime_bin as rt   # 包名以实际 wheel 为准
    src = Path(rt.__file__).parent
    dst = dist_dir / 'harness'
    shutil.copytree(src, dst, dirs_exist_ok=True)
    # 锁版本:把版本号写进构建信息,运行时校验
    (dst / 'VERSION').write_text(rt.__version__, encoding='utf-8')

不带这个开关打出来的包,AI 配置助手面板直接隐藏,其他功能不受影响。白标客户可以按需选择要不要这 70MB。

5.4 HarnessService:一层薄封装

后端加一个服务,负责启动 dsh、准备 profile、跑任务、收事件:

# services/harness_service.py(示意)
import secrets
import sys
from pathlib import Path
from deepseek_harness import DeepSeekHarness

def _app_dir() -> Path:
    # 与扩展管理器同一套规则:打包后以 exe 所在目录为基准
    if getattr(sys, "frozen", False):
        return Path(sys.executable).parent
    return Path(__file__).resolve().parents[1]

class HarnessService:
    def __init__(self, llm_config, mcp_port: int):
        self.home = _app_dir() / "data" / "harness_home"
        self.workspace = _app_dir() / "data" / "harness_workspace"
        self.mcp_token = secrets.token_urlsafe(32)   # 每次启动换新
        self.llm = llm_config
        self.mcp_port = mcp_port

    def _write_patch(self) -> Path:
        """每次启动生成 patch:挂冰石 MCP、只读预设、关会话日志上传"""
        patch = self.home / "profiles" / "icestone" / "cordis.patch.yml"
        patch.parent.mkdir(parents=True, exist_ok=True)
        patch.write_text(render_patch(port=self.mcp_port, token=self.mcp_token),
                         encoding="utf-8")
        return patch

    def run_task(self, instruction: str, session_id: str, on_event):
        with DeepSeekHarness(
            provider=self.llm.provider,          # deepseek-official 或自定义网关
            model=self.llm.model,                # 如 deepseek-v4-flash
            api_key=self.llm.api_key,
            base_url=self.llm.base_url,
            max_tokens=49_152,
            cwd=str(self.workspace),
            dsh_home=str(self.home),
            dsh_bin=str(_app_dir() / "harness" / "dsh"),   # 指向内嵌运行时
            profile="sdk",
            patches=(str(self._write_patch()),),
        ) as harness:
            return harness.run(instruction, session_id=session_id,
                               on_notification=on_event)

几个设计点:

  • dsh_home 显式指定。 SDK 的文档写明它"never discovers ~/.dsh",这很好——不会读到用户电脑上别的 dsh 配置,冰石的 dsh 和客户自己装的 dsh(如果有)互不干扰。
  • 模型配置复用冰石的。 冰石本来就支持 DeepSeek、通义、OpenAI 等多家模型。dsh 支持自定义 provider,协议可选 openai-completions、openai-responses、anthropic-messages,客户在冰石里配好的模型直接传进去,不用配第二遍。
  • run() 是同步阻塞的。 冰石后端是 async 的 FastAPI,要丢进线程池跑,事件通过 WebSocket 推给前端面板。

5.5 那个一定要关的默认项

读 base bundle 配置时我发现一件事:base bundle 默认会随 DeepSeek 请求上传会话日志(session-log-deepseek 插件)。

对编程工具来说这也许无所谓,但冰石的会话里会有客户的配置、订单、聊天记录片段。给企业客户交付的软件,这个必须关:

# 冰石生成的 cordis.patch.yml 片段(示意,具体写法以官方文档为准)
- id: session-log-deepseek
  config:
    enabled: false

同理,遥测也建议关掉(DSH_TELEMETRY_DISABLED)。这类默认值,集成方必须逐个过一遍,不能想当然。

5.6 生命周期和升级

  • 一任务一进程。 每个 with DeepSeekHarness(...) 起一个 dsh 子进程,任务结束就退出。冰石的 AI 配置任务频率很低(一个客户一天几次),没必要常驻。常驻还得处理内存泄漏和僵尸进程,得不偿失。
  • 并发上限设 1。 同一个冰石实例同时只跑一个 harness 任务。配置类操作本来就不该并发,两个任务同时改同一份提示词是灾难。
  • 会话可续。 session_id 用冰石自己的任务 id,任务中断后可以用同一个 id 续上——这是 JSONL 会话日志白送的能力。
  • 升级跟着冰石走。 每次升级 dsh 版本,都要跑一遍我们自己的集成回归(下一篇讲那些配置场景的测试用例),通过了才发版。harness/VERSION 和冰石的版本号一起写进"关于"页面,排障时一眼能看到。

六、把冰石的能力暴露给 dsh:写一个 MCP 服务器

6.1 为什么是 MCP

前面说了,Python 里没法直接往 dsh 注册工具。剩下两条路:写 dsh 的 TS 插件,或者写 MCP 服务器。

TS 插件意味着冰石得维护一套 TypeScript 代码,再通过 HTTP 回调 Python 后端——多一层,多一门语言。MCP 服务器可以直接挂在冰石现有的 FastAPI 上,工具的实现就是冰石已有的 Python 代码。

dsh 的 MCP 客户端支持 stdio 和 Streamable HTTP 两种传输。冰石本身就是个常驻的 HTTP 服务,用 Streamable HTTP 最自然。patch 里这样挂:

# 示意:在 profile patch 里插入 MCP 客户端插件
# 官方文档给的是 stdio 示例;streamable-http 的 url/headers 字段名请以 mcp-client 的 README 为准
- insert:
    - id: mcp-icestone
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: icestone
        transport: streamable-http
        url: http://127.0.0.1:{port}/mcp
        headers:
          Authorization: Bearer {token}

挂上之后,冰石的工具在 dsh 里的名字会变成 mcp__icestone__<工具名>。

6.2 复用现有的助手工具注册表

冰石的智能体助手有一个独立的 assistant_tool_registry,和客服机器人用的全局 tool_registry 完全隔离。这个隔离设计现在派上了大用场——助手工具本来就是"给管理员用的配置工具",正好整体映射成 MCP 工具;客服机器人给客户用的发图、打标签那些工具,不暴露给 dsh。

# api/mcp_server.py(示意,基于官方 mcp Python SDK 的低层 Server)
from mcp.server.lowlevel import Server
import mcp.types as types
from core.assistant_tools import assistant_tool_registry, execute_assistant_tools

server = Server("icestone")

EXPOSED = {   # 显式白名单,不是注册表里有什么就暴露什么
    "assistant_query_groups", "assistant_query_keywords", "assistant_get_system_config",
    "assistant_query_faqs", "assistant_query_orders",
    # 写操作不直接暴露,换成第二篇讲的"变更集"工具
}

@server.list_tools()
async def list_tools() -> list[types.Tool]:
    tools = []
    for name in EXPOSED:
        t = assistant_tool_registry.get_tool(name)
        if t:
            tools.append(types.Tool(
                name=name.removeprefix("assistant_"),
                description=t.get_description(),
                inputSchema=to_json_schema(t.get_parameters()),
            ))
    return tools

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    results, summary = await execute_assistant_tools(
        [make_tool_call("assistant_" + name, arguments)],
        context={"user_id": current_admin_id(), "source": "harness"},
    )
    return [types.TextContent(type="text", text=summary)]

6.3 一个马上会踩的坑:参数格式不是 JSON Schema

写上面这段的时候我翻了一下冰石助手工具的参数定义,发现是这样的:

def get_parameters(self):
    return {
        "key":   {"type": "string", "required": True, "description": "配置键"},
        "value": {"type": "string", "required": True, "description": "配置值"},
    }

这是冰石自己的简化格式,required 写在每个字段里。而 MCP 要的 inputSchema 是标准 JSON Schema,required 是对象上的一个数组。直接塞进去,dsh 那边的模型会以为所有参数都是可选的。

所以中间要有一个 to_json_schema() 转换。更麻烦的是,冰石的扩展工具里有的用标准 JSON Schema(比如 hello_ext 里 {"type": "object", "properties": {...}}),有的用简化格式——两种都得认。

这种事不写代码不会发现,写了才知道。这也是我坚持"方案文章也要把示意代码写到能对上真实代码"的原因。

6.4 MCP 端点本身的安全

/mcp 端点等于把冰石的管理能力开了一个口子,必须管住:

  • 只监听 127.0.0.1。 dsh 是本机子进程,不需要外部访问。
  • 每次启动换新 token。 token 只写进 dsh 的 patch 文件和冰石内存里,不落配置库。
  • 调用身份绑定到发起任务的管理员。 通过 MCP 进来的每个调用,都以"发起这次 AI 任务的那个管理员"的身份执行,受冰石现有 RBAC 约束——普通客服账号发起的任务,改不了系统配置。
  • 来源打标。 context 里带 source: harness,所有操作日志都能区分"人改的"还是"AI 改的"。

七、权限设计:三层,一层都不能少

前面几节已经零散提到了,这里汇总一下。因为 dsh 的 Plan mode 是软的、沙箱在 Windows 上是部分生效的、SDK 又收不到审批请求,冰石的权限必须自己兜底:

层在哪管什么
第一层:dsh 最小权限profile 选 read-only 预设dsh 自己不能写文件、不能乱跑命令
第二层:工具白名单冰石 MCP 服务器的 EXPOSEDdsh 能看到的只有我们挑过的工具
第三层:变更集 + 人工确认冰石的写操作工具任何改动先生成预览,管理员在冰石界面点确认才生效

第三层是核心。简单说就是:**dsh 永远不能直接"改",只能"提议改"。**它调 propose_change 把要改的内容放进一个变更集,冰石界面展示 diff,管理员点"应用",冰石才真正写库,写之前先打快照。整个流程怎么设计、会踩哪些坑,是下一篇的主要内容。

有人会问:既然都要人点确认,那 AI 省了什么?省的是**“知道要改哪儿、改成什么”**。客户不用知道"跟进时间"在规则 JSON 的哪个字段、"打标签"要去工具管理里勾哪个开关——他只需要看懂 diff,点确认。


八、成本与风险:先把丑话说在前面

风险来源应对
接口破坏性变更官方 README 明说内嵌锁版本;升级前跑集成回归
token 消耗高第三方测试同模型下约为其他 harness 的 3 倍默认用 flash 级模型;任务级 token 预算;Goal 续跑轮数设低
沙箱不可靠Windows ACL 部分生效,网络与读不受限选只读预设,所有副作用走冰石工具
数据外发默认上传会话日志、遥测patch 里显式关闭,逐项核对默认值
安装包变大runtime 约 72MB 压缩--with-harness 开关,按客户选择
PyPI 滞后PyPI 0.1.5rc1 vs 仓库 0.1.7-rc.2以实际锁定版本的文档为准,别看主干文档写代码

token 这条单独说一下。Goal 的自动续跑默认上限是 256 轮——对编程任务也许合理,对"帮我配个 SOP"来说太多了。冰石这边我打算按任务类型设预算:配置类任务 20 轮以内,建工具类 40 轮以内,超了就停下来问人。

**AI 干活的成本,一定要让客户在点"开始"之前就能预估。**这是 B 端软件和个人编程工具最大的区别之一——个人开发者多花几块钱无所谓,企业客户看到账单翻三倍,第二天就会把功能关掉。


九、写在最后

把这篇压成三句话:

第一,harness 是模型之外让它能干活的那层软件。 循环、工具、上下文、持久化、权限、规划,每一样自己写都要花时间。dsh 把这些做成了可插拔的插件,集成方只需要写 patch、写工具。

第二,dsh SDK 的三个限制决定了集成架构。 只有三个协议方法、宿主收不到审批请求、Python 里不能直接注册工具——所以冰石的能力要以 MCP 服务器暴露,写操作要走冰石自己的工具、由冰石自己审批。

第三,对预览版软件,内嵌反而是保守的选择。 多 70–100MB,换来的是版本可控、离线可用、白标可交付。运行时放在 exe 旁边而不是 exe 里面,默认的日志上传和遥测要逐项关掉。

架子搭好了,下一篇讲真正的业务:客户说一句"帮我配一个汽服门店的回访流程",harness 是怎么把它拆成十几个配置动作、生成 diff、让客户确认、再自己验证的;以及它怎么给冰石写一个新扩展工具,测好、装上、启用。


参考资料

本文为架构设计文章,文中代码为示意代码。DeepSeek Harness 相关内容基于 v0.1.7-rc.2 预览版的官方文档与源码整理,预览版接口可能变化,请以官方最新文档为准。

DeepSeek桌面端取代WebUI:原生系统集成与IPC直连架构解析 桌面端AI应用正从浏览器封装走向操作系统原生集成,其核心在于绕过HTTP/REST瓶颈,采用进程间通信(IPC)直连推理引擎,并深度调用GPU、文件系统、剪贴板等系统能力。相比WebUI依赖浏览器沙箱带来的性能损耗、权限限制与离线脆弱性,现代桌面端方案通过Rust后端、Electron渲染层与本地模型协同,实现低延迟响应、拖拽式文件处理、全局快捷键唤醒及硬件级加速。DeepSeek Harness Desktop正是这一范式的典型代表,它不仅提供模型能力交付,更重构了人机交互流——从输入层的多模态捕获,到处 阅读详情

相关推荐

DeepSeek Harness 整体架构解析

表格原则含义体现在哪一层一切皆插件没有特权核心,所有功能都是插件,可替换 / 禁用 / 热重载第 5 层 Cordis协议即契约Client 与 Host、插件与插件之间通过明确定义的接口 / 事件通信第 3 层能力接缝注册即效果所有注册都是可逆的,插件卸载时自动回滚第 5 层 Cordis模型可见 ⟺ 已记录任何到达模型的内容必须可从会话日志重建第 4 层 session能力接缝三角色每个能力 = Service Definition + Provider + Consumer,缺一不可。

大坡3D软件开发 84

DeepSeek Harness(dsh)从零到全栈【1】认识 DeepSeek Harness:Agent、Harness 与“一切皆插件“

本章从"模型只会输出 token"这一基本事实出发,厘清Agent = Model + Harness 的本质,并系统拆解 harness 承担的五类工程职责(工具安全执行、上下文管理、状态持久化、权限审批、多轮编排)。随后对比 2026 年主流 agent harness 格局,引出 DeepSeek Harness(`dsh`)的四个差异点,深入解读其"一切皆插件"架构在源码层面的含义——不存在特权内核,模型适配器、工具注册表、会话日志乃至 agent loop 本身皆可配置替换。

缘友一世的博客 1684

网易CodeWave智能生成应用实战:5分钟搞定库存管理系统(附详细配置截图)

本文详细介绍了如何利用网易CodeWave智能生成应用在5分钟内快速构建定制化库存管理系统。通过自然语言描述需求,无需编程即可生成包含产品管理、库存预警等核心功能的应用,并支持字段微调、业务流程注入等深度优化。文章附有详细配置截图,帮助用户高效实现数字化转型。

julia4scientist的博客 888

learn-harness-engineering 实战:解码 Pi、Claude Code、Codex 与 DeepSeek Harness 的四种前沿 harness 架构

本板块(对应仓库 [docs/fr/harness-designs/](https://link.gitcode.com/i/e2ee0f375ff3849f94ac5761151ac078))将课程中讲授的 harness 理论与当下最先进的实际产品逐一对账,只回答一个问题:**这些产品的 harness 是如何设计的?** 读完本文,你将掌握一套五子系统分析框架,能够独立解剖任意 AI 编程工

gitblog_00709的博客 212

体验灵雀云-创建基于Docker的云服务

今天体验了一下灵雀云,创建了第一个基于Docker的云服务。 1.登录灵雀云 2.开始使用 登录之后,从"控制台"进入操作界面,开始创建服务。 首先需要选择一个镜像。灵雀云已经为您提供了一些常用的镜像列表。请在“常用镜像”列表中,选择“其它”,然后找到“alauda/hello-world”镜像,点击它右侧的“选择”按钮,进入服务参数配置页面。 选择完要创建的

tomcat的专栏 3234

cdh zookeeper未授权访问(安全漏洞)处理

前言: 最近公司在做安全漏洞扫描。发现cdh zookeeper存在未授权访问的问题。 ZooKeeper的节点有5种操作权限: CREATE、READ、WRITE、DELETE、ADMIN 也就是 增、删、改、查、管理权限,这5种权限简写为crwda(即:每个单词的首字符缩写) 注:这5种权限中,delete是指对子节点的删除权限,其它4种权限指对自身节点的操作权限 ZooKeeper的身份的认证有4种方式: world:默认方式,相当于全世界都能访问 auth:代表已经认证通过的..

belialxing的专栏 2448

DeepSeek Harness Desktop 内置 Agents Anywhere 桥接包:发布管线、Profile 集成与 Connector 运行全解析

> 本篇以 [vendor/agents-anywhere/README.md](https://link.gitcode.com/i/f46484fefefab89b255e2b2e3bcb0e73) 为主体,结合仓库内的发布脚本、Profile 组装源码与无头验证脚本,完整拆解 DSH Desktop 如何以「固定版本内置」的方式集成 Agents Anywhere(AA)的 `@agents

gitblog_00443的博客 505

Ubuntu20.04安装Eigen3.3.7、模板类Sophus和Ceres

Sophus的使用必须依赖3.3以上的Eigen版本。如果版本太低,Sophus库将无法安装使用。

qq_62964142的博客 3422

Ekko Studio 深度集成 DeepSeek Harness:安装、配置、插件与 ACP 运行全解析

本文以 Hermes Studio(Ekko Studio)仓库中的 [docs/dsh-management.md](https://gitcode.com/gh_mirrors/he/hermes-studio/blob/85e1f0d5252582449369e9cd734437bfa544f658/docs/dsh-management.md?utm_source=gitcode_repo

gitblog_00990的博客 386

百度API实现人流量数量检测(动态)

百度的这个API还挺好用的,对与不追求高精度的人来说非常适用,结合他官方给的文档,极易上手。 需要做的就是通过API Key和Secret Key获取的access_token。 然后稍微修改下代码就行,但是他给的代码并没有直接从摄像头获取视频,而是读取一个文件夹,那么就需要自己先对摄像头的输出视频进行处理。 识别结果如下,"person_num"是当前画面的人数,in是累计进入的人数,out是累计走出去的人数。 他这个有个缺点就是返回值里边并没有实时返回in和out的值,而是都是0,但是这个图片上有,图片

qq_42479987的博客 3382

JY02无刷电机驱动芯片的硬件设计与调试实战

本文详细介绍了JY02无刷电机驱动芯片的硬件设计与调试实战。重点解析了其外置MOSFET的设计优势,提供了从电源滤波、功率MOSFET选型到电流采样保护的核心电路设计指南。文章还分享了安全上电、动态测试及常见问题排查的完整调试流程,并探讨了开关优化、闭环测速等性能提升技巧,帮助开发者构建稳定高效的无刷电机驱动系统。

weixin_29193359的博客 366

DeepSeek Harness 的 Vendored 包治理:Cordis 框架源码级内嵌、本地修改纪律与同步流程

本篇文章围绕 DeepSeek Harness 仓库中的 [vendor/AGENTS.md](https://link.gitcode.com/i/35f91af95ebad30807c65bbafb69765c) 展开,系统讲解该项目如何将 Cordis 框架及其基础库以**源码级 vendored(内嵌)**的方式纳入 monorepo:包括 `vendor/` 目录的完整清单与 manif

gitblog_01176的博客 352

UMI——斯坦福刷盘机器人:通过手持夹爪革新数据收集方式,且使用视觉SLAM和Diffusion Policy预测动作

没想到今年年初的斯坦福mobilealoha的热度刚过,而到今年2月的下旬,斯坦福另一个团队又推出了UMI刷盘机器人,且这两个团队还互相认识、还在一块共同切磋(顺带小小感叹一下,斯坦福的氛围是真好而且真高产)斯坦福UMI刷盘机器人其与mobile aloha(以及AirExo: Low-Cost Exoskeletons for Learning Whole-Arm Manipulation in the Wild)最大的不同在于其收集数据处理的非真实的机器人,而是一个手持夹持器(从而大幅降低成本)

u013250861的博客 1357

DeepSeek Harness 按模型推理声明:pi-ai 适配器的 `reasoningEfforts` 与 `modelOverrides` 设计解析

> 本文围绕 DeepSeek Harness 仓库中一份已实施(implemented)的 Agent Note——「llm-pi-ai 的按模型推理声明」——展开,系统梳理其问题背景、决策内容、方案取舍与落地影响,并对照 [`packages/llm/llm-pi-ai`](https://link.gitcode.com/i/02f09192d265580413fa1b2e12ce9e58)

gitblog_00117的博客 694

实用指南:制作通用的INCA和CANape兼容A2L文件

A2L(ASAM MCD-2 Measurement and Calibration Data)文件是描述ECU(电子控制单元)测量和校准数据的标准文件格式。在标定工作中,A2L文件扮演着极为重要的角色,它定义了测量通道、校准参数等关键信息,为工程师提供了统一的描述方式。INCA和CANape是两种常见的汽车电子系统标定工具,分别由ETAS和Vector公司开发。它们在汽车电子系统的开发和调试过程中发挥着重要作用,提供了丰富的标定功能和用户友好的界面。

一直在水些技术小文 2924

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

从传统客户端到AI智能体平台:DeepSeek Harness迁移实战指南

客户端开发正经历从传统桌面应用向AI增强开发平台的范式转变。传统客户端开发面临维护成本高、迭代速度慢、资源占用大等痛点,而现代开发工具通过插件化架构和AI智能体技术实现了根本性变革。AI Agent作为能够理解自然语言指令并自主调用工具完成开发任务的智能程序,结合插件化设计解决了功能臃肿和资源冲突问题,为开发提效带来了新的可能性。这种架构转变使得开发环境从“功能固化的桌面软件”演变为“可动态扩展的智能工作流”,在代码生成、Bug修复、自动化测试等场景中展现出巨大价值。本文以DeepSeek Harness为

weixin_30753873的博客 399

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

DeepSeek Harness Web 包安全策略:凭据承载请求为何必须拒绝重定向

本篇技术指南聚焦 DeepSeek Harness 中 [packages/web/AGENTS.md](https://link.gitcode.com/i/cf9152c535208f5a7fa42834db7484bf) 定义的 Web 包安全铁律:**凡是携带凭据的 provider 请求,必须在跟随任何重定向响应之前失败**。文章将结合 `web-search-deepseek`、`we

gitblog_00414的博客 677

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

DeepSeek Harness 全景技术解析-Day23

DeepSeek Harness(dsh)是DeepSeek AI开源的Agent运行时框架,定位为连接大语言模型与真实世界的"执行操作系统"。其核心采用"一切皆插件"的设计理念,基于Cordis元框架实现动态组合能力,支持模型适配、工具注册等功能的灵活扩展。项目采用TypeScript开发,以pnpm Monorepo管理,包含核心模块、LLM适配、Shell执行等能力族。通过Profile和Bundle机制实现配置组合,当前处于开发者预览阶段,不建议直接用于生产环境。

m0_51089660的博客 875

DeepSeek-Harness部署踩坑

文章摘要: DeepSeek-Harness(dsh)是DeepSeek推出的本地大模型API调试工具,需通过Node.js命令行运行。提供三种启动方式:1)npx临时运行;2)全局安装(推荐);3)dsh-launcher桌面启动器(适合新手)。重点介绍了dsh-launcher的功能优势(双击即用、开机自启、错误诊断等)和安装方法,并给出常见问题的解决方案(如命令未找到、端口占用等)。最后推荐两种简化流程:命令行派通过npm全局安装后使用bat脚本启动,桌面派直接安装dsh-launcher实现一键操作

2401_88525688的博客 4979

Cordis插件架构:DeepSeek Harness中的能力编排与语义路由

在大模型应用开发中,插件架构正从简单功能扩展转向精细化能力治理。Cordis作为DeepSeek Harness内置的插件生命周期管理与能力路由协议,本质是面向模型能力爆炸增长场景的柔性编排中枢。它通过标准化契约声明、语义图谱驱动的动态匹配、受控上下文透传等机制,实现插件间高内聚低耦合的协同。相比传统硬编码调用或规则引擎路由,Cordis以能力解耦替代功能叠加,支撑法律、金融、医疗等多领域插件的规模化集成与自适应组合。其核心价值体现在响应稳定性、错误收敛性与调试可观测性上,尤其适用于需求模糊、长尾多变的企业

weixin_29051811的博客 302

【开源】DSH GUI:DeepSeek Harness 桌面壳完整指南(内嵌 Web UI / 自动更新引擎 / 跨平台打包)

**DSH GUI** 是 [DeepSeek Harness](https://www.deepseek.com/harness/)(DeepSeek 开源 Agent 框架,npm 包 `@deepseek-ai/dsh`,技术预览阶段)的非官方桌面外壳。它把 Harness 的 Web UI 装进原生桌面窗口中,开箱即用、常驻系统托盘、自动保持引擎最新,同时保留完整的官方 Harness 能力。

晨石的博客 501

给 DeepSeek Harness 装上“睡眠循环“:dsh-skillopt 插件集成 SkillOpt-Sleep 实战指南

> **导读**:本文讲解 SkillOpt 项目中的 DeepSeek Harness(dsh)集成插件 `dsh-skillopt`——它通过 Cordis 插件体系把 SkillOpt-Sleep 睡眠引擎(harvest → mine → replay → consolidate → stage → adopt)暴露为 7 个原生工具,让 dsh 智能体在夜间离线复习历史会话、按你自己的

gitblog_00903的博客 147

把 DeepSeek Harness 智能体嵌进 IntelliJ IDEA —— 类 Qoder 的 AI 编程插件

【开源】DeepSeek Harness 智能体 IDEA 插件:嵌入式 AI 编程助手 这个开源项目将 DeepSeek Harness(dsh)智能体工作台集成到 IntelliJ IDEA 中,解决 AI 编程中的常见痛点: 消除浏览器/IDE切换 通过MCP桥接让AI感知项目上下文 提供代码审查/还原功能 支持一键发送选中代码 核心功能: 内置完整dsh Web UI 自带Node.js运行时(开箱即用) 6个MCP工具实现IDE上下文感知 代码变更Diff审查机制 项目级生命周期管理 技术亮点:

学无止步的博客 1302

DeepSeek Harness验证插件:自动化LLM输出质量检查实战指南

在大语言模型(LLM)应用开发中,输出质量验证是确保自动化流程可靠性的关键环节。传统的人工复查方式难以应对批量任务,而基于规则的自动化验证技术应运而生。其核心原理是通过预定义规则或辅助LLM对模型输出进行二次判断,实现格式合规性、内容完整性等维度的自动检查。这项技术的工程价值在于将验证环节无缝集成到任务流水线中,显著提升开发效率并降低人工成本。在自动化内容生成、代码审查、数据清洗等场景中,验证机制能有效保障输出结果的稳定性和可用性。本文聚焦DeepSeek Harness框架的LLM-as-a-Verifi

weixin_34209851的博客 335

从传统客户端到AI Agent平台:池建强团队迁移DeepSeek Harness实战解析

在当今软件开发领域,AI Agent正成为重构应用架构的核心技术。其原理在于通过大语言模型(LLM)的规划与工具调用能力,将复杂业务逻辑转化为可编排的工作流。这一转变的技术价值在于,它使应用从“代码驱动”转向“智能驱动”,大幅提升了应对业务变化的敏捷性。在实际应用场景中,AI Agent平台尤其适合处理那些需要灵活决策、多步骤协作的任务,例如智能客服、报告生成和流程自动化。本文以池建强团队迁移DeepSeek Harness的真实案例为切入点,深入探讨了如何将传统客户端中的固化逻辑,通过可视化编排重构为云端

weixin_32487557的博客 314

DeepSeek Harness 匿名用户标识设计解析:`$DSH_HOME/.anonymous-user-id` 与 OTel Resource `user.id`

本文以 DeepSeek Harness 仓库中的架构决策记录([Agent Note](https://link.gitcode.com/i/2e00ff3c739a2c520fb82e02a304630f))为主体,结合其落盘实现与三大消费方源码,完整讲解会话遥测(Session Telemetry)中匿名用户标识的设计权衡、存储契约与并发语义。读完你可以掌握:匿名 UUID 如何被生成与持久

gitblog_01110的博客 919
上一篇: 企业微信智能客服的挑战与实现(四):从单机版到SaaS——多租户改造实录
下一篇: DeepSeek Harness 集成实战(二):一句话配置与自动创建工具
冰石科技
博客等级 码龄19年 77粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值