Harness、Skills、Workflow——三个概念的关系和我的选择

Harness、Skills、Workflow:三个概念的关系,以及我现在的选择

做了几个比较重的 AI Skill 之后,我开始重新思考一个问题:

我现在做的东西,到底算 Skill、Workflow,还是 Harness?

一开始我把这三个概念放在同一条线上比较,后来发现这样容易混乱。更准确地说,它们不是同一层级的东西。

  • Workflow 是一种确定性流程编排方式。
  • Skill 是一种能力封装形态。
  • Harness 是一套能力运行与治理框架。

它们不是三选一,也不是谁比谁高级,而是解决不同层级的问题。一个成熟的 Agent 系统里,三者甚至可以同时存在。


一、Workflow:确定性流程编排

Workflow 是最传统、最稳定的工程抽象。

它的核心不是“每一步都完全没有判断”,而是:

流程控制权主要在代码或流程引擎手里。

也就是说,开发者提前定义好:

  • 有哪些步骤;
  • 每一步输入是什么;
  • 每一步输出是什么;
  • 失败怎么重试;
  • 哪些分支可以走;
  • 哪些状态可以恢复。

一个典型 workflow 可能长这样:

fetch_data
  ↓
clean_data
  ↓
analyze_data
  ↓
generate_report

如果写成配置,大概是这样:

steps:
  - id: fetch_data
    action: call_api
    next: clean_data

  - id: clean_data
    action: run_script
    next: analyze_data

  - id: analyze_data
    action: llm_call
    next: generate_report

  - id: generate_report
    action: render_template

Workflow 里当然也可以有 LLM 节点。比如某一步需要分类、总结、生成结构化 JSON,就可以调一次 LLM。

但是在这种模式下,LLM 通常只是流程里的一个节点:

上一步输出 → prompt 模板 → LLM 调用 → JSON 解析 → schema 校验 → 下一步

它不负责决定整个任务下一步怎么走,也不负责和用户自由交互。真正控制流程的是 workflow engine 或代码。

所以 workflow 最适合这些场景:

  • ETL;
  • 定时任务;
  • CI/CD;
  • 批量数据处理;
  • 固定步骤的自动化任务;
  • 要求高可靠、可恢复、可重试的流程。

它的优势是稳定、清晰、可恢复。缺点也很明显:

当用户交互很多、需求很模糊、分支很多时,workflow 会变成巨大的状态机。

每一个“用户中途改主意”、每一个“输入格式不标准”、每一个“这一步想跳过”,都可能变成新的 if/else。

这就是我以前写 workflow 最痛苦的地方。


二、Skill:Agent 可以使用的能力包

Skill 解决的是另一个问题:

如何把一个复杂能力封装起来,让 Agent 能够理解、调用和完成任务。

在 Codex、Cursor、Kiro、Claude Code 这类 Agent 平台里,Skill 往往不是一个简单函数,而是一个能力包。

它可能包含:

amazon-analysis-skill/
  INSTRUCTIONS.md
  config.json
  knowledge/
  tools/bin/
  templates/
  examples/

这里的核心不是“固定流程”,而是:

把领域知识、操作说明、工具入口、约束规则打包给 Agent,让 Agent 在任务中自主使用。

Agent 读了 INSTRUCTIONS.md 之后,可以自己判断:

  • 当前应该执行哪一步;
  • 用户输入是否缺信息;
  • 是否需要追问用户;
  • 是否要跳过某个步骤;
  • 出错后是重试、降级,还是让用户确认;
  • 最后应该怎么组织报告。

所以 Skill 的哲学和 Workflow 不一样。

Workflow 是:

代码控制流程,LLM 只是节点。

Skill 更像是:

Agent 控制过程,Skill 提供能力边界和操作工具。

这也是为什么我会选择 Skill 模式来做很多垂直 AI 应用。

我的场景不是简单的“输入 A 输出 B”,而是:

  • 用户会中途补充信息;
  • 用户可能不懂自己要什么;
  • 数据分析过程中需要判断;
  • 报告生成需要理解上下文;
  • 很多地方没法提前穷举所有分支。

这时候如果强行 workflow 化,就会写出大量状态机和分支逻辑。

而 Skill 模式的好处是:

我只需要描述正常路径、边界条件和禁止行为,中间的弹性判断交给 Agent。

本质上,这是把“穷举所有情况”的成本,转嫁给了 LLM 的泛化能力。

这句话不是说 Agent 万能。恰恰相反,Agent 不可靠,所以 Skill 不能只靠 prompt。

一个好的 Skill 仍然要有硬边界:

  • 后端校验参数;
  • CLI 封装复杂调用;
  • 凭据不要暴露给 Agent;
  • 中间结果写文件;
  • 输出格式尽量结构化;
  • 高风险操作交给代码拦截。

