> ## Documentation Index
> Fetch the complete documentation index at: https://felimet-hub.jmcores.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 04-5 Subagent：用途、格式、製作、與 Skill 如何配合

> Subagent 是有獨立 context window 的子任務執行容器，可指定模型、收斂工具權限、必要時用 git worktree 物理隔離，最終只把結論回傳主流程。本單元教你從零寫一個可用的 Subagent，並釐清它與 Skill 的分工。

export const ArchFlow = ({nodes = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    flow: "Data flow",
    hint: "Click any stage to see what it does",
    stage: "Stage"
  } : {
    flow: "資料流",
    hint: "點任一階段看它做什麼",
    stage: "階段"
  };
  const safe = Array.isArray(nodes) ? nodes : [];
  const [active, setActive] = useState(0);
  if (safe.length === 0) return null;
  const idx = Math.min(active, safe.length - 1);
  const current = safe[idx];
  const css = `
  .af-root{--af-bg:#FAF8F3;--af-surface:rgba(191,117,81,0.06);--af-surface2:rgba(0,0,0,0.025);--af-border:rgba(0,0,0,0.09);--af-text:#2b2722;--af-dim:#6f6a62;--af-faint:#8a8378;--af-rail:rgba(0,0,0,0.12);--af-accent:#bf7551;border:1px solid var(--af-border);border-radius:14px;background:var(--af-bg);color:var(--af-text);overflow:hidden;}
  .dark .af-root{--af-bg:#1b1a18;--af-surface:rgba(207,138,104,0.09);--af-surface2:rgba(255,255,255,0.03);--af-border:rgba(255,255,255,0.08);--af-text:#e7e3da;--af-dim:#a8a299;--af-faint:#8a8378;--af-rail:rgba(255,255,255,0.13);--af-accent:#cf8a68;}
  .af-head{padding:13px 18px 11px;display:flex;align-items:center;gap:9px;flex-wrap:wrap;border-bottom:1px solid var(--af-border);}
  .af-head-ic{color:var(--af-accent);flex-shrink:0;}
  .af-head-t{font-size:12px;font-weight:700;letter-spacing:.6px;color:var(--af-dim);text-transform:uppercase;}
  .af-head-h{font-size:12px;color:var(--af-faint);}
  .af-grid{display:flex;gap:0;align-items:stretch;}
  .af-list{flex:1 1 0;min-width:0;padding:12px 12px 16px;}
  .af-node{display:flex;align-items:stretch;gap:10px;width:100%;text-align:left;background:transparent;border:none;cursor:pointer;padding:0;color:inherit;font:inherit;-webkit-tap-highlight-color:transparent;}
  .af-railcol{width:22px;flex-shrink:0;display:flex;flex-direction:column;align-items:center;}
  .af-dot{width:9px;height:9px;border-radius:50%;margin-top:14px;background:var(--af-faint);opacity:.5;flex-shrink:0;transition:background .15s,box-shadow .15s,opacity .15s;}
  .af-line{width:2px;flex:1 1 0;background:var(--af-rail);min-height:10px;}
  .af-body{flex:1 1 0;min-width:0;padding:9px 12px;margin:2px 0;border-radius:9px;border:1px solid transparent;transition:background .15s,border-color .15s;}
  .af-node:hover .af-body{background:var(--af-surface2);}
  .af-node-on .af-body{background:var(--af-surface);border-color:rgba(191,117,81,.30);}
  .af-node-on .af-dot{background:var(--af-accent);opacity:1;box-shadow:0 0 0 4px rgba(191,117,81,.15);}
  .af-label{font-size:14.5px;font-weight:550;line-height:1.45;}
  .af-node-on .af-label{color:var(--af-accent);}
  .af-detail{width:300px;flex-shrink:0;border-left:1px solid var(--af-border);padding:16px 18px;background:var(--af-surface2);}
  .af-detail-k{font-size:11px;font-weight:700;letter-spacing:.5px;text-transform:uppercase;color:var(--af-accent);margin-bottom:7px;}
  .af-detail-l{font-size:16px;font-weight:600;margin-bottom:9px;line-height:1.35;}
  .af-detail-d{font-size:13.5px;line-height:1.65;color:var(--af-dim);}
  @media (max-width:640px){.af-grid{flex-direction:column;}.af-detail{width:auto;border-left:none;border-top:1px solid var(--af-border);}}
  `;
  return <div className="af-root">
      <style>{css}</style>
      <div className="af-head">
        <svg className="af-head-ic" xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect width="8" height="8" x="3" y="3" rx="2" /><path d="M7 11v4a2 2 0 0 0 2 2h4" /><rect width="8" height="8" x="13" y="13" rx="2" /></svg>
        <span className="af-head-t">{t.flow}</span>
        <span className="af-head-h">{t.hint}</span>
      </div>
      <div className="af-grid">
        <div className="af-list">
          {safe.map((n, i) => <button key={i} type="button" className={"af-node" + (i === idx ? " af-node-on" : "")} onClick={() => setActive(i)} onMouseEnter={() => setActive(i)}>
              <div className="af-railcol">
                <div className="af-dot" />
                {i < safe.length - 1 && <div className="af-line" />}
              </div>
              <div className="af-body">
                <div className="af-label">{n.label}</div>
              </div>
            </button>)}
        </div>
        <div className="af-detail">
          <div className="af-detail-k">{t.stage} {idx + 1} / {safe.length}</div>
          <div className="af-detail-l">{current.label}</div>
          <div className="af-detail-d">{current.detail}</div>
        </div>
      </div>
    </div>;
};

