DeepSeek Harness架构深度解析:一切皆插件如何重构Agent运行时

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

2026年8月13日,DeepSeek以MIT许可证开源了DeepSeek Harness(简称dsh),一个基于Cordis微内核的Agent运行时框架。它的架构宣言只有一句话:Everything is a Plugin。模型适配器、工具注册表、会话日志、Agent Loop本身甚至Web前端,全部是地位平等的插件。这不是又一个API聊天客户端,而是一套用于组装Agent的开源基础设施。本文从Cordis插件树、事件源会话、工具安全流水线、四种运行模式、多Agent编排和横向选型等维度,深度解析DeepSeek Harness如何重构Agent运行时。

一、Agent竞争的重心转移:从模型到Harness

1.1 为什么2026年Harness成为主角

早期LLM应用的典型形态是系统提示词加聊天历史再加一次API请求。工具调用出现后,应用需要在模型和现实世界之间反复循环:读文件、执行命令、检查输出、修改代码、跑测试,直到任务结束。此时决定成败的不再只是一段提示词,而是一套运行时制度。

演进阶段

应用重心

核心问题

Harness的回答

单轮对话

Prompt与生成质量

如何说清需求

系统提示词模板

工具调用

模型与API对接

如何调用、重试和解析

工具注册表与Agent Loop

长程任务

跨多步保持状态

上下文溢出、中断、恢复

事件日志、压缩与持久化

多Agent协作

分工、回报与审核

队列、身份、资源和取消

子代理运行时与Workflow

生产化

安全、观测和组织策略

Agent能碰什么、出错如何追责

审批、沙箱、回放与遥测

1.2 DeepSeek Harness的关键时间线

时间节点

事件

工程含义

2026年5月

DeepSeek官方招聘Agent Harness团队

目标不是维护API Demo,而是打通模型、产品反馈和Agent研究

2026年8月13日

deepseek-ai/deepseek-harness公开,MIT许可证

DeepSeek选择开放Harness层,让社区能替换模型、工具、沙箱和前端

2026年8月19日

版本迭代至v0.1.0-rc.8,12,940次提交

插件生态快速扩张,25位贡献者参与开发

2026年8月20日

社区插件生态启动,dsh-plugin话题开放

第三方插件可通过GitHub Topic被发现和安装

DeepSeek模型原本就能通过OpenAI或Anthropic兼容协议接入Claude Code、OpenCode等三方工具,因此能用DeepSeek写代码不是产品空白。真正缺失的是对Harness自身的控制权:模型看到什么上下文、如何编排子代理、什么反馈可以回流评测与训练。dsh的目标就是填补这一层。

二、Cordis微内核:不设特权内核的插件树

2.1 架构全景:五层插件堆叠

DeepSeek Harness基于Cordis框架构建。Cordis源自Koishi生态,其设计思想来自论文A Programming Paradigm for Spatiotemporal Composability。Cordis只做三件事:插件的加载、卸载和依赖管理。它本身不承载任何Agent能力,像个乐高底座板,只提供插口。

┌──────────────────────────────────────────────────┐

│              产品入口层                          │

│  Web UI · Headless · SDK · API Gateway          │

├──────────────────────────────────────────────────┤

│              Agent运行层                         │

│  Agent Loop · Session · Prompt · Scope · Compaction │

├──────────────────────────────────────────────────┤

│              能力与策略层                        │

│  Tools · Skills · MCP · LSP · Subagent · Approval │

├──────────────────────────────────────────────────┤

│              执行与存储层                        │

│  FS · Shell · PTY · Sandbox · SQLite/JSONL · OTel │

├──────────────────────────────────────────────────┤

│              模型适配层                         │

│  DeepSeek · OpenAI · Anthropic · 自定义兼容端点   │

└──────────────────────────────────────────────────┘

           每一层都通过Cordis插件组合