也就是说:

软约束写在 INSTRUCTIONS.md 里,硬约束放在 CLI、后端和服务端。

凡是不能出错的地方,不要只靠 Agent 自觉。


三、Harness:能力运行与治理框架

我之前对 Harness 的理解偏浅,容易把它理解成“更高级的 workflow”。

现在我觉得更准确的定义是:

Harness 不承载具体业务逻辑,它承载的是能力管理逻辑。

它不关心 Amazon 怎么分析,也不关心博客怎么写,更不关心服务器怎么排障。

这些业务能力属于 Skill。

Harness 关心的是:

  • 有哪些 Skills;
  • 每个 Skill 怎么声明;
  • 输入输出 schema 是什么;
  • 如何统一执行;
  • 如何记录 run 状态;
  • 如何保存中间产物;
  • 如何记录 trace;
  • 如何统一错误码;
  • 如何跑 eval;
  • 如何做权限和 guardrails;
  • 如何让 Agent 通过稳定接口调用这些能力。

如果用一句话说:

Skill 是能力包,Harness 是能力运行时。

或者更具体一点:

Skill Harness 是一套用于创建、运行、测试、追踪和治理多个 Skills 的统一框架。

这就像 Docker 和应用的关系。

Docker 不知道你的业务是博客、数据库、API 还是爬虫,但它统一管理镜像、容器、日志、端口、环境变量和运行状态。

Skill Harness 也一样。它不写具体业务,但它管理 Skill 的执行方式。

一个最小的 Skill Harness 可能会要求每个 Skill 都有统一结构:

skills/
  amazon-analysis/
    skill.yaml
    SKILL.md
    schemas/
      input.json
      output.json
    scripts/
      run.py
    knowledge/
    templates/
    eval_cases/

其中 skill.yaml 是 Harness 理解 Skill 的入口:

name: amazon_analysis
version: 0.1.0
description: Analyze Amazon products and generate structured reports
entrypoint: scripts/run.py
input_schema: schemas/input.json
output_schema: schemas/output.json
timeout_seconds: 600
permission_level: normal
eval_cases: eval_cases/

有了这个 manifest,Harness 才能统一做事情:

skill-harness list
skill-harness describe amazon_analysis
skill-harness run amazon_analysis --input input.json
skill-harness trace run_xxx
skill-harness eval amazon_analysis

执行一次 Skill 后,Harness 可以统一生成:

runs/{run_id}/
  input.json
  state.json
  trace.jsonl
  outputs/
  artifacts/
  reports/
  logs/

这就解决了我现在最真实的问题:

每开发一个新 Skill,都像从 0 开始。

目录结构不统一,配置不统一,CLI 风格不统一,输出格式不统一,错误处理不统一,trace 不统一,eval 也不统一。

当 Skill 很轻的时候,这些问题不明显。

但当 Skill 变重之后,比如一个 Skill 里已经包含:

  • Agent instructions;
  • 领域知识;
  • Go CLI;
  • 后端服务;
  • 异步任务;
  • 文件状态;
  • 报告模板;
  • 用户确认;
  • 安全边界;

这时候每个 Skill 都手搓一套,就会非常痛苦。

所以我现在理解的 Harness,不是为了显得高级,而是为了解决一个很朴素的问题:

把一堆重型 Skills 统一起来。


四、三者不是一条线,而是不同层级

我以前容易把它们想成这样:

Workflow → Harness → Skill

好像它们是同一条线上的不同阶段。

现在我觉得这样不准确。

更合理的分层是:

Agent
  ↓ 决策 / 规划 / 选择能力
Skill Harness
  ↓ 统一运行 / 追踪 / 评测 / 权限 / 状态
Skills
  ↓ 封装具体业务能力
Tools / CLI / API / Backend

Workflow 则是一种流程控制方式,它可以出现在不同层级里:

  • 一个 Skill 内部可以有小 workflow;
  • Harness 可以用 workflow 管理固定流程;
  • Agent runtime 也可以把部分步骤 workflow 化;
  • 完全不需要智能的任务,可以只用 workflow。

所以三者关系不是“谁替代谁”,而是:

Workflow = 确定性流程编排方式
Skill = 能力封装形态
Harness = 能力运行与治理框架

它们可以组合。

比如一个成熟系统可能是:

Agent 负责理解目标
  ↓
Harness 负责统一调度和治理
  ↓
Skill 提供具体能力
  ↓
Skill 内部某些步骤用 Workflow 固化

这才是更准确的关系。


五、我为什么一开始选择 Skill

我选择 Skill,不是因为 Harness 不重要,也不是因为 Workflow 没用。

而是因为我当前的问题更适合先用 Skill 落地。