export const LearnerPrimer = ({items = [], lang = "zh"}) => {
  const t = lang === "en" ? {
    title: "Before this unit, be honest with yourself",
    sub: "If you can't answer these, that gap is exactly what this unit closes."
  } : {
    title: "讀這個單元前，先誠實面對",
    sub: "這幾題答不出來，正是這個單元要替你補的洞。"
  };
  const css = `
  .lp-root{--lp-bg:#FAF7F1;--lp-surface:rgba(191,117,81,0.05);--lp-border:rgba(0,0,0,0.09);--lp-edge:rgba(191,117,81,0.42);--lp-text:#2b2722;--lp-dim:#6f6a62;--lp-accent:#bf7551;border:1px solid var(--lp-border);border-left:3px solid var(--lp-edge);border-radius:13px;background:var(--lp-bg);color:var(--lp-text);overflow:hidden;margin:1.25rem 0;}
  .dark .lp-root{--lp-bg:#1b1a18;--lp-surface:rgba(207,138,104,0.07);--lp-border:rgba(255,255,255,0.08);--lp-edge:rgba(207,138,104,0.5);--lp-text:#e7e3da;--lp-dim:#a8a299;--lp-accent:#cf8a68;}
  .lp-head{display:flex;align-items:center;gap:9px;padding:13px 18px 11px;border-bottom:1px solid var(--lp-border);background:var(--lp-surface);}
  .lp-ic{color:var(--lp-accent);flex-shrink:0;}
  .lp-htx{display:flex;flex-direction:column;gap:1px;min-width:0;}
  .lp-title{font-size:14px;font-weight:650;line-height:1.3;letter-spacing:.01em;}
  .lp-sub{font-size:12px;color:var(--lp-dim);line-height:1.4;}
  .lp-list{list-style:none;margin:0;padding:10px 18px 14px;display:flex;flex-direction:column;gap:0;}
  .lp-item{display:flex;align-items:baseline;gap:11px;padding:7px 0;font-size:14px;line-height:1.6;border-top:1px solid var(--lp-border);}
  .lp-item:first-child{border-top:none;}
  .lp-mark{flex-shrink:0;color:var(--lp-accent);font-size:13px;font-weight:700;line-height:1.55;font-variant-numeric:tabular-nums;opacity:.85;}
  .lp-q{flex:1 1 0;min-width:0;color:var(--lp-text);}
  @media (max-width:620px){.lp-head{padding:12px 14px 10px;}.lp-list{padding:8px 14px 12px;}}
  `;
  return <div className="lp-root">
      <style>{css}</style>
      <div className="lp-head">
        <svg className="lp-ic" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><circle cx="12" cy="12" r="6" /><circle cx="12" cy="12" r="2" /></svg>
        <span className="lp-htx">
          <span className="lp-title">{t.title}</span>
          <span className="lp-sub">{t.sub}</span>
        </span>
      </div>
      <ul className="lp-list">
        {items.map((q, i) => <li className="lp-item" key={i}>
            <span className="lp-mark">{String(i + 1).padStart(2, "0")}</span>
            <span className="lp-q">{q}</span>
          </li>)}
      </ul>
    </div>;
};

<LearnerPrimer
  lang="zh"
  items={[
"Subagent 隔離 context，主對話只付摘要的成本。",
"探索任務不丟 Subagent，主對話 attention 被稀釋。",
"每個 Subagent 都用 Opus，成本線性累積。",
"唯讀任務給了 Write，等於白費隔離。",
"isolation: worktree 對唯讀是浪費。",
"你把 Subagent 當 Thread 用，它是一次性容器。",
"description 太模糊就期待自動觸發，等於期待隨機。",
"預設工具全繼承就是白名單失效。",
]}
/>

<Info>
  **這個單元解決什麼問題**

  Subagent 是擁有獨立 context window 的子任務執行容器，可指定模型、收斂工具權限、必要時用 git worktree 物理隔離，最終只把結論回傳給主流程。Claude Code v2.1 起採「兩層」結構：內建子代理（Explore、Plan、general-purpose 自動叫用）加自訂子代理（你寫 Markdown frontmatter 定義）。本單元講如何從零寫一個可用的 Subagent、如何選模型與最小權限、何時用 `isolation: worktree` 隔離平行衝突，以及釐清它與 Skill 的分工。
</Info>

## 學習目標

* [ ] 說出 Claude Code v2.1 起「兩層 Subagent」結構：內建（Explore、Plan、general-purpose）與自訂（Markdown 檔），以及各自適用的場景。
* [ ] 寫出正確的 Subagent frontmatter，含 `model`、`tools`、`permissionMode`、`skills`、`isolation` 等欄位，並說明各欄位的取值依據。
* [ ] 判斷一個子任務該用哪個模型、給哪些工具、何時需要 `isolation: worktree`、要不要預載 `skills`、是否需要 `permissionMode`。
* [ ] 說明 Subagent 與 Skill 的分工：Skill 是程序，Subagent 是執行容器；Skill 用 `context: fork` 把同一段程序丟到 Subagent 內執行，Subagent 用 `skills:` 預載程序到自己的 context。
* [ ] 能在主流程 prompt 中正確叫用 Subagent（描述觸發或 `@`-mention 顯式叫用），並取回結論。