这种架构的要点不是插件数量多,而是核心循环也没有特权。如果一个团队希望把本地文件系统和进程执行替换为远程沙箱,可以替换对应Service Provider;依赖这两项服务的Bash、PTY和LSP也会随之转移,而不需要复制一套Agent Loop。

2.2 Profile、Bundle与Patch:插件组合的三层配置

运行中的dsh是一棵按序叠加的插件树。profile是具名组装,bundle是可分发的插件配置包,cordis.patch.yml负责覆盖或插入配置。

组合对象

职责

官方默认

dsh-base

模型、工具、持久化、沙箱、审批、凭据、遥测

所有profile的底座

dsh-web-app

Web服务器与浏览器界面

web profile

dsh-headless

一次性执行器,不启动服务器

headless profile

profile patch

某个组装的本地差异

安装第三方插件、替换实现

home patch / --patch

用户级或本次启动覆盖

环境策略和实验配置

同一套核心可以被组装为Web Agent、无头CI任务执行器、特定企业环境的受限Agent,或完全不同的前端产品。开发者可用命令查看最终组装结果:

dsh --profile web --dump-config

2.3 Capability Seam:可替换能力的三个角色

DeepSeek Harness把可替换能力称为seam,并拆成三个角色。这种拆分比把所有功能都做成一个工具插件更严格,要求开发者先明确能力边界,再分别处理实现与暴露。

角色

含义

以文件系统为例

Service Definition

稳定接口和领域词汇

ctx.fs定义读写能力

Service Provider

具体执行环境

本地FS、沙箱FS或E2B远程FS

Consumer

面向模型或用户的入口

读文件、编辑文件工具

三、四种运行模式深度拆解

DeepSeek Harness提供四种运行模式,每种模式对应不同的插件组合和工具集,覆盖从全功能编码到基准测试的完整场景。

运行模式

工具集

典型场景

核心特征

Standard模式

文件编辑、Shell、文件搜索、Web搜索、Skills、规划、目标、子代理、工作流

日常编码与复杂任务

全工具集,最通用

Code模式

Standard全部能力 + Code Mode SDK

多步骤工具编排

模型生成TypeScript程序编排多轮操作

Minimal模式

仅Shell + str_replace_editor

模型基准测试

最小环境,两工具编码Agent

Creator模式

Standard全部能力 + 运行时检查 + 插件实验

自定义Agent预设

检查运行时、内存中测试Cordis插件

Minimal模式的设计意图尤为值得关注。它只保留两个工具——持久化bash和str_replace_editor——专门用于在最小环境中评估模型的真实编码能力,排除丰富工具集带来的性能偏差。这对模型评测和选型具有直接工程价值。

四、事件源会话:模型可见即已记录

4.1 Turn、Step与Tool Call的精确定义

DeepSeek Harness对一次任务的定义极其精确:一个step是一次模型请求及其触发的工具调用;一个turn包含零个或多个step,直到系统不再欠任何待处理工作才结束。

用户输入进入 inbox

     ↓

turn/start

     ↓

agent/pre-step:改写、拒绝或放行本次输入

     ↓

step/start → 组装 Prompt 与 Tool Schema

     ↓

agent/request → llm/stream → assistant/message

     ↓

tool/call → 审批/守卫/执行/后处理 → tool/result

     ↓

step/end

  ├─ 还有工具结果或新输入 → 下一个 step

  └─ 没有待办 → turn/end

agent/pre-step、agent/request、llm/stream和工具前后处理都是可被插件拦截的waterfall事件。插件可以调用next()委托给下游,也可以短路并返回自己的决策。因此,压缩策略、请求重写、权限检查和遥测不需要修改Agent Loop源码。

4.2 事件域与持久化策略

事件域

是否持久化

用途

