iT邦幫忙

2026 iThome 鐵人賽

DAY 27
0

開場故事

如果說 ClawHub 是市場,那 skill 比較像市場裡的「可帶走的工作說明書」。

它不是 runtime 本體,也不是整個平台的骨架。
它比較像一個 agent 碰到某個情境時,可以拿來照著做的專用手冊、步驟集、或作戰方案。

第 27 天我想把這件事講清楚:

skill 在 ClawHub 裡到底扮演什麼角色?它只是可安裝內容,還是會真的影響 OpenClaw 怎麼工作?

答案是後者。
skill 不只是資料,它會進到 discovery、readiness、install、doctor 這幾條路徑,最後變成 agent 能不能用、該不該用、怎麼用的判準。

今天要解的問題

  • skill 在 OpenClaw 的生命週期裡位於哪一層?
  • skill 為什麼需要 discovery / status / doctor 這種配套?
  • skill 跟 ClawHub 的 install / update 是怎麼串起來的?
  • skill 的「可用」不是單一條件,而是哪些條件的合成?
  • 為什麼 skill 不是單純裝好就好,而是要能被檢查、被追蹤、被修復?

架構總覽

我會用三個角度看 skill:

  1. 發現:系統先知道有哪些 skill 存在
  2. 狀態:系統判斷它現在能不能用
  3. 交付:系統把 skill 從 ClawHub 或本地來源安裝進來

這三步看起來簡單,但其實每一步都在做不同事情。

  • discovery 解的是「這東西在不在」
  • status 解的是「這東西現在能不能用」
  • install 解的是「這東西怎麼安全地裝進來」

這也是 skill 比 plugin 更像「工作單元」的原因。
skill 的價值不是存在,而是可被 agent 消化。

原始碼節錄

先看 skill status 的核心資料結構。

📄 原始碼:src/skills/discovery/status.ts:46-77

export type SkillStatusEntry = {
  name: string;
  description: string;
  source: string;
  bundled: boolean;
  filePath: string;
  baseDir: string;
  skillKey: string;
  primaryEnv?: string;
  emoji?: string;
  homepage?: string;
  always: boolean;
  disabled: boolean;
  blockedByAllowlist: boolean;
  blockedByAgentFilter: boolean;
  eligible: boolean;
  platformIncompatible: boolean;
  modelVisible: boolean;
  userInvocable: boolean;
  commandVisible: boolean;
  requirements: Requirements;
  missing: Requirements;
  configChecks: RequirementConfigCheck[];
  install: SkillInstallOption[];
  clawhub?: ClawHubSkillStatusLink;
  skillCard?: LocalSkillCardStatus;
};

這一長串欄位其實很誠實。

OpenClaw 並沒有把 skill 簡化成「有」或「沒有」。
它把 skill 當成一個有條件、有來源、有狀態、有介面的實體。

再看 status 是怎麼做出來的。

📄 原始碼:src/skills/discovery/status.ts:290-296

const eligible = !disabled && !blockedByAllowlist && requirementsSatisfied;
const platformIncompatible = missing.os.length > 0;
const availableToAgent = eligible && !blockedByAgentFilter;

這三行很關鍵。

  • disabled 是配置層面關掉
  • blockedByAllowlist 是策略層面不讓進
  • requirementsSatisfied 是環境層面能不能跑
  • blockedByAgentFilter 則是「這個 agent 能不能碰」

也就是說,skill 的可用性不是一刀切,而是多層過濾後的結果。

再看它怎麼決定 install 選項。

📄 原始碼:src/skills/discovery/status.ts:139-156