***

## 1. Subagent 是什麼

Subagent 是一個**有獨立 context window、可指定模型與工具組合的子任務執行單元**。主對話把工作丟進去，Subagent 在自己的 context 內跑完整個任務，最後只回傳結論給主對話（截至 2026-06 依官方 subagents 章節 \[1]）。

它解決的核心問題：**把會把主對話 context 灌爆的副作用，關進獨立的 context 裡**。把 200 個檔案掃過一次找出所有 deprecated import、跑大量 grep 蒐集資訊、執行 10 分鐘的測試並回傳失敗摘要。如果這些都在主對話做，幾萬 token 就被搜尋結果灌掉，模型在後面輪次還要付 attention 成本去掃過它們。Subagent 在自己 context 內做完，把摘要丟回來，**主對話只需要付一次摘要的成本**。

兩個關鍵事實先記住：

* **Subagent 不能 spawn 另一個 Subagent**（無巢狀）。需要分工時由主對話平行叫用多個 Subagent，或用 agent team（見 [04-11](/code-agent/customization/team-vs-subagent)）。
* **Subagent 的 system prompt 是你寫的 frontmatter 後的 Markdown body**，不是 Claude Code 的完整 system prompt。你給的指令品質直接決定 Subagent 的行為。

<Tip>
  **與 01-4 上下文工程的銜接**

  [01-4](/code-agent/foundations/context-engineering) 把 context window 比作 RAM：成本隨對話線性累積。Subagent 是「把大任務關到 swap partition」，主 RAM 只看到最終結論，沒看到中間的搜尋噪音。Subagent 與 Skill 的差別在於後者是把「程序描述」放進當前 context，Subagent 是把「整個執行過程」放到隔離 context。
</Tip>

<ArchFlow
  nodes={[
{ label: "主對話", detail: "主 context window。偵測到子任務後，依 description 語意匹配或 @-mention 顯式委派給指定 Subagent。" },
{ label: "Agent 工具呼叫", detail: "主對話以 Agent tool（v2.1.63 前為 Task tool）建立 Subagent，傳入任務描述與參數。" },
{ label: "隔離 context", detail: "Subagent 取得自己的獨立 context window。frontmatter 的 model、tools、permissionMode、skills 在此生效；isolation: worktree 時另有獨立 git worktree。" },
{ label: "子任務執行", detail: "Subagent 在自己的 context 內完成全部工具呼叫、搜尋、修改。這些中間成本不污染主對話。" },
{ label: "結論回傳", detail: "Subagent 把摘要或最終結果回傳主對話。主對話只看見這份摘要，不看見中間過程。" },
]}
/>

## 2. 兩層結構：內建 + 自訂

Claude Code v2.1 起 Subagent 採「兩層」結構（\[1]）：

| 層      | 內容                                                                                                                | 觸發方式                                               | 用途           |
| ------ | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------ |
| **內建** | Explore、Plan、general-purpose，外加 statusline-setup、claude-code-guide 等輔助                                            | 模型依任務語意自動叫用，使用者不直接面對                               | 探索、規劃、複雜多步任務 |
| **自訂** | 你寫的 Markdown 檔，存於 `~/.claude/agents/`、`.claude/agents/`、plugin `agents/`、managed settings 或 `claude --agents` CLI | 模型依 `description` 自動叫用、或主對話用 `@subagent-name` 顯式叫用 | 特定領域的專用工作者   |

### 2.1 內建 Subagent

| 名稱                  | 模型            | 工具                    | 用途                     |
| ------------------- | ------------- | --------------------- | ---------------------- |
| **Explore**         | Haiku（快速、低延遲） | 唯讀工具（Write / Edit 拒絕） | 檔案搜尋、codebase 探索       |
| **Plan**            | 繼承主對話         | 唯讀工具                  | plan mode 下的研究（避免無限巢狀） |
| **general-purpose** | 繼承主對話         | 全部工具                  | 探索加修改混合的複雜多步任務         |
| statusline-setup    | Sonnet        | （輔助）                  | 跑 `/statusline` 設定狀態列時 |
| claude-code-guide   | Haiku         | （輔助）                  | 回答 Claude Code 本身功能問題  |

Explore 與 Plan 有個特殊設計：**它們跳過 `CLAUDE.md` 與父 session 的 git status**，讓研究保持快速、便宜。其他內建與全部自訂 Subagent 都會載入 `CLAUDE.md` \[1]。

叫用 Explore 時可以指定徹底程度（thoroughness level）：`quick`（目標式查詢）、`medium`（平衡）、`very thorough`（全面分析）。

### 2.2 自訂 Subagent 與內建的差別

自訂 Subagent 的本體是**一個 Markdown 檔**，包含 YAML frontmatter（設定）與 body（system prompt）。可以建在多個 scope，scope 決定它在哪些 session 可用與優先序。

最重要的設計差異：

* 內建 Subagent 跑**唯讀**任務為主（Plan、Explore），`general-purpose` 是唯一可寫的內建。
* 自訂 Subagent 完全由你決定：可唯讀、可寫、可指定模型、可預載 Skill、可用 worktree 隔離。