turn/*、step/*

重建任务与步骤边界

user/message、assistant/*

恢复模型可见对话与流式输出

tool/call、tool/result

重放工具轨迹、校验调用结果配对

agent/*

否(实时)

inbox、状态、中途引导、重试和续跑

fs/*、tools/*等能力事件

按事件定义

把策略挂在能力边界上

事件源比每轮把整个会话JSON覆盖一次复杂,但它解决了Agent长程运行中最难的可观测性问题:界面上看到的输出、模型实际收到的上下文与磁盘上恢复的状态,理论上来自同一份事实。Resume、fork、search和replay都操作在同一条事件流上。

4.3 上下文压缩:原始事实不变,可见投影可变

长任务终将碰到上下文窗口。dsh-compaction-basic不直接改写旧日志,而是记录compaction/start、摘要、被遮蔽范围和compaction/end,再用一条新的user/message替换模型可见表层的某一段。完整历史仍然可用于审计,模型则看到压缩后的表层。

压缩维度

传统做法

dsh做法

工程优势

历史保存

覆盖旧messages

仅追加compaction事件

原始事实可审计

模型可见

裁剪后的列表

压缩后的表层投影

上下文窗口可控

恢复方式

从最终状态重启

从事件流任意点fork

支持分支探索

工具结果

直接截断

可选剪枝过大结果

减少信息损失

五、工具安全流水线:从tool/call到tool/result

5.1 六层工具执行流水线

模型生成一个tool call后,DeepSeek Harness不会立即调用工具函数。一次调用会通过前置策略、单调守卫、审批、执行包装、后置重写和结果归一化,最后才作为唯一模型可见结果写入会话。

tool/call 已记录

     ↓

tools/pre-execute

  ├─ deny    → 跳过工具主体

  ├─ ask     → 一次性用户审批

  └─ allow

     ↓

单调守卫:只能加严,不能绕过既有拒绝

     ↓

tools/execute:超时、重试、指标 → 工具主体

     ↓

tools/post-execute:接受、屏蔽、替换或附加上下文

     ↓

结果序列化与不变式检查

     ↓

tool/result 已记录

单调守卫是一个关键设计:多个策略叠加时,后加的插件不应把前面的拒绝重新改成允许。否则,一个设置顺序就可能把安全策略变成偶然行为。

5.2 安全层对比矩阵

安全层

解决的问题

仍需注意的风险

Tool Schema

参数类型与结果格式

Schema正确不等于操作安全

Approval

高风险动作是否经人确认

频繁弹窗会造成审批疲劳

Guard(单调守卫)

组织策略与终态拒绝

需测试插件组合后的实际行为

Sandbox

限制进程对文件和系统的影响

平台后端的强制能力并不完全相同

Event Log

追踪模型说了什么、调了什么

可追责不等于事前防护

Result Normalization

防止异常输出污染上下文

归一化规则需与业务对齐

5.3 沙箱失败即关闭原则

Harness的沙箱层把策略和后端分开。策略描述工作区边界和执行模式,后端则把命令包装为具体平台的受限进程。对于声明为受限的执行,如果没有可用后端,系统必须报SANDBOX_UNAVAILABLE,不允许静默退化为无沙箱运行。这是安全设计中的失败安全原则。

六、多Agent编排:Skills、Subagent与Workflow

6.1 Skills:按需加载的过程知识

dsh支持从项目级.dsh/skills、.agents/skills、用户目录、自定义目录和绑定资源中发现Skill。模型初始只看到名称和描述,需要时再读取完整SKILL.md,避免把所有操作手册一次性塞进上下文。项目级Skill可覆盖用户级同名Skill,每个候选项都记录来源和Provider,目录变化会使缓存失效。

Skill特征

工程价值

对比传统Prompt

按需加载

初始只暴露名称和描述

避免上下文膨胀

分层覆盖

项目级覆盖用户级同名Skill

支持环境差异化

来源追踪

每个候选项记录Provider

可审计、可回溯

缓存失效

目录变化自动刷新

保证Skill时效性

6.2 Subagent:多种后端的子代理运行时

ctx.subagents后面可同时注册多种Provider。官方代码包已包含进程内spawn、继承父历史的fork、ACP、Codex、Claude Code和dsh SDK等后端。这意味着协调者可以把任务交给另一个dsh Agent,也可以把Codex或Claude Code当作外部子代理。

子代理能力

工程价值

一次性子代理

把边界清晰的研究、实现或审查任务独立执行

可继续子代理

保留子会话ID,可多轮追加消息或冷恢复

Persona与Tool Filter

限定子代理角色与可见工具,减少误用

结构化输出

让上层编排获取稳定JSON,而非从自然语言中猜测

直接父级授权

followup、interrupt和report围绕持久化谱系校验

6.3 Workflow:模型生成的受限编排程序

Workflow seam允许模型生成JavaScript编排脚本,再由Worker Thread中的VM执行。脚本可串行或并行启动子代理,上报阶段和进度,并返回纯JSON结果。引擎可限制总子代理数,取消后会在有界宽限期内终止脚本并等待child清理。核心不是让模型随便写段JS,而是把复杂编排从一连串自然语言tool call转换为可表达并行、管道和错误处理的程序。

6.4 MCP、ACP与LSP的边界划分

协议/能力

dsh中的位置

解决什么边界

MCP

接入外部工具与资源

扩大Agent能做什么

ACP

连接外部Agent运行时

可作为子代理传输

LSP

从编程语言服务器获取信息

定义、引用和诊断

Skill

按需加载任务方法

领域知识和规则

Plugin

改变Harness本身

服务、策略、工具或UI

七、Python实战:dsh会话日志解析与MCP工具服务

DeepSeek Harness的会话日志采用仅追加的JSONL格式,每个SessionEvent都是一条独立JSON记录。以下Python代码实现了dsh会话日志的解析、工具调用轨迹提取和Token消耗分析,可用于CI/CD流水线中的Agent行为审计。

7.1 dsh会话日志解析器

import json

from pathlib import Path

from collections import defaultdict

from dataclasses import dataclass, field

from typing import Optional

@dataclass

class ToolCallRecord:

    tool_name: str

    step_index: int

    turn_index: int

    duration_ms: Optional[float] = None

    success: bool = True

    input_summary: str = ""

    output_summary: str = ""

@dataclass

class SessionAnalysis:

    total_turns: int = 0

    total_steps: int = 0

    total_tool_calls: int = 0

    tool_calls: list = field(default_factory=list)

    compaction_events: int = 0

    error_count: int = 0

    token_usage: dict = field(default_factory=lambda: defaultdict(int))

class DSHSessionParser:

    """解析dsh仅追加会话日志(JSONL格式)的解析器"""

    EVENT_TYPES = {

        "turn/start": "turn", "turn/end": "turn",

        "step/start": "step", "step/end": "step",

        "tool/call": "tool", "tool/result": "tool",

        "compaction/start": "compaction", "compaction/end": "compaction",

        "assistant/message": "message",

        "user/message": "message",

    }

    def __init__(self, log_path: str):

        self.log_path = Path(log_path)

        self.events = self._load_events()

    def _load_events(self) -> list:

        events = []

        with open(self.log_path, "r", encoding="utf-8") as f:

            for line in f:

                line = line.strip()

                if line:

                    events.append(json.loads(line))

        return events

    def analyze(self) -> SessionAnalysis:

        analysis = SessionAnalysis()

        turn_idx = 0

        step_idx = 0

        pending_tool_calls = {}

        for event in self.events:

            etype = event.get("type", "")

            category = self.EVENT_TYPES.get(etype, "")

            if etype == "turn/start":

                turn_idx += 1

            elif etype == "step/start":

                step_idx += 1

            elif etype == "tool/call":

                tool_name = event.get("tool", "unknown")

                call_id = event.get("callId", str(len(pending_tool_calls)))

                pending_tool_calls[call_id] = ToolCallRecord(

                    tool_name=tool_name,

                    step_index=step_idx,

                    turn_index=turn_idx,

                    input_summary=str(event.get("input", ""))[:200],

                )

            elif etype == "tool/result":

                call_id = event.get("callId", "")

                record = pending_tool_calls.pop(call_id, None)

                if record:

                    record.output_summary = str(event.get("output", ""))[:200]

                    record.success = not event.get("error", False)

                    record.duration_ms = event.get("durationMs")

                    analysis.tool_calls.append(record)

            elif etype == "compaction/start":

                analysis.compaction_events += 1

            elif etype == "assistant/message":

                usage = event.get("usage", {})

                for key in ["prompt_tokens", "completion_tokens"]:

                    if key in usage:

                        analysis.token_usage[key] += usage[key]

        analysis.total_turns = turn_idx

        analysis.total_steps = step_idx

        analysis.total_tool_calls = len(analysis.tool_calls)

        analysis.error_count = sum(1 for tc in analysis.tool_calls if not tc.success)

        return analysis

    def generate_report(self, analysis: SessionAnalysis) -> str:

        lines = ["=" * 60, "DeepSeek Harness Session Analysis Report", "=" * 60]

        lines.append(f"Total Turns:      {analysis.total_turns}")

        lines.append(f"Total Steps:      {analysis.total_steps}")

        lines.append(f"Tool Calls:       {analysis.total_tool_calls}")

        lines.append(f"Failed Calls:     {analysis.error_count}")

        lines.append(f"Compaction Events: {analysis.compaction_events}")

        lines.append("")

        lines.append("Token Usage:")

        for key, val in analysis.token_usage.items():

            lines.append(f"  {key}: {val}")

        lines.append("")

        lines.append("Tool Call Trace:")

        for tc in analysis.tool_calls:

            status = "OK" if tc.success else "FAIL"

            lines.append(f"  [T{tc.turn_index}/S{tc.step_index}] {tc.tool_name} ({status})")

        return "\n".join(lines)

这段代码将dsh的JSONL会话日志解析为结构化的SessionAnalysis对象,支持工具调用轨迹追踪、Token消耗统计和压缩事件计数。在CI/CD流水线中,可用它生成Agent行为审计报告,定位失败的工具调用和异常的Token消耗模式。

7.2 Python MCP工具服务:为dsh扩展自定义工具

dsh通过MCP协议接入外部工具。以下Python代码实现了一个MCP工具服务,为dsh提供代码质量检查能力,展示了如何用Python为dsh扩展自定义工具集。

import asyncio

import json

import subprocess

from pathlib import Path

from typing import Any

class MCPToolServer:

    """为DeepSeek Harness提供MCP协议工具服务的Python实现"""

    TOOLS_SCHEMA = {

        "check_code_quality": {

            "description": "Run linter and type checker on a Python file",

            "parameters": {

                "type": "object",

                "properties": {

                    "file_path": {"type": "string", "description": "Path to Python file"},

                    "checks": {

                        "type": "array",

                        "items": {"type": "string", "enum": ["ruff", "mypy", "pylint"]},

                        "default": ["ruff", "mypy"],

                    },

                },

                "required": ["file_path"],

            },

        },

        "run_test_suite": {

            "description": "Execute pytest with coverage for a directory",

            "parameters": {

                "type": "object",

                "properties": {

                    "test_dir": {"type": "string", "description": "Test directory path"},

                    "coverage": {"type": "boolean", "default": True},

                    "parallel": {"type": "boolean", "default": False},

                },

                "required": ["test_dir"],

            },

        },

        "analyze_dependencies": {

            "description": "Parse import statements and build dependency graph",

            "parameters": {

                "type": "object",

                "properties": {

                    "root_dir": {"type": "string", "description": "Project root directory"},

                },

                "required": ["root_dir"],

            },

        },

    }

    async def handle_tool_call(self, tool_name: str, args: dict) -> dict:

        if tool_name == "check_code_quality":

            return await self._check_quality(args)

        elif tool_name == "run_test_suite":

            return await self._run_tests(args)

        elif tool_name == "analyze_dependencies":

            return await self._analyze_deps(args)

        return {"error": f"Unknown tool: {tool_name}"}

    async def _check_quality(self, args: dict) -> dict:

        file_path = Path(args["file_path"])

        checks = args.get("checks", ["ruff", "mypy"])

        results = {}

        for checker in checks:

            cmd = self._build_checker_cmd(checker, file_path)

            proc = await asyncio.create_subprocess_exec(

                *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE

            )

            stdout, stderr = await proc.communicate()

            results[checker] = {

                "exit_code": proc.returncode,

                "output": stdout.decode()[:2000],

                "errors": stderr.decode()[:2000] if stderr else "",

            }

        return {"file": str(file_path), "results": results}

    async def _run_tests(self, args: dict) -> dict:

        test_dir = args["test_dir"]

        cmd = ["python", "-m", "pytest", test_dir]

        if args.get("coverage"):

            cmd.extend(["--cov", "--cov-report=term-missing"])

        if args.get("parallel"):

            cmd.append("-n", )

        proc = await asyncio.create_subprocess_exec(

            *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE

        )

        stdout, stderr = await proc.communicate()

        return {

            "exit_code": proc.returncode,

            "summary": stdout.decode()[-1000:],

            "errors": stderr.decode()[:1000] if stderr else "",

        }

    async def _analyze_deps(self, args: dict) -> dict:

        root = Path(args["root_dir"])

        graph = {}

        for py_file in root.rglob("*.py"):

            imports = self._extract_imports(py_file)

            if imports:

                graph[str(py_file.relative_to(root))] = imports

        return {"dependency_graph": graph, "total_files": len(graph)}

    def _build_checker_cmd(self, checker: str, file_path: Path) -> list:

        commands = {

            "ruff": ["ruff", "check", str(file_path)],

            "mypy": ["mypy", str(file_path)],

            "pylint": ["pylint", str(file_path)],

        }

        return commands.get(checker, [])

    def _extract_imports(self, file_path: Path) -> list:

        imports = []

        with open(file_path, "r", encoding="utf-8") as f:

            for line in f:

                line = line.strip()

                if line.startswith("import ") or line.startswith("from "):

                    imports.append(line)

        return imports

if __name__ == "__main__":

    server = MCPToolServer()

    print("MCP Tool Server ready for dsh integration")

    print(f"Available tools: {list(server.TOOLS_SCHEMA.keys())}")

这个MCP工具服务实现了代码质量检查、测试套件执行和依赖分析三个工具。dsh通过MCP协议接入后,模型可以在Agent Loop中直接调用这些工具,实现编码质量门禁的自动化。关键设计是将工具的执行逻辑与Schema声明分离,便于在dsh的tools/pre-execute和tools/post-execute流水线中插入安全策略。

八、横向对比矩阵:dsh vs Claude Code vs Codex vs OpenCode

8.1 架构维度对比

对比维度

DeepSeek Harness (dsh)

Claude Code

Codex CLI

OpenCode

开源许可

MIT

 proprietary

MIT

Apache 2.0

架构哲学

一切皆插件

一体化设计

工具链集成

模块化设计

微内核

Cordis

插件体系

全能力可替换

MCP工具扩展

配置扩展

插件系统

会话模型

事件源(append-only)

消息列表

消息列表

消息列表

上下文压缩

不改原始日志

截断历史

截断历史

摘要替换

沙箱策略

失败即关闭

内置限制

Docker隔离

进程限制

子代理

多后端(dsh/Codex/Claude)

不支持

不支持

有限支持

模型绑定

不绑定(多provider)

绑定Anthropic

绑定OpenAI

多provider

语言构成

TypeScript 97.1%

TypeScript

Rust

Go

8.2 能力维度对比

能力维度

dsh

Claude Code

Codex

OpenCode

运行模式数

4种(Standard/Code/Minimal/Creator)

1种

1种

2种

Workflow编排

模型生成JS脚本

Skills按需加载

支持(分层覆盖)

有限

会话回放

事件流fork/replay

凭据管理

脱敏存储+引用

环境变量

环境变量

配置文件

遥测集成

OTel原生

有限

Profile系统

Profile+Bundle+Patch

MCP支持

原生

支持

支持

ACP支持

原生

LSP集成

原生

8.3 差异化定位分析

维度

dsh真正的差异点

工程含义

插件化深度

连Agent Loop和会话日志都是插件

扩展不需要修改源码

事件源会话

模型可见即已记录

可审计、可回放、可分支

单调守卫

安全策略只能加严不能放松

防止插件组合导致安全降级

多后端子代理

可调度Codex和Claude Code作为子代理

跨框架编排能力

Profile组合

同一核心可组装为不同产品

一套代码多种部署形态

九、企业落地路径与风险边界

9.1 企业采纳的四个阶段

阶段

目标

关键动作

风险控制

评估期

理解dsh架构与能力边界

Minimal模式跑基准测试

隔离环境运行

试点期

在非核心项目中验证

Standard模式+自定义Skill

审批策略全开

集成期

接入企业工具链

开发MCP工具服务+Profile配置

供应链审查

生产期

规模化部署与监控

OTel遥测+事件流审计

沙箱强制+凭据隔离

9.2 风险矩阵

风险类别

具体风险

缓解策略

供应链风险

第三方插件可能位于凭据和命令的关键路径上

固定版本、保留物料清单、审查权限声明

兼容性风险

开发者预览阶段有破坏性变更

锁定rc版本,建立升级回归测试

安全配置风险

插件组合可能导致安全策略被绕过

测试单调守卫行为,审计tools/pre-execute链

沙箱逃逸风险

平台后端强制能力不完全相同

生产环境强制SANDBOX_UNAVAILABLE失败即关闭

上下文管理风险

压缩策略可能丢失关键信息

审计compaction事件,验证模型可见投影

9.3 生产化部署建议

  • 凭据边界:DSH_HOME目录权限限制为600,.credentials.yaml加密存储,设置层只保留引用
  • 沙箱策略:生产环境声明所有执行为受限模式,配置landlock或Docker后端,禁止SANDBOX_UNAVAILABLE静默降级
  • 遥测接入:启用OTel导出,将turn/step/tool事件流接入企业可观测性平台
  • 插件供应链:建立插件物料清单(CBOM),版本固定+签名验证+定期安全扫描
  • Profile管理:使用cordis.patch.yml管理企业策略,不修改dsh-base源码
  • 会话审计:定期分析JSONL会话日志,使用解析器提取工具调用轨迹和Token消耗模式

十、总结

维度

核心要点

产品定位

dsh是开源Agent运行时,不是API封装或编程客户端

架构核心

Cordis将Agent Loop、Session、Tool、模型适配器和UI组装为可替换插件树

状态模型

仅追加事件日志作为会话真相来源,压缩改变可见投影而不删除原始事实

安全路径

工具调用经过审批、单调守卫、沙箱、前后置策略和结果归一化

多Agent编排

Skills按需加载、Subagent多后端、Workflow模型生成JS编排

模型无关

不绑定DeepSeek,支持OpenAI/Anthropic/自定义兼容端点

四种模式

Standard/Code/Minimal/Creator覆盖全场景

生态阶段

MIT许可证开发者预览,12,940次提交,25位贡献者活跃迭代

DeepSeek Harness的真正赌注不是做一个更好的Claude Code,而是开放模型之外的实验室。当模型、工具、沙箱、会话日志和Agent Loop都可以被替换和重组时,DeepSeek把Agent工程的核心矛盾——能力上限由模型决定,但能力下限由运行时决定——摆在了台面上。对于企业AI团队来说,dsh值得在评估期认真对待:即使不在生产中使用它,它的架构设计也为自建Agent运行时提供了高价值的参考框架。

紫宸策 | GEO咨询与企业AI落地实践

公众号:紫宸策

AI 时代程序员必备技能

Codex、Claude Code、Cursor、Hermes Agent、OpenClaw等工程化实战专栏 ,讲透 AI 如何接管脏活累活

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值