DeepSeek Harness实测:权限拦截≠结果正确

看 Agent 产品演示时,最容易被最后一句“任务完成”带走。真正值得看的,是它到底发起了几次模型请求,工具有没有真的执行,权限拒绝发生在哪一层,最后的回答是否与实际文件状态一致。
用户提供的 DeepSeek Harness 素材记录了一次很小但很有价值的本地实验:让 Agent 创建 result.txt,写入指定内容,再通过 Shell 确认文件存在。实验没有拿一个复杂项目来展示“模型多聪明”,而是用确定性测试端点,把模型质量和 Harness 的执行能力分开。这个思路值得所有 Agent 开发者借鉴。
本文不把一次实验外推成产品的全部能力,而是借这条最小链路说明:Harness 如何把模型的工具意图变成实际动作,权限如何阻拦动作,为什么仍然需要独立的验收机制,以及怎样把实验改造成自己的回归测试。
一、先理解模型说了什么,系统做了什么
直接调用模型 API 时,模型可能返回一个工具调用结构,大意是“请调用 write,把某段内容写进 result.txt”。这只是计划或意图,文件系统不会因为 JSON 出现就自动改变。
真正的过程需要外部运行时接住它:
模型请求:选择 write 工具并给出参数。
Harness:读取当前工作区和权限,检查路径与参数。
工具执行:实际创建或写入文件,返回成功或错误。
Harness:把工具结果放回会话上下文。
模型请求:根据结果决定是否继续,可能选择 bash 验证。
工具执行:在受限 Shell 中执行验证命令。
模型:结合工具返回,生成最终说明。因此,评估 Agent 不能只看模型输出,也不能只看工具列表。至少要同时观察请求、工具、权限、返回值和最终状态。缺了其中一环,失败时就只能靠猜。
二、为什么要用一个最小实验
复杂项目同时包含代码、依赖、测试、项目规则和大量上下文。一次任务失败后,很难确定原因来自模型、工具参数、权限、环境,还是仓库本身。最小实验则把变量压缩到几件可核对的事实:
工作区:一个新建的测试目录。
输入:一个明确的文件名和固定文本。
动作:一次写入、一次 Shell 检查。
验收:文件存在,内容与要求一致。
权限:分别测试可写和只读环境。用户素材中使用本地确定性测试端点,是为了观察 Harness 的执行过程,而不是为某个模型做速度或质量宣传。即使你没有同样的测试端点,也可以用一个固定任务、一个空目录和人工检查实现类似实验。关键是不要把“模型表现”和“运行时行为”混成一个分数。
三、可复现实验的任务定义
可以先把任务写成下面这样:
只在当前测试工作区执行任务。
1. 创建 result.txt。
2. 写入:harness-test-ok
3. 使用受限 Shell 检查文件是否存在,并读取内容。
4. 最终回复必须说明:文件路径、实际内容、验证命令结果。
如果任一步失败,必须报告失败,不得把任务标记为完成。这里最后一句很重要。它把验收要求写进任务,但不能把它当成唯一保证。模型可能忽略要求,或者在工具失败后仍然生成“已完成”。所以实验结束后仍要由测试脚本或人工查看文件状态,不要只看聊天窗口。
四、成功路径应该观察什么
在可写工作区中,一条合理的轨迹大致包含:
task_received
-> workspace_loaded
-> write_requested
-> permission_allowed
-> file_written
-> bash_requested
-> bash_returned
-> task_completed检查时可以问:
write 的路径是否在测试目录内?
写入的内容是否与参数完全一致?
Shell 是否真的读取了文件,而不是只返回一个固定字符串?
模型是否看到了工具返回后才宣布完成?
最终回复是否包含实际验证结果?如果界面提供轨迹或事件视图,优先保存一次完整记录。它比截图最终答案更有价值,因为未来修改插件、模型或权限后,可以拿同一任务比较行为是否变化。
五、只读模式下,权限拦截发生在哪里
将同一个任务放进只读工作区,预期结果应该不同。写文件动作在执行层被拒绝,常见表现是类似 FS_SANDBOX_DENIED 的权限错误;由于文件没有创建,后续的 Shell 验证也可能因目标不存在而失败。具体错误名称会因版本和实现变化,不能把某个字符串当成所有环境的固定协议。
这类失败说明了一个重要事实:权限控制不是提示词。提示词可以告诉模型“不要写文件”,沙箱则是在工具真正执行前检查路径和操作类型。即使模型坚持调用 write,只要执行层没有写权限,动作就不会落地。
但权限拦截只回答一个问题:能不能做。它不回答另一个问题:最后那句“已经完成”是否可信。素材记录过一种边界情况:工具报错后,测试模型仍然回复任务完成。这个结果并不意味着权限系统失效,而是说明“执行控制”和“结果验收”是两个独立层次。
六、把权限和验收分成两条线
可以把任务安全拆成两条流水线:
权限线:路径、命令、网络、身份和审批,决定动作能不能发生。
验收线:文件状态、测试结果、业务规则和证据,决定结果能不能交付。例如,权限线允许 Agent 在工作区内写文件,不代表它写出的代码通过测试;权限线拒绝了 Shell 命令,也不代表 Agent 应该把任务判定为完成。工程上要给验收线单独设计检查:
| 任务 | 最低验收 |
|---|---|
| 创建文件 | 文件存在、路径正确、内容匹配 |
| 修改代码 | diff 范围正确、测试执行、结果无新增失败 |
| 生成报告 | 来源存在、数字口径一致、待确认项列出 |
| 调用外部系统 | 返回 ID、状态可查、没有重复副作用 |
在可靠的工作流里,最终状态应由工具结果、测试脚本或业务规则共同决定,而不是只由模型的一句话决定。
七、把一次实验做成回归测试
最小实验跑通一次后,不要把它停在截图。可以保存以下内容:
测试任务文本和工作区初始化方式。
模型、Harness、插件与配置版本。
允许和拒绝两组权限设置。
预期事件顺序与关键工具参数。
预期文件状态、Shell 返回和最终状态。
异常时的人工接手与清理方式。每次升级后重跑两组任务:可写成功、只读拒绝。若写入路径、事件顺序、错误处理或最终状态发生变化,就先查看差异,再决定是不是预期改动。对有外部副作用的 Agent,还应增加重复执行、取消任务、工具超时和中途卸载插件的用例。
八、哪些结果不能从这个实验推出
一个文件写入实验能证明的范围很窄。它可以帮助你确认某套环境里的工具调用和权限边界,但不能证明:
模型适合复杂编码任务。
Agent 能稳定理解大型仓库。
所有插件都能安全热插拔。
Shell 沙箱覆盖了所有外部副作用。
任务失败后一定能自动恢复。
产品在生产环境具备多租户和审计能力。这些问题需要分别设计评测。模型能力要用固定任务集和多次运行衡量;复杂仓库要看上下文、测试和人工修正;插件安全要做权限与供应链审查;生产能力要核对身份、状态、日志、恢复和组织流程。不要让一个成功创建文本文件的演示替产品承担它没有证明的结论。
九、实际使用中的排查顺序
当一个任务表现异常时,可以按从底层到上层的顺序查:
1. 工作区是否正确,目标路径是否存在且可访问。
2. 当前模式是否加载了预期工具、Skill 和插件。
3. 权限是否允许该操作,拒绝是否发生在执行层。
4. 工具参数和返回值是否与模型看到的内容一致。
5. 模型是否在收到失败结果后仍然继续或误报完成。
6. 最终文件、测试、外部状态是否真的符合验收条件。这条顺序能避免一开始就更换模型。很多看似“模型不行”的问题,其实是工作区选错、工具没有加载、权限拒绝或验收缺失。反过来,底层都正常而模型仍然反复误判时,才值得比较模型、提示词和上下文策略。
十、把实验结果记录成一张对照表
只写“成功”或“失败”不够。至少把权限、工具和最终状态拆开记录:
| 场景 | 工具请求 | 执行结果 | 最终文件 | 正确终态 |
|---|---|---|---|---|
| 可写工作区 | write、bash | 均成功 | 内容匹配且可读取 | completed |
| 只读工作区 | write 被拒绝 | bash 因文件不存在失败 | 文件不存在 | failed 或 handed_off |
| 错误路径 | write 参数合法但目标不在范围 | 沙箱拒绝 | 文件不存在 | failed |
| 工具超时 | write 无明确返回 | 状态未知 | 先查询再决定 | waiting 或 handed_off |
| 重复执行 | 同一任务再次写入 | 需检查幂等规则 | 不应产生意外副本 | completed 或 skipped |
这张表把“工具有没有执行”和“任务是否完成”分开了。测试时还可以加一条故意错误的模型回答:让模型在工具失败后声称成功,然后检查系统是否依靠文件状态或测试脚本把它拦下来。这个用例比正常成功路径更能暴露验收缺口。
十一、如何处理误报完成
如果 Harness 把工具失败结果交还给模型,而模型仍然说任务完成,不要只在系统提示词里加一句“不要说谎”。更可靠的做法是把完成状态交给外部判定器:
工具失败:任务不能进入 completed。
文件任务:检查路径、内容哈希和文件存在性。
代码任务:检查 diff、测试命令退出码和新增失败。
外部任务:检查对象 ID、服务端状态和幂等记录。
信息任务:检查必需来源、字段和人工确认项。模型可以负责解释这些结果,但不能单独改变状态。若判定器发现证据缺失,界面应该显示“失败”“等待确认”或“转人工”,而不是继续显示绿色的完成提示。对业务人员来说,明确的未完成比一段自信但错误的总结更有用。
十二、让测试覆盖工具以外的状态
文件写入和 Shell 只是第一组测试。实际使用还会遇到会话压缩、插件切换、任务取消和重新加载页面。可以逐步扩展测试矩阵:
在模型请求之间关闭页面,再恢复会话。
在工具执行前取消任务,确认不会留下半截文件。
在任务运行中撤销写权限,确认后续调用被阻断。
让 Shell 返回非零退出码,确认模型不会忽略错误。
加载一个新增插件,确认旧任务的工具集合没有悄悄变化。
重复提交同一任务,确认不会产生重复外部副作用。这些测试的共同目标,是检查状态变化是否可见、可解释、可恢复。Agent 运行时的可靠性通常不是由一次成功调用决定的,而是由任务被打断、拒绝或重试时仍能保持边界决定的。
十三、不要把界面轨迹当成完整审计
轨迹页对开发调试很有用,但它不一定等于企业审计日志。界面可能只展示摘要,日志可能没有保存权限变化,也可能没有把外部对象 ID 和插件版本串起来。正式使用前要确认:
事件是否能导出或查询,而不是只能看当前页面。
任务、运行、插件、模型、工具和用户是否有稳定 ID。
敏感内容是否脱敏,访问权限和保留期限是否明确。
删除、发送、部署等外部副作用是否有单独记录。如果这些能力尚未具备,就把 Harness 当作开发测试环境使用,不要因为看到了几行工具记录,就把它描述成已经完成企业级审计。
十四、一次运行至少保存哪些字段
为了让下一次问题能回到同一条链路,测试记录至少应保留一组能关联的字段。下面是通用设计示例,不是 DeepSeek Harness 的固定接口:
{
"task_id": "write-file-readonly-001",
"run_id": "run-001",
"workspace_scope": "test-readonly",
"runtime_version": "recorded-locally",
"model_provider": "test-endpoint",
"tool_name": "write",
"permission_decision": "denied",
"tool_outcome": "failed",
"verification_outcome": "file_absent",
"final_state": "failed"
}这组字段刻意没有保存完整提示词、密钥或文件正文。调试时需要的是“哪一轮、在什么边界下、哪个工具、因为什么原因失败”,而不是把所有敏感信息复制进另一套日志。对需要更强审计的场景,可以追加执行身份、插件版本、工具参数摘要和时间戳,但仍应按组织的数据保留规则脱敏。
十五、结论
DeepSeek Harness 的价值,恰恰体现在它把模型请求、工具执行、权限检查和会话轨迹摊开给开发者看。一次小实验已经足以说明:模型只提出动作,Harness 才把动作接入文件系统和 Shell;权限可以阻止越权,验收机制才决定结果是否真实。
如果你准备研究 Agent,先用一个可写、一个只读的测试工作区把这条链路跑通,再逐步加入复杂工具和插件。不要从“最终回答看起来像完成了”开始,而要从“实际发生了什么、失败后能否解释”开始。
资料说明:本文依据用户提供的 DeepSeek Harness 实测素材整理。实验现象、错误名称、界面字段和支持的配置可能随版本变化,正式使用前请以当前官方文档和本地实际轨迹为准。
Related
相关文章推荐

DeepSeek Harness:Agent与插件运行时拆解
DeepSeek Harness是什么?可组合Agent运行时,Cordis管插件,拆解Agent=Model+Harness。

Agent上线后怎么观测?三仪表盘监控成功率/接管率/成本
Agent上线后三仪表盘:任务成功率、人工接管率与成本监控,事件链设计与异常排查流程。

MT-SDPO多教师蒸馏实战:多模型集成降本与路由策略
多教师蒸馏MT-SDPO实战:按样本选教师、验证器把门、缓存降本,附4sapi多模型路由示例。

21万页假评测污染 AI 推荐|引用溯源避坑
内容农场如何污染AI推荐?来源校验、模板检测、去重与引用溯源,附4sapi接入示例。