## 3. 放置位置與優先序

自訂 Subagent 可放在五個 scope，優先序高到低 \[1]：

| 位置                  | 範疇           | 優先序   | 建立方式                   |
| ------------------- | ------------ | ----- | ---------------------- |
| Managed settings    | 組織全機器        | 1（最高） | 管理者部署                  |
| `--agents` CLI flag | 當前 session   | 2     | 啟動 Claude Code 時傳 JSON |
| `.claude/agents/`   | 當前專案（進版控）    | 3     | 互動式或手動                 |
| `~/.claude/agents/` | 你所有專案        | 4     | 互動式或手動                 |
| Plugin `agents/` 目錄 | Plugin 啟用範圍內 | 5（最低） | 隨 plugin 安裝            |

Claude Code 會**遞迴掃描** `.claude/agents/` 與 `~/.claude/agents/`，所以可以分子目錄組織（`agents/review/`、`agents/research/`）。**目錄路徑不影響 Subagent 識別**，識別只看 frontmatter 的 `name` 欄位。同一 scope 內若兩個檔案宣告同名 `name`，Claude Code 會保留其中一個、丟掉另一個且不警告 \[1]。

Plugin 的 `agents/` 也遞迴掃描，但**子目錄會變成 scoped identifier 的一部分**：`my-plugin/agents/review/security.md` 在 plugin `my-plugin` 內識別為 `my-plugin:review:security` \[1]。

<Tip>
  **專案級 vs 使用者級怎麼選**

  專案級（`.claude/agents/`）進版控、團隊共享，適合「這個 codebase 專用」的 Subagent。使用者級（`~/.claude/agents/`）跨專案可用，適合「我個人在所有工作都會用」的 Subagent，例如個人慣用的 code review agent。
</Tip>

<Warning>
  **Plugin 內 Subagent 限制三個 frontmatter 欄位**

  安全考量，Plugin Subagent **不支援** `hooks`、`mcpServers`、`permissionMode` 欄位，會被忽略 \[1]。需要這三個時，把 agent 檔複製到 `.claude/agents/` 或 `~/.claude/agents/`。另一條路是在 `settings.json` 的 `permissions.allow` 加規則，但該規則適用整個 session，無法只限 plugin agent。
</Warning>

## 4. frontmatter 完整參考

Subagent 檔案格式（截至 2026-06，依官方 subagents 章節 \[1]）：

```markdown theme={null}
---
name: code-reviewer
description: Reviews code for quality and best practices
tools: Read, Glob, Grep
model: sonnet
---

You are a code reviewer. When invoked, analyze the code and provide
specific, actionable feedback on quality, security, and best practices.
```

只有 `name` 與 `description` 必填，其餘選填。完整欄位：

| 欄位                | 必填 | 用途                                                                                     |
| ----------------- | -- | -------------------------------------------------------------------------------------- |
| `name`            | 是  | 唯一識別（小寫字母與連字符）。`SubagentStart` hook 收到的 `agent_type` 是這個值 \[1]                         |
| `description`     | 是  | 模型判斷何時委派給這個 Subagent 的依據                                                               |
| `tools`           | 否  | Subagent 可用工具的白名單。省略時繼承全部工具。若要預載 Skill，**用 `skills` 欄位，不要把 `Skill` 列在 `tools` 內** \[1] |
| `disallowedTools` | 否  | 黑名單，從繼承或指定清單中移除                                                                        |
| `model`           | 否  | `sonnet` / `opus` / `haiku` / 完整模型 ID / `inherit`（預設）                                  |
| `permissionMode`  | 否  | `default` / `acceptEdits` / `auto` / `dontAsk` / `bypassPermissions` / `plan`          |
| `maxTurns`        | 否  | Subagent 在此輪 agentic turn 數上限                                                          |
| `skills`          | 否  | 預載 Skill 名稱清單到 Subagent context；full content 注入                                        |
| `mcpServers`      | 否  | 此 Subagent 專用的 MCP servers，可 inline 或 reference 已連線的 server                            |
| `hooks`           | 否  | 此 Subagent 生命週期專屬 hooks                                                                |
| `memory`          | 否  | 持久化記憶範圍：`user` / `project` / `local`                                                   |
| `background`      | 否  | 預設背景模式 `false`；設 `true` 一律以 background task 跑                                          |
| `effort`          | 否  | 覆寫 session effort：`low` / `medium` / `high` / `xhigh` / `max`                          |
| `isolation`       | 否  | 設 `worktree` 在暫時 git worktree 跑 Subagent                                               |
| `color`           | 否  | UI 顯示色：`red` / `blue` / `green` / `yellow` / `purple` / `orange` / `pink` / `cyan`     |
| `initialPrompt`   | 否  | 當此 agent 作為主 session 跑（`--agent` 或 `agent` 設定）時的第一句 user turn                          |

<Note>
  **v2.1.63 起 `Task` 改為 `Agent`**

  在 v2.1.63，`Task` tool 改命名為 `Agent`（\[1]）。舊的 `Task(...)` 在 settings 與 agent 定義中仍可作為 alias 用。`tools: Agent(worker, researcher)` 是新語法，限制此 Subagent 可 spawn 哪些類型。
</Note>

### 4.1 model 解析順序