我的场景有几个特点:

  1. 用户交互密集;
  2. 输入经常不标准;
  3. 中间判断很多;
  4. 报告生成需要理解上下文;
  5. 我希望跨 Codex、Cursor、Kiro 等 Agent 平台复用;
  6. 当前很多 Agent 平台并没有给我完整的外部编排接口。

如果我强行写成 workflow,每个用户意图变化都要变成新的分支。

比如用户可能说:

  • “这一步先跳过”;
  • “换一个类目”;
  • “只分析前 5 个”;
  • “这个结果不对,重新筛一遍”;
  • “先别生成报告,我要改条件”。

这些都写进代码状态机,会非常痛苦。

Skill 模式让我可以把流程写成自然语言约束,让 Agent 在边界内自由发挥。

所以短期我选 Skill,是务实选择。

但经过这次重新梳理,我也意识到:

长期不能只停留在写一个个复杂 Skill。

因为当 Skill 多起来之后,真正的问题会变成复用、统一、测试、追踪和治理。

这时候就必须往 Skill Harness 方向抽象。


六、复杂 Skill 里的 mini-harness

我现在的很多 Skill,其实已经不是轻量 Skill 了。

它们里面已经长出了很多 mini-harness 能力:

  • CLI 封装复杂 API;
  • config 管理后端地址和 token;
  • 文件系统保存中间状态;
  • 后端做参数校验;
  • 报告模板统一展示;
  • 错误输出给 Agent 处理;
  • 关键步骤要求用户确认。

这些能力如果只服务于一个 Skill,就还是 Skill 的内部实现。

但如果它们在多个 Skill 中反复出现,就应该抽出来,变成通用 Harness。

判断标准很简单:

只服务一个 Skill,是 Skill 内部 mini-harness;服务多个 Skills,才是真正的 Skill Harness。

这也是我现在最大的认知变化。

我之前以为自己只是在做 Skill。

现在看,我其实已经在每个复杂 Skill 里重复手搓一小套 Harness。

下一步应该把这些重复部分抽象出来。


七、我理想中的 Skill Harness

我现在想做的,不是一个大而全的 Agent 平台。

第一版只需要解决我自己的痛点:

新 Skill 不再从 0 开始。

所以我理想中的 v0.1 应该包含:

  1. 统一目录结构;
  2. 统一 skill.yaml
  3. 统一 CLI 入口;
  4. 统一 runs 目录;
  5. 统一 state.json;
  6. 统一 trace.jsonl;
  7. 统一错误格式;
  8. 统一 eval 入口。

也就是说,它不是先去追求什么复杂 AgentOps,而是先把“重型 Skill 的脚手架和运行器”做好。

未来可以逐步加入:

  • checkpoint;
  • resume;
  • waiting_user;
  • waiting_backend;
  • approval;
  • permission;
  • guardrails;
  • eval dataset;
  • MCP 接入;
  • Web UI;
  • 多 worker 执行。

但第一步很简单:

统一 Skill。

先统一,才能管理。

先管理,才能治理。

先治理,才能谈 Agent Runtime。


八、Harness 怎么接入 Agent

如果 Skill Harness 做好了,它不一定要直接暴露所有业务细节给 Agent。

Agent 不应该重新读一遍所有 Skill 的内部实现。

更合理的是:

Agent
  ↓ MCP / CLI / HTTP
Skill Harness
  ↓ manifest + registry
具体 Skill

MCP 也不应该把所有 Skill 的说明复制一遍。

MCP 只需要暴露几个固定工具:

list_skills
describe_skill
run_skill
get_run_trace
get_run_artifacts
run_eval

真正的 Skill 描述仍然来自 skill.yamlSKILL.md

也就是说:

MCP 是连接线,Harness 是能力管理层,Skills 是能力本体。

不能维护多份重复说明。

正确做法是:

Skill 只有一份 manifest
Harness 读取 manifest
MCP 通过 Harness 动态返回 describe_skill
Agent 通过 run_skill 调用具体能力

这样不会出现“在 Skill 里写一份说明,在 MCP 里再复述一遍”的混乱。


九、我现在的选择

现在我对三者的选择更清楚了。

如果任务是纯确定性的,比如定时同步数据、清洗数据、跑报表,我会选 Workflow。

如果任务是交互式、模糊的、需要 Agent 理解和判断,我会选 Skill。

如果我已经有一堆复杂 Skills,并且开始遇到复用、统一、测试、追踪、权限和状态管理问题,我就需要 Skill Harness。

所以我当前阶段的判断是:

短期用 Skill 落地垂直 AI 应用,长期把多个重型 Skills 抽象进自己的 Skill Harness。

这不是否定 Skill。

恰恰相反,是因为 Skill 做重了、做多了,才需要 Harness。


十、最后的总结

我现在会这样定义这三个概念:

Workflow:确定性流程编排方式。
Skill:Agent 可以使用的能力封装形态。
Harness:管理多个 Skills 的运行、状态、trace、eval、guardrails 的框架。

它们不是互斥关系。

一个好的系统应该是:

用 Workflow 固化确定性流程;
用 Skill 封装垂直业务能力;
用 Harness 统一管理多个 Skills;
用 Agent 在目标驱动下选择和组合这些能力。

我之前最大的误区,是把 Skill 和 Harness 对立起来。

现在我更愿意这样理解:

Skill 是能力,Harness 是能力管理层。

当只有一个 Skill 时,Harness 可能没必要。

当有很多重型 Skills 时,Harness 就不是可选项,而是必然会长出来的工程底座。

这也是我下一步想做的事情:

把我已经写过的复杂 Skills 里重复出现的结构、CLI、状态、trace、eval、错误处理和执行规范抽出来,形成自己的 Skill Harness。

从写 Skill,到管理 Skill,这应该是我接下来最重要的一次升级。

Read more

三台机器部署 ClickHouse 高可用集群实战记录

本文是一份可发布版部署记录。真实 IP、域名、账号、密码、下载链接、业务目录名、机器唯一标识等敏感信息已经替换为占位符。命令中的 <...> 需要按自己的环境替换。 目标与拓扑 这次目标是用三台数据节点部署一套 ClickHouse 高可用集群,拓扑采用: 1 shard x 3 replicas 含义是:集群只有一个逻辑分片,三台机器都保存同一份数据的完整副本。任意一台数据节点宕机时,只要 ClickHouse Keeper 仍然有多数派,剩余节点仍可继续提供读写服务。 规划节点如下: 主机名示例地址角色ch-01<ch-01-ip>ClickHouse Server + ClickHouse Keeperch-02<ch-02-ip>ClickHouse Server + ClickHouse Keeperch-03<ch-03-ip&

By ladydd

折腾记(二):接入火山引擎实时语音 API,家庭语音助手体验直接拉满

接上篇 上一篇用全开源组件(Whisper + Hermes + Edge-TTS)搭了个语音助手,能跑,但体验就是"能用"二字: * 中文识别只有 70 分,方言基本歇菜 * 英文唤醒词"Alexa"喊着别扭 * 说完到回复要等 4-8 秒 * 它说话的时候你插不了嘴 这些问题靠堆开源组件很难根治。于是我去试了火山引擎(字节跳动)的语音服务,结果直接换了条路。 这篇分两段:先讲怎么用火山引擎的 ASR/TTS 替换掉开源组件(小改),再讲怎么上端到端实时语音模型(大改)。 第一段:先把 ASR 和 TTS 换成火山引擎 为什么换 我用豆包输入法的时候发现它语音识别准得离谱。一查,豆包用的就是字节自家的火山引擎 Seed-ASR。开通后有免费额度(

By ladydd

折腾记(一):用全开源组件给家里搭一个语音助手,对接自己的 Hermes Agent

起因 事情是从一块 ESP32-S3 开发板开始的。 我手上有一块 Seeed Studio XIAO ESP32-S3 Sense,带摄像头和麦克风。最初的想法很美好:用这块板子做一个无线语音终端,对着它说话,连到我服务器上跑的 Hermes Agent(一个自托管的 AI agent),让它回答我。 但折腾到一半我突然意识到一件事:我的麦克风、音响、服务器全在家里,为什么要绕一圈用 ESP32?直接把麦克风和音响插到服务器上不就行了? ESP32 那条路(做无线拾音终端)当然也有价值,但那是"为了学嵌入式而学",不是解决问题的最短路径。于是这个项目就从"嵌入式项目"变成了"在服务器上拼一个语音助手"。这篇就记录后者。 教训零:先想清楚你要解决的是什么问题。很多时候最优解比你最初设想的简单得多。 目标

By ladydd

Kiro 的三种代理设置方法:本地、服务端、Remote

作为kiro的骨灰级用户,这篇是我自己折腾 Kiro / Kiro Remote / Ubuntu Server 代理问题后的复盘。 核心不是“怎么配一个代理”,而是先判断:到底是谁在访问外网? 谁访问外网,代理就要配给谁。 0. 先说结论 Kiro 相关代理大概分三类: 场景真正访问外网的进程在哪里代理应该配在哪里本地 KiroWindows / Mac 本机本机 Clash / Proxifier / 系统代理服务端 Kiro / CLIUbuntu Server 上的 shell、CLI、node、kiro 进程Ubuntu 的环境变量,比如 HTTP_PROXY / HTTPS_PROXYKiro Remote远程 Ubuntu 上的 ~/.kiro-server 和 extensionHost远程 Ubuntu 的 Kiro Server

By ladydd
陕公网安备61011302002223号 | 陕ICP备2025083092号