先看一个反直觉的结论:大量Agent项目之所以停摆,真正瓶颈往往不是模型能力不够,而是“骨架”没搭对。这里的“骨架”不是指某个模型,也不是指某个开源框架,而是我们用什么样的控制流程,把大模型、工具、记忆和外部环境组合起来。这个骨架,在工程上通常被称为Harness。
很多人拿到DeepSeek API之后的第一反应,是写一个循环:把用户问题丢给模型,再把模型输出拼进下一次对话。这种写法做Demo没有问题,一旦进入生产环境就会连环踩坑:工具调用格式不稳定、上下文越积越长、哪个环节出错完全无法定位、换一个开源模型就要重写一遍控制逻辑。这些问题不是模型选型能解决的,而是架构设计的问题。
这篇文章要讲清楚三件事:第一,Harness到底是什么,它和Agent、Skill是什么关系;第二,怎么基于DeepSeek搭建一个工业级可演进的Harness骨架;第三,Skill体系为什么是缩短开发周期的关键,以及怎么在企业项目里落地。文章配有完整的Python示例,读者可以照着跑通一个最小Harness,再把它扩展成团队的生产级基础组件。
1. 90%团队踩坑的架构死穴:模型之下缺少Harness层
先建立一个核心判断:Agent项目能不能落地,取决于模型之外的工程控制能力,而不是模型本身有多聪明。
所谓“架构死穴”,最常见的表现有三种。
第一种,提示词和业务逻辑完全耦合。团队把整个工具列表、历史对话、业务规则全部塞进一个巨大的system prompt里。效果确实“看起来不错”,但一旦工具数量超过20个,提示词超过几千字,模型的输出格式就会飘;改一个工具参数,所有相关任务都可能受影响。这种架构下,Agent的表现完全依赖提示词撰写者的手艺,不具备工程稳定性。
第二种,工具调用没有统一协议。有人用JSON格式,有人用Markdown代码块,有人直接让模型输出一行shell命令。Demo阶段都能用,一旦需要接入鉴权、审计、限流、超时重试,就会发现每个工具的实现方式都不一样,公共逻辑无处安放。团队把时间大量花在“和环境吵架”上,而不是解决业务问题。
第三种,没有“Skill”的概念。Skill可以简单理解为“提示词+工具链+执行策略”的可复用封装单元。没有Skill体系时,每个新需求都从零构建提示词和控制流;有了Skill体系后,常见任务可以被固化成标准化资产。这不只是“封装”的问题,而是决定一个团队是持续积累还是反复返工的关键。
这三种问题叠加在一起,会造成一个现象:模型Demo演示时惊艳全场,上线后维护成本爆炸。多数团队在三个月内放弃,然后把原因归咎于“大模型不稳定”。实际上,大模型的不确定性只是背景噪声,真正决定项目生命周期的是Harness层的设计质量。
2. 核心概念:Agent、Harness、Skill的关系
在展开示例之前,先把三个核心概念讲清楚。这部分内容也是大模型面试中的高频考点。
Agent是目标导向的自主执行体。它不是一次问答请求,而是一个能够接收目标、拆解任务、调用工具、观察结果、迭代推进直到完成的系统。一个完整的Agent通常由大模型内核、控制循环、工具集、记忆系统和观测反馈五部分组成。
Harness是承载控制循环的外部框架。类比来说,大模型像是发动机,Harness是底盘和变速箱。发动机决定动力上限,但最终能跑多快、拐弯稳不稳,取决于底盘调校。Harness负责控制循环的编排,包括如何组装上下文、何时调用工具、如何处理工具返回结果、如何终止任务、如何做安全边界限制。
Skill是封装好的能力资产。一个Skill描述的是“什么任务触发它、按什么步骤执行、需要哪些工具、结果如何校验”。例如“代码审查Skill”可能包含触发条件、审查步骤、工具组合和输出模板。Skill让通用能力可以跨项目复用,也让人工定义的业务规则可以被模型稳定引用。
三者之间的关系可以这样理解:Harness是容器和执行框架,Agent是框架中运行的自主任务实例,Skill是框架中可插拔的标准化能力单元。没有Harness,Agent就退化为裸API调用;没有Skill,Agent的每次任务执行都是从零开始,无法积累。
| 概念 | 定义 | 类比 | 主要解决什么 |
|---|---|---|---|
| Agent | 目标驱动的自主执行系统 | 自动驾驶汽车整体 | 完成复杂目标 |
| Harness | 控制循环与外部编排框架 | 底盘和变速箱 | 控制流程稳定与工程化 |
| Skill | 可复用的能力封装单元 | 标准化功能模块 | 能力复用和积累 |
还有一个容易混淆的点:Chain、Workflow、Agent三者的区别。Chain是固定顺序的链路,每一步都预先写死;Workflow是基于规则的流程编排,可能有分支和条件判断,但决策路径由开发者定义;Agent则是把决策权交给模型,由模型在循环里自主决定下一步动作。工业级项目真正需要的是三者的混合,而不是非此即彼。Harness的职责之一,就是兼容这些不同粒度的控制方式。
3. DeepSeek作为Agent底座的优势与边界
为什么拿DeepSeek来搭Harness?这需要分开两点看:模型能力和架构适配性。
从模型能力看,DeepSeek系列模型在中文理解、代码生成、逻辑推理和长文本处理上都有不错的表现。DeepSeek的API兼容OpenAI的消息格式,这意味着团队不需要为它单独开发一套SDK适配层,可以直接用OpenAI生态的工具链完成接入。具体API地址、模型名称、Key申请方式,以官方文档为准。这篇文章的重点不是API参数背诵,而是怎么用这套接口把Harness搭起来。
从成本和组织适配看,DeepSeek有两个受欢迎的特点:一是API调用成本相对可控,适合需要大量Agent尝试的团队;二是开源权重模型支持私有化部署,对数据和合规要求高的企业更有吸引力。这两点让DeepSeek成为很多团队做Agent原型的首选模型之一。
但必须承认边界。DeepSeek不是万能的,Agent项目的成败更多取决于Harness能不能把模型能力稳定放大。即使是行业最强的模型,如果外层控制框架设计混乱,照样会出现上下文失控、工具误调用、错误循环等问题。
因此,本文所讲的DeepSeek Harness,不是特指某个官方闭源产品,而是一种工程模式:以DeepSeek模型为推理内核,在外部建立Control Loop、Tool Registry、Memory、Skill、Observability五个基础组件。这个模式可以落地在不同模型上,选用DeepSeek只是因为它的接入成本低、API兼容性好,适合作为示例。
4. DeepSeek Harness的架构分层设计
工业级Harness不是一段循环脚本,而是分层的。以下是推荐的五层结构。
第一层是控制层。控制层承载主循环,负责维护任务状态机的流转。一个常见的状态机是:plan(拆解任务)→ act(调用模型或工具)→ observe(读取执行结果)→ reflect(判断任务是否完成)。控制层必须设计终止条件,避免Agent陷入无限循环。通常使用最大迭代次数、超时时间、目标完成判定三重机制。
第二层是消息层。消息层负责把系统提示词、用户问题、历史消息、工具结果组装成模型可以理解的上下文。这里的关键是消息结构的统一:一个标准tool消息必须包含工具名称、参数、返回结果、执行状态。所有工具的输入输出都走同一套协议,上层控制逻辑才不会被某个特殊格式绑架。
第三层是工具层。工具层通过Tool Registry管理工具。注册表里需要记录工具名称、描述、参数Schema、权限级别、超时阈值。工具层必须做到鉴权、限流、审计、失败重试等公共逻辑的统一处理,而不是把这个责任推给模型。
第四层是Skills层。Skills层负责把“提示词+工具链+执行策略”固化成可复用资产。每个Skill有触发条件、执行步骤、依赖工具和输出Schema。控制层在收到用户请求后,会先尝试匹配Skill;命中Skill就走标准化执行路径,未命中则走通用Agent路径。
第五层是观测层。观测层负责日志、追踪、指标和评测。简单说,就是每个Agent运行周期的输入输出、工具调用时间、Token消耗、失败原因都要有记录。工业级Agent和Demo级Agent最大的区别,就是能否在出问题时快速定位到具体环节。
这五层的关系可以用一句话概括:控制层决定Agent怎么转,消息层决定模型看到什么,工具层决定Agent能做什么,Skills层决定团队积累了什么,观测层决定问题如何被发现。
5. 环境准备与最小Harness骨架
接下来进入实操环节。本文示例使用Python 3.10及以上版本,依赖OpenAI Python SDK,因为DeepSeek API兼容OpenAI格式。
首先准备环境。
mkdir deepseek-harness-demo cd deepseek-harness-demo python -m venv venv source venv/bin/activate pip install openai python-dotenv在项目目录下创建.env文件,填入API Key。
DEEPSEEK_API_KEY=sk-你的key DEEPSEEK_BASE_URL=https://api.deepseek.com DEEPSEEK_MODEL=deepseek-chat创建config.py,统一读取环境变量。这个文件看起来简单,但它的价值在于让整个项目只有一个地方维护模型配置,避免密钥散落在业务代码里。
# config.py import os from dotenv import load_dotenv load_dotenv() DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY") DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL", "https://api.deepseek.com") DEEPSEEK_MODEL = os.getenv("DEEPSEEK_MODEL", "deepseek-chat") MAX_ITERATIONS = int(os.getenv("MAX_ITERATIONS", "8"))接下来创建tools.py,定义两个示例工具。一个是获取当前时间,一个是按文件名关键字搜索项目文件。注意,工具函数必须返回字符串,这样后续消息组装才不会出现类型问题。
# tools.py import os from datetime import datetime def get_current_time(): return datetime.now().strftime("%Y-%m-%d %H:%M:%S") def search_file(keyword: str): results = [] for root, dirs, files in os.walk("."): if any(skip in root for skip in (".git", "venv", "__pycache__")): continue for fname in files: if keyword in fname: results.append(os.path.join(root, fname)) return "\n".join(results[:10]) if results else "未找到包含该关键词的文件" TOOL_REGISTRY = { "get_current_time": { "func": get_current_time, "desc": "获取当前时间,返回格式为 YYYY-MM-DD HH:MM:SS", }, "search_file": { "func": search_file, "desc": "按文件名关键字搜索项目文件,参数为 keyword", }, }6. 完整示例:用DeepSeek搭建一个可运行的Harness
这个章节是全文的核心代码部分。为了让读者理解Harness的控制逻辑,我把实现拆成三个文件:Skills定义、Harness主循环、入口脚本。
先创建skills.py。这里定义两个Skill:一个模拟“代码审查”,一个模拟“日报生成”。Skill的主要作用是让Agent在特定任务下走标准化路径,而不是每次盲目让模型自由发挥。
# skills.py SKILLS = { "code_review": { "trigger": "代码审查、代码走查、检查代码", "steps": [ "明确用户需要审查的文件范围", "使用 search_file 找到目标文件", "从错误处理、资源释放、日志规范三个维度评价", "输出问题清单和修改建议", ], "tools": ["search_file"], }, "daily_report": { "trigger": "生成日报、生成汇报、整理工作日报", "steps": [ "询问用户今日完成的主要事项", "按 今日完成 / 明日计划 / 风险与依赖 三部分输出", ], "tools": [], }, }然后创建harness.py,这是整个示例的核心。控制逻辑采用“模型输出→解析动作→执行工具→回填结果→再次调用模型”的循环。和直接使用模型原生的function calling不同,这里故意使用自定义的TOOL_CALL标记,目的是把控制流程显式展示出来。生产环境建议使用官方function calling或结构化输出,思路完全一致。
# harness.py import json from openai import OpenAI import config from tools import TOOL_REGISTRY from skills import SKILLS class DeepSeekHarness: def __init__(self): self.client = OpenAI( api_key=config.DEEPSEEK_API_KEY, base_url=config.DEEPSEEK_BASE_URL, ) self.model = config.DEEPSEEK_MODEL self.messages = [ {"role": "system", "content": self._build_system_prompt()} ] self.iterations = 0 def _build_system_prompt(self): tool_lines = "\n".join( f"- {name}: {meta['desc']}" for name, meta in TOOL_REGISTRY.items() ) skill_lines = "\n".join( f"- {name}: 触发条件[{meta['trigger']}] " f"执行步骤 {meta['steps']}" for name, meta in SKILLS.items() ) return ( "你是一个运行在Harness框架中的Agent。你的工作方式如下:\n" "1. 如果需要调用工具,请先输出一行 TOOL_CALL,紧接着输出一个JSON对象," "JSON包含 name 和 arguments 两个字段。\n" "2. 如果任务完成,请先输出 FINAL 标记,再输出最终答案。\n" "3. 不要输出多余的解释。\n\n" f"可用工具:\n{tool_lines}\n\n" f"可用Skill:\n{skill_lines}\n" ) def _parse_action(self, text): if "TOOL_CALL" not in text: return None json_part = text.split("TOOL_CALL", 1)[1].strip() try: return json.loads(json_part) except json.JSONDecodeError as e: return {"error": f"工具调用JSON解析失败: {e}"} def _execute_tool(self, action): if "error" in action: return action["error"] name = action.get("name") arguments = action.get("arguments", {}) meta = TOOL_REGISTRY.get(name) if not meta: return f"未知工具: {name}" try: result = meta["func"](**arguments) return str(result) except Exception as e: return f"工具执行异常: {e}" def run(self, user_question): self.messages.append({"role": "user", "content": user_question}) while self.iterations < config.MAX_ITERATIONS: self.iterations += 1 response = self.client.chat.completions.create( model=self.model, messages=self.messages, temperature=0.2, ) text = response.choices[0].message.content print(f"\n[Agent迭代 {self.iterations}]") print(text) action = self._parse_action(text) if action is None: return text tool_result = self._execute_tool(action) self.messages.append({"role": "assistant", "content": text}) self.messages.append( { "role": "user", "content": ( f"工具执行结果:{tool_result}\n" "请根据结果继续处理。如果任务完成,请直接以 FINAL 开头输出最终答案。" ), } ) return "达到最大迭代次数,请缩小任务范围或提高 MAX_ITERATIONS。"最后创建main.py,作为入口。
# main.py from harness import DeepSeekHarness if __name__ == "__main__": question = input("请输入任务:") answer = DeepSeekHarness().run(question) print("\n========== 最终结果 ==========") print(answer)这段代码虽然精简,但它已经体现了工业级Harness的几个核心机制:
一是上下文中的角色分工。系统提示词负责定规则,用户消息负责给目标,助手消息保存Agent的推理轨迹,用户消息再回填工具结果。这种消息组装方式是所有Agent框架的基础。
二是工具执行结果回填。模型生成“TOOL_CALL”后,Harness截获解析,调用工具,再把结果作为新的用户消息交给模型。这个“模型-工具-结果-模型”的闭环就是ReAct思想的工程实现。
三是迭代边界。MAX_ITERATIONS防止任务失控。生产环境还需要加上总耗时限制和Token消耗限制,避免单次任务耗尽预算。
四是Skill匹配与执行路径分离。示例代码将Skill作为提示词的一部分提供给模型。更复杂的工业实现会把Skill匹配放在Harness内部,用分类模型或规则引擎决定是否走标准化Skill路径。
7. 运行效果与验证方式
运行示例:
python main.py输入一个需要调用工具的任务,例如:“请帮我搜索项目里和 config 相关的文件,并列出路径”。
预期输出会有类似这样的流程:模型先输出一个带有TOOL_CALL标记的JSON,Harness执行search_file后把结果回填给模型,模型再输出FINAL结果。
成功启动的关键指标有三个:第一,没有出现401或403鉴权错误;第二,能看到至少一次工具调用;第三,最终回答与工具返回结果一致。如果模型没有按预期输出TOOL_CALL,问题通常出在系统提示词的指令不够清晰,可以补充一个few-shot示例。
如果DeepSeek API返回超时,本质就是“agent执行提供方没有及时响应”。这类超时可能说明模型服务繁忙,也可能说明你的工具执行耗时过长,比如某个工具在同步调用外部接口。生产环境必须为这两类超时分别设计重试策略:模型调用超时使用指数退避,工具执行超时则根据工具类型判断是否允许取消。
验证阶段还要做一类测试:输入一个不需要工具的任务,例如“使用日报Skill帮我整理今天的工作”,观察模型是否会选择引用Skill中定义的结构。如果模型完全忽略Skill定义,就不要急着扩展功能,先优化系统提示词中的Skill描述,这也是后面要说的Skill优化问题。
8. 常见问题与排查思路
以下是最容易在Agent项目里遇到的问题,按出现频率排序。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| API返回401 | API Key错误或缺失 | 检查.env文件和负载变量 | 确认Key有效并重新加载env |
| 请求超时 | 模型服务繁忙或网络不稳定 | 查看客户端超时配置和日志 | 增加超时时间,使用指数退避重试 |
| 模型不输出TOOL_CALL | 系统提示词缺少few-shot示例 | 打印system prompt,检查指令是否明确 | 在提示词中加入一个工具调用示例 |
| 工具返回JSON解析失败 | 模型输出了多余的说明文字 | 打印原始输出 | 调整提示词,要求只输出JSON;或使用正则截取JSON |
| 上下文越来越长 | 工具结果未做截断 | 查看messages长度曲线 | 对工具结果做长度上限,增加摘要压缩 |
| 达到最大迭代次数 | 任务边界不清或循环无出口 | 查看调用链和工具结果 | 限定子任务范围,增加终止条件 |
| 限流429 | 并发过高或触发频率限制 | 查看API返回头 | 增加请求排队和退避机制 |
这里尤其要强调上下文管理。示例为了可读性没有做消息截断,生产环境如果放任工具结果无限增长,对话很快会撑爆上下文窗口,费用也会线性上升。常见做法是:每轮工具结果只保留最近N条;超过阈值后,先把历史消息摘要在系统提示词中,再丢弃原始消息。
另一个容易被忽视的问题是参数传递错误。例如search_file函数期望keyword参数,如果模型输出了keywords,工具层应该捕获TypeError并返回可读错误。这种问题的高频发生,说明Tool Registry必须有参数Schema校验能力,而不是简单地把**arguments传给函数。
9. Skill优化:把20分钟Demo变成3天可交付项目的关键
Skill体系是工业级Agent项目里最值得投资的部分,也是“开发周期缩短”这个目标的真正支撑点。
先理解为什么Skill能缩短周期。没有Skill时,每次类似任务都要重新设计提示词、重新调试工具调用,调试过程还会重复踩坑。有了Skill后,任务被标准化为“触发条件+执行步骤+工具依赖+输出规范”。团队里任何成员接手新任务,优先复用已有Skill,只有真正的新场景才需要新建Skill。这种积累效应会让开发成本随时间递减,而裸调API的项目成本只会随复杂度递增。
Skill优化有三个重点。
重点是触发条件的准确性。一个Skill的trigger必须描述清楚“什么时候用它”。可以把触发条件写给模型看,也要写给检索系统看。比如“代码审查”Skill的触发词应该覆盖“检查代码”“代码走查”“review代码”等常见表达。触发条件模糊,再好的Skill也不会被模型正确选中。
重点是执行步骤的颗粒度。Skill中的steps不宜太细,也不宜太粗。太细会把模型限制成死流程,失去灵活性;太粗等于没写。业界常用的颗粒度是“每步是可验证的执行阶段”,而不是“每句提示词”。例如“找到目标文件”“从错误处理角度分析”就比“用find命令递归查找”“看看有没有try except”更合适。
重点是输出Schema的统一。每个Skill最好定义标准输出结构。比如代码审查Skill的输出应该包含问题列表、严重级别、修改建议三个字段。这样上层系统可以结构化解析结果,无论是接入告警、生成报告还是进入修复流程,都变得容易。
Skill优化还包括定期清理和测试。随着项目演进,Skill会累积重复或过时。建议每个迭代周期做一次Skill列表复盘:哪个Skill命中率低?哪个Skill步骤描述已经和最新代码不一致?Skill本身也要纳入版本控制,因为它是团队的重要资产。
10. 从实战到面试:Agent架构高频考点与总结
这篇文章从架构死穴讲到Harness分层,再落到代码和Skill优化,核心想传递一个观点:Agent项目不是“模型够不够强”的问题,而是“工程化控制够不够稳”的问题。DeepSeek Harness在这样的背景下,不是某一个固定产品,而是一套可以复用的工程思路:用分层架构管理不可控的大模型推理过程,用统一消息协议连接工具,用Skill体系沉淀团队能力。
如果你准备用这篇文章作为一次团队分享的素材,可以围绕四个问题展开:你们现在的Agent项目有没有独立的控制层?工具调用是否走统一协议?历史任务经验是否沉淀成了Skill?故障是否能快速定位到具体环节?把这四个问题想清楚,比换一个更强的模型更有意义。
在大模型面试中,Agent架构相关的问题也值得单独准备。高频方向包括:ReAct循环的实现机制、Tool Calling的消息格式、Harness与Chain和Workflow的区别、上下文窗口的管理策略、Agent的终止条件设计、工具调用的安全边界。回答时不要只背概念,要用项目中的实际取舍来说明,例如“我们的Harness里为什么设置最大迭代次数”“工具结果为什么要截断”。能够讲清楚设计决策背后的原因,才是面试官真正想听到的内容。
对于已经跑通示例代码的读者,我建议的下一步不是急着堆功能,而是做三件事:第一,把工具层接入统一的鉴权和审计逻辑;第二,为一个真实业务场景设计一个Skill并测试它的命中率和输出质量;第三,给Harness加一层观测面板,记录每次Agent运行的轨迹。这三步做完,你就真正从“Demo开发者”迈向了“Agent系统工程师”。
最后提醒一点:生产环境使用Agent时,所有工具都要遵循最小权限原则,尤其是具备文件删除、数据写入、命令执行能力的工具,一定要做权限校验、操作确认和完整审计。架构决定一个Agent能跑多远,而安全边界决定它能不能安全地跑完全程。