當 Claude 叫用 Subagent 時，模型依下列順序解析 \[1]：

<Steps>
  <Step title="CLAUDE_CODE_SUBAGENT_MODEL 環境變數">
    最高優先序，可在啟動環境統一指定所有 Subagent 的模型，覆寫一切。
  </Step>

  <Step title="該次叫用的 model 參數">
    呼叫端在叫用時傳入的 model 參數，優先於 frontmatter。
  </Step>

  <Step title="Subagent frontmatter model">
    Subagent 檔案內宣告的 `model` 欄位。`model: inherit`（預設）等同跟主對話用同模型。
  </Step>

  <Step title="主對話的模型">
    以上都未指定時，fallback 到主對話當前使用的模型。
  </Step>
</Steps>

**重複性高、結構明確的子任務用便宜模型（Haiku），推理要求高的留給 Sonnet / Opus**。這是 Subagent 最直接的省錢切入點。

### 4.2 工具白名單 vs 黑名單

`tools` 給白名單、`disallowedTools` 給黑名單。**兩個都設時，先套黑名單，再從剩下的套白名單** \[1]。

白名單範例（嚴格限制）：

```yaml theme={null}
---
name: safe-researcher
description: Research agent with restricted capabilities
tools: Read, Grep, Glob, Bash
---
```

黑名單範例（繼承全部工具但禁用寫入）：

```yaml theme={null}
---
name: no-writes
description: Inherits every tool except file writes
disallowedTools: Write, Edit
---
```

<Warning>
  **Subagent 不可用的工具清單**

  即使列在 `tools` 內，下列工具也**不能**用於 Subagent \[1]：

  * `Agent`（Subagent 不能 spawn 另一個 Subagent）
  * `AskUserQuestion`
  * `EnterPlanMode`
  * `ExitPlanMode`（除非 `permissionMode: plan`）
  * `ScheduleWakeup`
  * `WaitForMcpServers`
</Warning>

### 4.3 限制可 spawn 的 Subagent 類型

當 agent 作為主 thread 跑（`claude --agent`），可 spawn 其他 Subagent。**用 `tools: Agent(worker, researcher)` 限定可 spawn 哪些類型** \[1]：

```yaml theme={null}
---
name: coordinator
description: Coordinates work across specialized agents
tools: Agent(worker, researcher), Read, Bash
---
```

這是白名單：只能 spawn `worker` 與 `researcher`。想允許任何類型用 `tools: Agent, Read, Bash`（不加括號）。完全不列 `Agent` 時，該 agent 不能 spawn 任何 Subagent。**這個限制只對主 thread agent 生效；Subagent 本身不能 spawn 任何 Subagent**（無巢狀），所以 `Agent(agent_type)` 在 Subagent frontmatter 內無作用 \[1]。

### 4.4 `permissionMode` 細節

| 模式                  | 行為                                       |
| ------------------- | ---------------------------------------- |
| `default`           | 標準權限檢查與 prompt                           |
| `acceptEdits`       | 自動接受工作目錄與 `additionalDirectories` 內的檔案編輯 |
| `auto`              | Auto mode：背景 classifier 審查指令與受保護目錄寫入     |
| `dontAsk`           | 自動拒絕權限 prompt（顯式允許的工具仍可用）                |
| `bypassPermissions` | 跳過所有權限 prompt                            |
| `plan`              | Plan mode（唯讀探索）                          |

<Warning>
  **父 session 模式優先**

  若主 session 用 `bypassPermissions` 或 `acceptEdits`，Subagent **不能覆寫**（\[1]）。若主 session 用 auto mode，Subagent 繼承 auto mode，frontmatter 內的 `permissionMode` 被忽略：classifier 用與主 session 相同的規則評估 Subagent 工具呼叫。

  `bypassPermissions` 跳過所有權限 prompt，包括對 `.git`、`.claude`、`.vscode`、`.idea`、`.husky`、`.cargo` 的寫入。Root 與 home 目錄的 `rm -rf` 仍會 prompt 作為電路斷路器 \[1]。
</Warning>

### 4.5 `skills`：預載 Skill 內容到 Subagent

```yaml theme={null}
---
name: api-developer
description: Implement API endpoints following team conventions
skills:
  - api-conventions
  - error-handling-patterns
---

Implement API endpoints. Follow the conventions and patterns from the preloaded skills.
```

每個列出的 Skill **完整內容**會在 Subagent 啟動時注入 context。這控制「預載哪些」，**不是**控制「可呼叫哪些」：沒列的 Skill，Subagent 還是可以透過 Skill tool 在執行中發現並叫用 project / user / plugin Skill \[1]。

預載有反向限制：**不能預載設了 `disable-model-invocation: true` 的 Skill**，因為預載與模型可叫用共用同一組 Skill 集。若列出的 Skill 缺失或停用，Claude Code 跳過並在 debug log 寫 warning \[1]。

<Tip>
  **Subagent 預載 Skill vs Skill 跑在 Subagent**

  這是同一底層機制的兩種視角（\[1]）：

  * **Subagent frontmatter `skills: [...]`**：Subagent 控 system prompt，把 Skill 內容載入。
  * **Skill frontmatter `context: fork` + `agent: ...`**：Skill 內容變成指定 agent 的 task prompt，agent 在乾淨 context 跑。

  兩者底層是一個東西，只是寫法反過來。
