从零实现 DeepSeek Harness:Python 工具链与 VS Code 接入实战

发布时间:2026/9/8 11:48:43
从零实现 DeepSeek Harness:Python 工具链与 VS Code 接入实战 在 AI 开发工具链里DeepSeek Harness 插件这个组合词被搜索的频率越来越高。有人想把它装进 VS Code有人想找一个桌面端还有人以为它是某种能自动完成任务的 Agent。搜索不到完整资料时很容易在安装环节卡住。这篇文章会换一个思路不依赖某个不确定维护状态的现成插件而是把 DeepSeek Harness 拆成可以自己实现的工程能力。Harness 的英文本意是“背带、挽具”在机器学习工程里它通常指一层承上启下的运行框架向下统一调用模型接口向上提供工具注册、上下文管理、结果回传等能力。所谓 DeepSeek Harness 插件可以理解成“把 DeepSeek 模型接进自己工具链的一层框架”。这篇文章会从零写一个最小可用的 Python Harness支持统一 API 调用、工具函数注册、CLI 交互再把它接入 VS Code。整个过程就像一次空城计用单个脚本模拟出完整插件平台的核心结构等确实需要重型功能时再逐步扩展。1. 先理解 DeepSeek Harness 是什么为什么很多人都在安装它1.1 Harness 的通俗含义和技术定义Harness 的英文原意是“挽具、背带”用于把牲畜套在车或犁上。迁移到软件工程后Harness 变成了“把多个部件组合起来运行的控制框架”。在 LLM 应用里Harness 更直观的理解是模型本身只负责文字生成真正让它能干活的是外层挂上的一堆工具、提示词、上下文管理逻辑以及调用这些逻辑的统一入口。技术定义上Harness 是一层承上启下的中间层。它的下层是模型 API上层是用户界面或业务系统。它负责处理几个重复性很高的问题API Key 怎么读取、请求参数怎么构造、工具函数如何暴露给模型、模型输出如何解析、错误如何重试。没有这层封装时每个脚本都要重复写一遍网络请求有了这层封装后业务代码只需要描述“我想让模型做什么”不需要关心底层 HTTP 细节。在很多英文资料里Harness Engineering 被用来指一类为模型搭建执行环境的工程实践。它和评估工具中的 Evaluation Harness 不完全是一回事。评估 Harness 侧重批量跑数据集、计算指标工程 Harness 侧重线上应用中的调用、工具编排和异常处理。本文讨论的是后者。1.2 DeepSeek Harness 插件解决哪几类问题DeepSeek 模型本身以 API 形式提供服务。如果只是测试对话直接 curl 一下就行。但一旦进入真实工具链“DeepSeek Harness 插件”这类需求通常是为了解决以下问题。第一统一 API 调用。多个脚本要共用同一个模型地址、Key 和超时策略不该每处都重复写 requests 请求。第二给模型开放外部工具。让模型可以读取文件、执行命令、查询天气、操作数据库而不是只能基于训练知识回答问题。Harness 在这一层负责工具注册和调用结果回传。第三把模型接进开发环境。VS Code 插件、命令行工具、桌面端本质都是同一个 API 的前端。Harness 通过提供稳定入口让不同前端都能调用同一套能力。第四管理上下文和成本。对话轮数变多后Harness 需要决定哪些历史消息保留哪些截断避免 token 消耗失控。如果你在搜索“deepseek harness 安装”多数情况是想快速跑通一个能用的入口。安装本身并不难难的是装完后不知道它内部怎么工作遇到问题没法排查。所以这篇文章选择从实现角度切入而不是推荐一个安装包。1.3 Harness、Agent、普通插件有什么区别这三个词经常被混用实际上边界很清楚。普通插件是宿主应用的一个扩展点。VS Code 插件、浏览器插件都是在宿主环境提供的入口里增加功能。插件本身不关心模型调度它只是在 UI 上把代码或文本发给后端。Harness 是模型运行的外层框架。它关心请求怎么构造、工具怎么注册、响应怎么解析。插件通常是 Harness 的前端表现。Agent 则更进一步它有“自主规划”能力。Agent 拿到目标后会拆解步骤逐步调用模型和工具根据中间结果调整下一步操作。一个 Agent 内部往往内置了一个 Harness但 Harness 不一定具备 Agent 的规划能力。表格对比会更直观。术语核心特征典型使用场景容易混淆点插件给宿主应用增加功能入口VS Code 中通过按钮触发 DeepSeek 调用只是前端入口不是 Harness 本体Harness统一管理模型调用、工具注册和上下文脚本或平台中稳定调度模型能力与“插件”混用实际上 Harness 是框架层Agent自主规划、拆解任务、循环调用工具给模型一个目标让它自己决定调用哪些函数不是所有 Harness 都有 Agent 的自主规划依赖这个表搜索时就能判断资料质量如果一个“Harness 插件”只能发请求没有工具调用能力那它更像一个 API 客户端而不是完整 Harness。1.4 用“空城计”理解最小 Harness 的定位“空城计”在这里是一个工程策略隐喻。很多时候我们并不需要一开始就搭建一个庞大的平台。面对模糊需求时可以用一个小而完整的脚本把核心链路跑通。最小 Harness 就是这样的空城计一个 Python 文件几百行代码却具备完整 Harness 的核心结构。看起来像一套系统实际上只是一小段逻辑。等业务增长后再把它替换成更重的组件。这种做法的好处是每个环节都在自己控制范围里出了问题能快速定位不需要去读别人插件的源码。注意如果只是临时体验单文件脚本足够。如果打算长期维护或多人协作还是尽早拆模块化。2. 环境准备API、依赖、目录结构一次对齐2.1 接入 DeepSeek API 前需要确认的四个信息很多失败案例不是代码写错而是前置信息没确认。至少需要确认四样东西API Key、Base URL、模型名称、上下文长度。API Key 需要在 DeepSeek 开放平台后台创建。创建后通常只完整显示一次如果丢失只能重新生成。Base URL 一般指向https://api.deepseek.com具体路径要参考当前官方文档因为不同版本可能使用/chat/completions或/v1/chat/completions等不同路径。模型名称常见的有deepseek-chat、deepseek-reasoner等不同阶段可能有调整不能凭记忆写死。上下文长度决定单次请求能传多少 token。超出限制时请求可能报错或内容被截断。低成本测试时建议先使用短文本确认链路通了再放大上下文。检查项常见配置出错表现API Key后台生成妥善保存401 UnauthorizedBase URL按官方文档配置不随意加/v1404、连接超时Model使用官方文档中的模型标识400 model not found上下文长度确认模型最大值长文本截断或请求失败2.2 学习环境的依赖配置最小依赖只需要 Python 3.10 以上和requests。如果习惯用 OpenAI SDK 也可以但为了看清内部流程建议先从 HTTP 请求开始。创建虚拟环境并安装依赖mkdir deepseek-harness cd deepseek-harness python -m venv venv source venv/bin/activate # Windows 执行 venv\Scripts\activate pip install requests python-dotenvpython-dotenv用于读取.env文件避免在代码里硬编码 Key。学习环境里这两个包足够。2.3 项目目录结构从单文件起步按模块扩展建议初始目录如下deepseek-harness/ harness/ __init__.py core.py tools.py config.py scripts/ cli.py .env .gitignore requirements.txt README.mdharness/core.py放模型调用入口harness/tools.py放工具注册器harness/config.py放配置读取scripts/cli.py放命令行交互界面。如果只是快速验证也可以先只写一个main.py把上述逻辑都放进去。但后续加工具、加日志时还是按模块拆分更舒服。需要在.gitignore中排除.env。.env venv/ __pycache__/ *.pyc .DS_Store空城计策略的关键是目录结构先做出来但每层代码保持最小不需要一开始就实现太多抽象类。3. 用 Python 实现一个最小 Harness模型调用、工具注册和插件扩展3.1 配置管理API Key 不进代码先创建.env文件DEEPSEEK_API_KEYsk-xxx DEEPSEEK_BASE_URLhttps://api.deepseek.com DEEPSEEK_MODELdeepseek-chat再实现harness/config.pyimport os from dotenv import load_dotenv load_dotenv() class HarnessConfig: def __init__(self): self.api_key os.getenv(DEEPSEEK_API_KEY, ).strip() self.base_url os.getenv(DEEPSEEK_BASE_URL, https://api.deepseek.com).strip() self.model os.getenv(DEEPSEEK_MODEL, deepseek-chat).strip() self.timeout int(os.getenv(DEEPSEEK_TIMEOUT, 60)) self.max_tokens int(os.getenv(DEEPSEEK_MAX_TOKENS, 1024)) def validate(self): if not self.api_key: raise ValueError(DEEPSEEK_API_KEY 未配置请在 .env 或环境变量中配置)注意strip()处理 Key 前后不小心复制进来的空格。这是最常见的低级错误却会导致 401。3.2 统一模型调用入口harness/core.py实现一个最简客户端import requests class DeepSeekClient: def __init__(self, config): self.config config def chat(self, messages, toolsNone, temperature0.7, max_tokensNone, streamFalse): if not self.config.api_key: raise ValueError(DEEPSEEK_API_KEY 未配置) url self.config.base_url.rstrip(/) /chat/completions headers { Authorization: fBearer {self.config.api_key}, Content-Type: application/json, } payload { model: self.config.model, messages: messages, temperature: temperature, max_tokens: max_tokens or self.config.max_tokens, stream: stream, } if tools: payload[tools] tools resp requests.post(url, headersheaders, jsonpayload, timeoutself.config.timeout) if resp.status_code ! 200: raise RuntimeError( fDeepSeek API error: status{resp.status_code}, body{resp.text} ) return resp.json()这里把模型调用收敛成一个chat方法。业务代码只需要传messages和可选的tools不需要关心 URL、Headers、超时。后续要加日志、重试、缓存也只需要改这一个文件。如果要用 OpenAI SDK只需要替换成一个OpenAI客户端from openai import OpenAI client OpenAI( api_keyconfig.api_key, base_urlconfig.base_url, )注意是否兼容 OpenAI SDK以你拿到的服务端实现为准。DeepSeek 开放平台的设计通常兼容 OpenAI 风格但不同阶段可能有差异落地前先看文档。3.3 工具注册表让模型能“调用插件”Harness 区别于普通 API Demo 的核心是工具注册机制。在harness/tools.py中实现一个简单注册表TOOL_REGISTRY {} def register_tool(name, description, parameters): def decorator(func): TOOL_REGISTRY[name] { func: func, description: description, parameters: parameters, } return func return decorator def get_tools_for_api(): tools [] for name, item in TOOL_REGISTRY.items(): tools.append({ type: function, function: { name: name, description: item[description], parameters: item[parameters], }, }) return tools def call_tool(name, arguments): if name not in TOOL_REGISTRY: return funknown tool: {name} try: return TOOL_REGISTRY[name][func](**arguments) except Exception as e: return ftool {name} error: {str(e)}注册两个最小工具import datetime register_tool( nameget_current_time, description获取当前系统时间。, parameters{ type: object, properties: {}, }, ) def get_current_time(): return datetime.datetime.now().isoformat() register_tool( nameread_file, description读取文本文件内容路径必须是绝对路径。, parameters{ type: object, properties: { path: {type: string, description: 文件绝对路径} }, required: [path], }, ) def read_file(path: str): try: with open(path, r, encodingutf-8) as f: return f.read()[:2000] except Exception as e: return fread file error: {e}这个注册表就是“插件”的雏形。每增加一个工具只需要register_tool注册一个函数再写清描述和参数。模型通过描述知道什么时候该调用工具Harness 通过注册表找到具体函数并执行。3.4 工具调用循环Harness 和普通 API Demo 的分水岭普通对话是“模型生成 - 返回”。加了工具后变成了循环用户消息放入messages。Harness 把messages和工具描述发给模型。如果模型返回tool_callsHarness 解析调用名和参数。Harness 执行本地工具把结果作为新消息追加到messages。Harness 再次请求模型让模型基于工具结果生成最终回答。这个循环可以重复多次直到模型不再请求工具。在core.py中增加一个运行循环class HarnessRunner: def __init__(self, client): self.client client self.messages [] self.max_iterations 5 def run(self, user_message: str) - str: self.messages.append({role: user, content: user_message}) for _ in range(self.max_iterations): response self.client.chat(self.messages, toolsget_tools_for_api()) choice response[choices][0] message choice[message] self.messages.append(message) tool_calls message.get(tool_calls) if not tool_calls: return message.get(content, ) for call in tool_calls: func_name call[function][name] args_text call[function][arguments] import json try: args json.loads(args_text) if args_text else {} except json.JSONDecodeError: args {} result call_tool(func_name, args) self.messages.append({ role: tool, tool_call_id: call[id], content: str(result), }) return 达到最大工具调用轮数停止执行这段代码最容易出错的地方是messages的组装。OpenAI 兼容格式要求模型返回的message要原样追加到messages然后再追加每个tool角色的结果。漏掉message.content或tool_call_id都可能让服务端报错。注意工具调用循环必须设置最大轮数。业务上如果工具步骤有误模型可能会一直重试最终浪费 token。把max_iterations控制在 5 以内会比较合理。3.5 最小 CLI跑起来才算完成scripts/cli.pyimport sys from harness.config import HarnessConfig from harness.core import DeepSeekClient, HarnessRunner def main(): config HarnessConfig() config.validate() client DeepSeekClient(config) runner HarnessRunner(client) print(DeepSeek Harness 已启动输入 exit 或 quit 退出。) while True: try: user_input input( ) except (EOFError, KeyboardInterrupt): print() break if user_input.lower() in {exit, quit}: break if not user_input.strip(): continue answer runner.run(user_input) print(answer) if __name__ __main__: sys.exit(main())这个 CLI 就是 Harness 的“插件前端”。虽然它没有图形界面但已经具备完整链路。后续做 VS Code 插件、Web 界面都可以复用它调用的HarnessRunner。4. 把 Harness 接进 VS Code 和命令行4.1 VS Code 自定义任务接入很多搜索“vscode 接入 deepseek”的读者最终只是想在一段 Markdown 或代码里把内容发给模型。在没有安装第三方插件的情况下可以直接用 VS Code 的任务机制跑上面的 CLI。在项目根目录.vscode/tasks.json增加{ version: 2.0.0, tasks: [ { label: DeepSeek Harness, type: shell, command: python ${workspaceFolder}/scripts/cli.py, presentation: { reveal: always, panel: dedicated, focus: true } } ] }之后按CtrlShiftP运行 Tasks选择DeepSeek Harness就会在集成终端里打开一个可交互的模型入口。这个方案避免了安装未知来源的插件适合公司网络或安全要求较高的环境。也可以注册一个按键绑定运行后直接把当前选中文本复制到剪贴板再粘贴进 CLI。更复杂的使用方式可以后续自己实现。4.2 命令行 Agent 工具接入兼容 API 的场景网上搜索“codex 接入 deepseek”、“codex harness”时会看到一些人通过配置OPENAI_BASE_URL和OPENAI_API_KEY来让 OpenAI 风格的命令行工具指向 DeepSeek。这种做法的前提是目标工具支持自定义base_url。匹配时要注意以下几点确认命令行工具是否允许配置base_url以及配置文件位置。确认目标模型是否支持该工具内部使用的功能例如 function calling、JSON mode 或视觉输入。确认工具的鉴权方式是否与服务端兼容。升级工具版本后要重新验证不要假设配置长期有效。不建议通过修改第三方 SDK 内部代码的方式强行接入。升级 SDK 后改动会被覆盖维护成本很高。最稳妥的方式是把上面第 3 节实现的 Harness 封装成一个小型 HTTP 服务然后让命令行工具的base_url指向自己写的服务由这个服务负责转发到 DeepSeek。这样虽然多了一层但可控性更强。4.3 桌面端和 Web 端都是外表核心还是 API热搜词里经常出现“deepseek harness 桌面端”。桌面端本质上是一个用 Electron、Tauri 或 Qt 包装的聊天界面。它调用的还是 DeepSeek API。没有可靠桌面端时自己用 Flask 或 FastAPI 暴露一个接口再用网页打开就能达到类似效果。一个最小 Web 后端只需要把HarnessRunner封装成 HTTP 接口from flask import Flask, request, jsonify from harness.config import HarnessConfig from harness.core import DeepSeekClient, HarnessRunner app Flask(__name__) config HarnessConfig() runner HarnessRunner(DeepSeekClient(config)) app.post(/chat) def chat(): data request.get_json() user_message data.get(message, ) answer runner.run(user_message) return jsonify({answer: answer})用flask run启动后浏览器页面或其他插件就能通过/chat接口调用同一个 Harness。这样一来VS Code 插件、浏览器插件和桌面端都只是外壳核心能力仍然在 Harness 层。5. 运行验证和结果分析5.1 第一步验证普通对话启动 CLIpython scripts/cli.py输入“你好请用一句话介绍自己”。正常输出类似DeepSeek Harness 已启动输入 exit 或 quit 退出。 你好请用一句话介绍自己 你好我是一个基于 DeepSeek 模型的智能助手。这里验证的是最基础链路API Key 有效、Base URL 正确、模型名称正确、请求能正常返回。5.2 第二步验证工具调用输入“现在北京时间几点”。如果模型识别到需要调用get_current_timeHarness 会执行工具然后基于工具结果生成回答。预期输出会包含一个具体时间而不是模型自己编造的时间。这个验证很关键。如果模型回答的是一个编造时间说明工具调用没有发生或者工具调用结果没有正确回填到messages。需要检查工具描述的格式和call_tool的解析逻辑。如果模型没有返回tool_calls而是直接给出一个猜测时间可以在工具描述里强调“这是获取当前时间的唯一来源”或者降低temperature让模型更倾向于调用工具。5.3 第三步观察 token 消耗在DeepSeekClient.chat里打印响应中的 usage 字段if usage in resp_data: usage resp_data[usage] print(f[usage] prompt_tokens{usage.get(prompt_tokens)} fcompletion_tokens{usage.get(completion_tokens)} ftotal_tokens{usage.get(total_tokens)})通过 token 消耗可以判断一个普通问题消耗了多少输入 token。工具调用会让请求变成多次总 token 会不会成倍增长。是否需要在长对话中做历史截断。是否因为上下文增长导致成本超出预期。实际项目中建议把 usage 写入结构化日志方便按用户、按时段统计成本。5.4 第四步验证异常分支至少要验证三类异常配置错误故意在.env中写错 API Key观察是否返回 401。网络异常断网后运行观察是否报连接超时。模型不存在把DEEPSEEK_MODEL改成不存在的模型观察是否返回 400。每类异常都要有明确提示不能只是 Python 堆栈。可以在chat方法里统一抛RuntimeError在 CLI 外层捕获并显示友好提示try: answer runner.run(user_input) except Exception as e: print(f请求失败: {e})6. 常见问题排查链路6.1 连接超时、404 或网络不可达现象可能原因检查方式处理建议连接超时Base URL 错误、网络不可达、DNS 解析失败curl -v https://api.deepseek.com核对官方文档地址检查网络连通性404URL 路径拼接错误打印最终请求 URL查看是否多拼了/v1或漏了路径SSL 证书错误本地证书环境异常临时关闭验证定位问题不使用verifyFalse应修复证书环境排查顺序先确认 URL 本身能访问再确认代码里的拼接结果和它一致。不要上来就改超时时间。6.2 401 Unauthorized现象可能原因检查方式处理建议401API Key 无效后台重新生成 Key确认 Key 未过期、未泄露401Key 前后有空格打印config.api_key长度使用strip()401请求头格式错误抓包或打印 headers确认Bearer后有空格排查时不要只检查.env还要看代码实际读取到的值。环境变量里的同名变量会覆盖.env中的配置这很容易被忽略。6.3 400 model not found 或参数错误现象可能原因检查方式处理建议400 model not found模型名称写错对比官方文档中的 model 字段使用当前文档中的模型标识400 max_tokens 超限参数超出模型允许范围查看错误信息中的限制按上下文限制设置400 tools 格式错误工具参数不符合 schema打印 payload 中的 tools参考 OpenAI function calling 格式这一类问题通常在请求失败时的 response body 里有具体原因。不要只看状态码要把resp.text完整打印出来。6.4 工具调用结果异常模型返回了tool_calls但代码报错或回答不对常见情况有arguments不是合法 JSON。模型偶尔会生成多余字符解析失败时不能直接崩溃要捕获JSONDecodeError。工具参数类型不匹配。例如read_file要求path是字符串但模型传了数组。call_tool里需要做类型校验或把异常变成可读信息。tool_call_id缺失或不对。OpenAI 兼容格式要求 tool 消息必须关联tool_call_id否则服务端可能拒绝。工具调用轮数限制触发。模型在连续调用工具时如果没有收敛最终会达到max_iterations。解决方式是给工具调用循环增加完整日志在每轮打印本轮是模型文本、工具调用名、工具参数、工具结果这样能快速定位是哪一步断了。6.5 环境配置能读程序却提示未配置现象可能原因处理建议提示未配置但.env有内容.env不在当前工作目录使用绝对路径加载.env或确认启动目录环境变量也有值但没生效Shell 缓存重启终端或unset DEEPSEEK_API_KEY后重新加载多人协作时 Key 混乱.env被提交到了 Git加入.gitignore并轮换已泄露 Key排查时先打印os.getenv(DEEPSEEK_API_KEY)确认代码真正读取到的是什么。7. 成本、安全与生产化建议7.1 API Key 安全清单不要把 Key 硬编码在代码里也不要提交到 Git。每次代码仓库扫描都应检查.env是否被误提交。不要把 Key 放在前端代码、浏览器插件源码或桌面端本地配置里。前端暴露的 Key 等于公开。用环境变量、密钥管理服务或者工厂内部的配置中心保存 Key。为 Key 设置消费上限或额度提醒避免异常调用导致费用失控。一旦发现 Key 泄露立即在平台后台轮换不能只删仓库文件。7.2 成本控制三件事第一限制单次请求的max_tokens。模型回答越长费用越高。如果业务只需要短结论设成 512 或 1024 即可。第二控制上下文长度。工具调用会让每轮请求都带上全部历史消息和工具结果。长时间运行后历史会变得非常大。可以用滑动窗口只保留最近 N 轮或者做一次摘要压缩再继续。第三使用降级策略。DeepSeek 服务不可用时可以降级到本地小模型或返回缓存结果而不是无限重试。重试时要使用指数退避并加上最大重试次数。成本手段学习环境生产环境上下文不限制滑动窗口或摘要压缩超时重试无指数退避 熔断日志print结构化日志 usage 统计降级直接报错缓存或备用模型7.3 从学习 Demo 到生产 Harness 的差距模块学习环境生产环境配置.env配置中心或密钥管理服务日志控制台打印JSON 日志、Trace ID、集中采集工具权限本地随意调用沙箱、白名单、权限校验监控无请求数、延迟、错误率、token 消耗回滚重启脚本版本化部署 灰度切换特别要注意工具权限。示例中的read_file可以读取任意文件这在本地演示没问题但暴露到生产环境就是严重风险。真实场景里文件工具只能访问指定目录命令执行工具必须经过白名单和审计。7.4 合理使用与合规边界在使用 DeepSeek 或任何模型服务时要遵守服务提供方的使用条款和当地法律法规。不要在 Harness 中加入任何尝试绕过来使用限制、突破内容边界或窃取未授权数据的功能。工具执行层也要做权限校验和审计不能因为模型输出“想访问某个路径”就直接执行。8. 扩展方向把“空城计”变成真 Harness8.1 从单文件到插件化加载当前工具注册表是显式导入的。工具多了以后可以用importlib自动扫描tools/目录下的 Python 文件实现类似插件的加载机制。每个文件定义一个register()函数放在固定目录中即可生效。这样新工具不需要改主流程代码只需要新增文件。不过自动加载也带来风险任何人往目录里放一个 Python 文件就可能执行任意代码。生产环境必须对插件加载目录做严格权限控制不能静默加载未知来源插件。也可以使用 YAML/JSON 配置描述工具参数配合一个通用 executor 动态执行。这种方式更适合允许用户自己定义工具的 Harness。8.2 在 Harness 之上叠加 Agent 规划能力Harness 解决了“调用模型 调用工具”的问题Agent 进一步解决“拆解任务”的问题。如果想要一个 Agent可以在 Harness 之上加入规划循环模型先生成一段计划再按计划调用工具每一步观察结果后修正下一步。这个循环和第 3.4 节的工具循环类似但需要更详细的状态管理和中断机制。建议不要一开始就上重型 Agent 框架。先把 Harness 的稳定性做好再逐步加入目标规划、子任务拆分和反馈复盘。8.3 一份可执行的学习路径如果读者想从这篇文章继续深入可以参考下面顺序读懂 DeepSeek API 文档中的messages结构动手构造一次 HTTP 请求。实践 function calling把工具从 2 个扩展到 5 个以上。给 Harness 增加日志、token 统计和异常恢复能力。把它封装成小型 HTTP 服务接入 Web 或桌面前端。在工具层增加沙箱、权限和审计再考虑自动加载插件。如果确需 Agent 能力再研究 ReAct 循环或引入成熟 Agent 框架。最后回到这篇文章的核心判断所谓 DeepSeek Harness 插件不需要一开始就依赖某个神秘安装包。先理解 Harness 的层次结构再手写一个最小闭环后续无论接入 VS Code、命令行还是桌面端都会很清楚哪里是模型 API哪里是工具执行层哪里只是前端表现。这个可控的最小骨架就是“空城计”真正的价值看起来像一座坚城实际只是一小段扎实的代码但足以让你在更大工程面前不慌不乱。