function selectPreferredInstallSpec(
  install: SkillInstallSpec[],
  prefs: SkillsInstallPreferences,
): { spec: SkillInstallSpec; index: number } | undefined {
  if (install.length === 0) {
    return undefined;
  }

  const brewSpec = findKind("brew");
  const nodeSpec = findKind("node");
  const goSpec = findKind("go");
  const uvSpec = findKind("uv");
  const downloadSpec = findKind("download");
  const brewAvailable = hasBinary("brew");

這裡的意思是:

  • skill 可能有很多 installer
  • 但實際上只會挑一個主要路徑先走

這個設計很像人類的現場操作。

你可以同時提供:

  • brew 安裝
  • node 安裝
  • go 安裝
  • 直接下載

但面對使用者時,通常只先講一條最合理的路徑,不會把全部選項一次倒出來。

再看 onboarding 怎麼用這些 status。

📄 原始碼:src/commands/onboard-skills.ts:150-156

const report = buildWorkspaceSkillStatus(workspaceDir, { config: cfg });
const eligible = report.skills.filter((s) => s.eligible);
const unsupportedOs = report.skills.filter(
  (s) => !s.disabled && !s.blockedByAllowlist && s.missing.os.length > 0,
);
const missing = report.skills.filter(
  (s) => !s.eligible && !s.disabled && !s.blockedByAllowlist && s.missing.os.length === 0,
);

這段就是 skill 舞台化之後的用法。

OpenClaw 不是只知道 skill 存在,而是會把它們分成:

  • 已經可以用的
  • 因為 OS 不符而不適合現在用的
  • 因為缺依賴而暫時不能用的

這很像一個管理員在看名冊,不是只看名字,而是看現況。

再看 doctor 怎麼處理。

📄 原始碼:src/commands/doctor-skills.ts:90-97

const unavailable = collectUnavailableAgentSkills(report);
if (unavailable.length === 0) {
  return params.cfg;
}

note(formatUnavailableSkillDoctorLines(unavailable).join("\n"), "Skills");
const shouldDisable = await params.prompter.confirmAutoFix({
  message: `Disable ${unavailable.length} unavailable skill${unavailable.length === 1 ? "" : "s"} in config?`,
  initialValue: false,
});

doctor 的角色很明確:

  • 找出不可用但又被配置允許的 skill
  • 提醒使用者
  • 需要時幫你把它關掉

這代表 skill 不只是安裝時的故事,而是持續維護的故事。

最後再看 skill 跟 ClawHub 的連結。

📄 原始碼:src/skills/discovery/status.ts:303-307

const clawhub =
  workspaceDir && !bundled
    ? resolveClawHubSkillStatusLinkSync({
        workspaceDir,
        skillDir: entry.skill.baseDir,
        skillKey,
        lockRead: context.clawhubLockRead,
        lockfileScope: "workspace",
      })
    : undefined;

這個 link 很有意思。
它把 skill 的現況連回 ClawHub 的 origin / lock 記錄,讓 skill 不會只是「目錄裡的一個資料夾」,而是「有來源的 install 實體」。

白話拆解

skill 在 ClawHub 裡,像是一本可更新的作戰手冊。

你不是把它裝進來就結束,而是要確認:

  1. 它現在是不是存在
  2. 它現在是不是能跑
  3. 它是不是適合這台機器
  4. 它是不是被這個 agent 允許使用
  5. 它的安裝來源能不能追溯

這也是 skill 跟 plugin 最大的不同之一。

  • plugin 偏向「系統擴充」
  • skill 偏向「工作能力」

系統擴充要處理的是 runtime、config、provider、route。
工作能力要處理的是任務是否能執行、使用者是否能理解、agent 是否知道該不該用。

所以 skill 在 ClawHub 裡扮演的不是被動檔案,而是「會被判斷、會被推薦、會被修復」的活物。

設計取捨

  • 好處是 skill 可以被細緻地描述,不會被簡化成一個布林值
  • 好處是 onboarding 和 doctor 都能共用同一套 status
  • 好處是 agent filter、allowlist、OS、依賴都能被納入判斷
  • 代價是 status 結構比較大,不好一眼看懂
  • 代價是 skill 的概念會比一般「tool」更重,因為它兼顧安裝、可用性與治理
  • 代價是維護者必須同時理解 discovery、install、doctor、origin 這幾條路

但這個設計很符合真實世界。
因為 skill 不是展示品,它會活在長期系統裡。

今天的結論

  • skill 在 OpenClaw 裡不是靜態資源,而是可治理的工作能力
  • skill 的可用性由 disabled、allowlist、requirements、agent filter 等多層條件共同決定
  • onboarding 會根據 status 給出安裝建議,doctor 會根據 status 做修復
  • ClawHub 的 origin / lock 讓 skill 可以被追蹤、更新與稽核
  • skill 的角色不是「裝好就好」,而是「能被安全地持續使用」

上一篇
第 26 天:ClawHub 平台是什麼,先看 skill 和 plugin 的舞台
系列文
30 天走進 OpenClaw:一個 AI Agent 的誕生、掙扎與進化 共 27 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言