</Tip>

### 4.6 `isolation: worktree`

`isolation: worktree` 讓 Subagent 在**暫時的 git worktree** 內跑，給它 repo 的一個隔離複本（從預設分支 fork，不是父 session 的 `HEAD`）\[1]。

```yaml theme={null}
---
name: refactor-agent
description: Refactor a module in isolation
isolation: worktree
tools: Read, Edit, Write, Bash
---
```

worktree 行為：

* Subagent 啟動時自動建一個暫時 worktree。
* Subagent 的寫入只發生在這個 worktree，不影響主工作目錄。
* **若 Subagent 沒做任何改動，worktree 自動清除** \[1]。
* 若有改動，你需要決定合併、保留、丟棄。

<Warning>
  **`cd` 在 Subagent 內不持久**

  Subagent 內的 `cd` 不會跨 Bash / PowerShell 工具呼叫保留，也不影響主 session 的工作目錄 \[1]。需要隔離工作目錄請用 `isolation: worktree`。
</Warning>

## 5. 唯讀 vs 可寫、worktree 隔離何時用

判準只有一個：**這個 Subagent 會不會改檔案或外部狀態？**

| 類型                | 任務                          | 工具                                           | worktree                       |
| ----------------- | --------------------------- | -------------------------------------------- | ------------------------------ |
| 唯讀                | 搜尋、review、summarize、analyze | `Read`、`Glob`、`Grep`，**禁用** `Write` / `Edit` | 不需要                            |
| 可寫（無平行衝突）         | 重構、文件生成、單檔修改                | 包含 `Write` / `Edit`                          | 不需要（同一 Subagent 自己）            |
| 可寫（多 Subagent 平行） | 多個 Subagent 同時改不同檔案         | 包含 `Write` / `Edit`                          | **需要**，每個 Subagent 各自 worktree |
| 不可信輸入             | 處理外部文件、URL、PR 內容            | 最小集                                          | 強烈建議（隔離爆炸半徑）                   |

worktree 操作模式：

```bash theme={null}
# 1. 為每個 Subagent 建獨立 worktree
git worktree add ../agent-A -b agent-A-branch
git worktree add ../agent-B -b agent-B-branch

# 2. Subagent 各自在 ../agent-A、../agent-B 內作業

# 3. 結束後合併或比較
git diff main agent-A-branch
git merge agent-A-branch
```

<Note>
  **判斷清單**

  1. 這個 Subagent 會寫檔或動外部狀態嗎？否，不需要 worktree。
  2. 同一批平行跑的 Subagent 會寫入重疊路徑嗎？是，需要 worktree。
  3. Subagent 會處理不可信內容（外部文件、隨機 PR）嗎？是，worktree 作為爆炸半徑隔離。
</Note>

## 6. 與 Skill 的配合：程序 vs 容器

這是 Subagent 與 Skill 最容易混淆的地方。澄清它們的分工：

| 維度   | Skill                       | Subagent                           |
| ---- | --------------------------- | ---------------------------------- |
| 本質   | 程序定義（步驟、判準、格式）              | 執行容器（context、模型、工具、隔離）             |
| 載入時機 | 模型判斷語意相關時叫用                 | 模型依 `description` 委派，或 `@`-mention |
| 誰執行  | 當前對話的 Claude（主對話或 Subagent） | Subagent 自己                        |
| 可重入  | 同一個 Skill 在不同對話重複用          | 同一個 Subagent 定義可被多個 session 委派     |
| 適合   | 「這個流程要這樣跑」                  | 「這個任務丟到獨立 context 跑」               |

### 6.1 三種典型配合

**只用 Skill**：程序在主對話跑，沒隔離需求。例：「依這個寫作風格重寫文件」。

**只用 Subagent**：子任務程序簡單到寫在 Subagent 描述裡即可，沒複用需求。例：「搜尋 codebase 找所有用到 deprecated API 的地方」。

**Skill + Subagent 搭配**：兩條路徑。

路徑 A：Subagent 預載 Skill（`skills: [...]`）

```yaml theme={null}
---
name: code-reviewer
description: Reviews code for team conventions
skills:
  - api-conventions
  - testing-standards
---

You are a code reviewer. Apply the preloaded conventions and standards.
```

路徑 B：Skill 用 `context: fork` 丟到 Subagent

```yaml theme={null}
# SKILL.md in a Skill directory
---
description: 研究某個主題並回傳引用清單
context: fork
agent: Explore
---

Research $ARGUMENTS thoroughly:
1. Use Glob and Grep to find relevant files
2. Read and analyze
3. Summarize with specific file references
```

兩條路徑底層是同一個機制，差別是「誰定義程序、誰定義容器」\[1]。

<Warning>
  **`context: fork` 需要 Skill 內含明確任務**

  Skill 內容若只是「遵守這些 API 慣例」（規範式、沒有明確任務），`context: fork` 會讓 Subagent 收到「慣例」但沒「要做什麼」，回傳空結果。`context: fork` 適合有明確步驟的程序型 Skill \[1]。
</Warning>

## 7. 叫用 Subagent

### 7.1 自動叫用

Claude 讀 Subagent 的 `description`，當任務語意匹配時自動委派。寫好 `description` 是觸發的關鍵。

<Note>
  **觸發描述寫法對照**

  太泛，會誤觸：

  ```yaml theme={null}
  description: 幫我處理各種任務
  ```

  太窄，會漏觸：

  ```yaml theme={null}
  description: 幫我把週末研究日誌轉成 markdown
  ```

  剛好：

  ```yaml theme={null}
  description: 在 Python codebase 找型別錯誤、未使用 import、與公開函式缺 docstring 的問題。Use when reviewing Python files or after a refactor.
  ```
</Note>

### 7.2 顯式叫用：`@`-mention

主對話用 `@subagent-name` 顯式叫用。例：「用 `@code-reviewer` 看看這個 PR 改了什麼」。

Plugin 內的 Subagent 用 namespaced 識別：`@my-plugin:review:security` \[1]。

### 7.3 背景模式

`background: true` 讓 Subagent 一律以 background task 跑，可與主對話並行；Subagent 完成時 Claude Code 會通知主對話 \[1]。

## 8. 工具對照

各家工具對「獨立 context 子代理」的對應機制差異顯著（截至 2026-06）：

| 概念             | Anthropic Claude（主範本）                                                     | OpenAI Codex                                                                                                                                    | Google Antigravity                | GitHub Copilot CLI | Cursor（短提）                     |
| -------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------------ | ------------------------------ |
| 自訂 Subagent 格式 | Markdown frontmatter 檔                                                    | `~/.codex/agents/*.toml`（個人）/ `.codex/agents/*.toml`（專案）加 `config.toml` 的 `[agents]` 全域參數，必填 `name`/`description`/`developer_instructions` \[6] | `.agents/agents/*.md` frontmatter | 不適用主流程（CLI 為單代理）   | `.cursor/agents/` 與內建 Subagent |
| 內建子代理          | Explore（Haiku 唯讀）、Plan（繼承 唯讀）、general-purpose（繼承 全工具）                     | 系統層 provider agent                                                                                                                              | 系統層 sub-agent                     | 不適用                | Composer、Background Agent 等    |
| 指定模型           | `model: sonnet/opus/haiku/inherit/<id>`                                   | 設定式                                                                                                                                             | 設定式                               | 設定式                | 設定式                            |
| 工具收斂           | `tools` 白名單 + `disallowedTools` 黑名單                                       | 設定式                                                                                                                                             | 設定式                               | 工具白名單 / 黑名單        | 設定式                            |
| 隔離機制           | `isolation: worktree`                                                     | 環境層                                                                                                                                             | 環境層                               | 環境層                | 環境層                            |
| 預載 Skill       | `skills: [...]` frontmatter                                               | 不適用                                                                                                                                             | 設定式                               | 不適用                | 不適用                            |
| 權限模式           | `permissionMode: default/acceptEdits/auto/dontAsk/bypassPermissions/plan` | 設定式                                                                                                                                             | 設定式                               | 設定式                | 設定式                            |
| 持久化記憶          | `memory: user/project/local`                                              | 不適用                                                                                                                                             | Memory 機制                         | 不適用                | 不適用                            |
| 顯式叫用           | `@subagent-name`                                                          | `/agent` 指令                                                                                                                                     | 設定式                               | 設定式                | `@agent`                       |

<Note>
  **命名澄清**

  * **Claude Code 的 Subagent 工具名**：v2.1.63 起從 `Task` 改為 `Agent`（舊 `Task(...)` 仍可作 alias）（\[1]）。`tools: Agent(worker, researcher)` 限制可 spawn 類型是 v2.1 後的標準寫法。
  * **OpenAI Codex** 的 Subagent 已對官方查證 \[6]：`config.toml` 的 `[agents]` 定全域參數（`max_threads` / `max_depth` / `job_max_runtime_seconds`），各角色為 `~/.codex/agents/*.toml`（個人）或 `.codex/agents/*.toml`（專案）。它沒有 `~/.codex/prompts/*.md`，也沒有 `codex.md`，持久指令走 `AGENTS.md`。**Antigravity、Cursor** 的對應機制演進快，採用前以各家當前官方文件為準。
  * **GitHub Copilot CLI** 截至 2026-06 為單代理模型，不在 Subagent 概念下提供一等公民機制；雲端 coding agent 是另一條路線。
  * **Cursor 為第三方 IDE**（Anysphere），本 Playbook 僅短提一欄。
</Note>

## 9. 動手做

<Note>
  **30 分鐘練習**

  1. **寫唯讀 Subagent**：建 `~/.claude/agents/api-explorer.md`，frontmatter 給 `tools: Read, Glob, Grep`、`model: haiku`，body 寫「掃描 `src/api/` 下的端點、回報每個的 method、路徑、認證需求」。用 `/agents` 確認它出現在 Library。
  2. **寫可寫 Subagent**：建 `.claude/agents/doc-fixer.md`，frontmatter 給 `tools: Read, Edit, Grep`、`model: haiku`、`permissionMode: acceptEdits`，body 寫「把所有 `.md` 內的 `TODO` 換成連結到 issues 的錨點」。在同一專案下用 `@doc-fixer` 顯式叫用。
  3. **隔離測試**：用 `isolation: worktree` 寫一個 Subagent，讓它改一個檔；觀察 worktree 自動建立、Subagent 改完後 worktree 還在、與主工作目錄的差異。沒改動時應自動清除。
  4. **Skill + Subagent**：寫一個 Skill 用 `context: fork` 與 `agent: Explore`；叫用 Skill 觀察它在獨立 context 跑，結果摘要回傳主對話。
  5. **預載 Skill**：寫一個 Subagent 用 `skills: [api-conventions]`，啟動 session 後觀察 Skill 內容是否已在 Subagent context（從 Subagent 內問「你看到 api-conventions 嗎」驗證）。
</Note>

## 10. 常見誤區

<Warning>
  **反模式清單**

  * **每個 Subagent 都用最強模型**：重複性高的子任務用 Haiku 系列即可；Opus 留給真正需要深度推理的場景，否則成本線性累積。
  * **給 Subagent 過寬工具權限**：唯讀任務給了 `Write` 和 `Bash`，等於白費隔離的意義，也增加供應鏈風險。預設用白名單列最小集。
  * **把 Skill 程序寫進 Subagent 描述卻沒複用需求**：若只用一次，不必強行拆成 Skill，直接在 Subagent body 寫明程序更直接。
  * **`isolation: worktree` 對唯讀任務**：沒寫入就不需要 worktree；加了只是浪費磁碟與建置時間。
  * **沒設計 `description` 就期待模型觸發**：模型觸發靠語意比對，描述太模糊、太技術、太空泛都會漏觸。
  * **把 Subagent 當 Thread 來用**：Subagent 是一次性容器，任務結束就消滅。需要持續對話、可定址代理，請用 agent team（見 [04-11](/code-agent/customization/team-vs-subagent)）。
  * **在 Subagent body 內放敏感資訊**：Subagent body 進 context、若進版控則對所有人可見。機密應用環境變數或動態注入。
</Warning>

## 自我檢核

<Check>
  **自我檢核**

  1. 你能說出 Claude Code v2.1 Subagent 的兩層結構，以及內建三個（Explore、Plan、general-purpose）各自的模型與工具預設嗎？
  2. 你能寫出一個 frontmatter 完整、`description` 觸發精準的 Subagent 嗎？
  3. 你能對手邊一個真實子任務說清楚：它的 `model` 選擇依據、`tools` 最小集、是否需要 `isolation: worktree`、`permissionMode` 該不該用哪個，以及它有沒有用 `skills` 預載 Skill？
  4. 你能分清 Subagent 與 Skill 的關係嗎？什麼時候該只用其中一個、什麼時候該搭配？
</Check>

## 來源與延伸閱讀

事實主張依官方文件，快變動項標註截至 2026-05。

<div className="references">
  * \[1] Anthropic, "Create custom subagents," code.claude.com, 2026. （含兩層結構、frontmatter 完整參考、`isolation: worktree`、`skills` 預載、`memory` 持久化、`v2.1.63` `Task` 改為 `Agent` 命名） [https://code.claude.com/docs/en/subagents](https://code.claude.com/docs/en/subagents) （截至 2026-06）

  * \[2] Anthropic, "Extend Claude with skills," code.claude.com, 2026. （含 Skill 與 Subagent 透過 `context: fork` 與 `skills:` 預載的兩條配合路徑） [https://code.claude.com/docs/en/skills](https://code.claude.com/docs/en/skills) （截至 2026-06）

  * \[3] Anthropic, "Plugins reference," code.claude.com, 2026. （Plugin Subagent 限制 `hooks` / `mcpServers` / `permissionMode` 三欄位） [https://code.claude.com/docs/en/plugins-reference](https://code.claude.com/docs/en/plugins-reference) （截至 2026-06）

  * \[4] Anthropic, "Worktrees," code.claude.com, 2026. （`isolation: worktree` 機制與 base branch 預設行為） [https://code.claude.com/docs/en/worktrees](https://code.claude.com/docs/en/worktrees) （截至 2026-06）

  * \[5] Agent Skills Open Standard, "Agent Skills," 2026. （Skill 與 Subagent 互通的開放標準） [https://agentskills.io](https://agentskills.io) （截至 2026-06）

  * \[6] OpenAI, "Subagents," developers.openai.com/codex, 2026. （`config.toml` 的 `[agents]` 全域參數 `max_threads` / `max_depth` / `job_max_runtime_seconds`；獨立 agent TOML 於 `~/.codex/agents/`（個人）與 `.codex/agents/`（專案），必填 `name` / `description` / `developer_instructions`，選填 `model` / `sandbox_mode` / `mcp_servers`；無 `prompts/*.md` 與 `codex.md`，持久指令用 `AGENTS.md`） [https://developers.openai.com/codex/subagents](https://developers.openai.com/codex/subagents) （截至 2026-06）
</div>

* `CLAUDE.md` 與 rules 見 [04-1 CLAUDE.md 與記憶檔](/code-agent/customization/claude-md-memory) 與 [04-2 rules](/code-agent/customization/rules)。
* Skill 與 frontmatter 見 [04-4 Skill](/code-agent/customization/skills)。
* Hook 確定性強制見 [04-6 Hooks](/code-agent/customization/hooks)。
* 上下文隔離概念見 [01-4 上下文工程](/code-agent/foundations/context-engineering)。
* Agent Teams 與多代理編排見 [04-11 Agent Teams 與 Sub Agent](/code-agent/customization/team-vs-subagent)。
