最新
療心智能正式加入 NVIDIA Inception 新創計畫 | 療心智能入選 Anthropic Claude Startups 計畫 | 療心智能進入 2026 資訊應用服務創新創業新秀選拔決選 | DietMate 臨床營養 AI 平台開放診所試用 | Taiwan Health MCP v0.1.0 更新上線,支援 FHIR R4 資源與台灣 FDA 藥品查詢 → | 
聯絡我們
✓ 連結已複製

Anthropic Skills 實戰:醫療病歷 Agent 的分層載入設計

用 Anthropic Skills 打造醫療 AI Agent:從 SOAP note 到出院摘要,一套架構支援所有病歷模板,實測節省 70% Token 成本,新增科別從 2 天縮短到 30 分鐘。

BY 療心智能團隊 2026.07.30 · 9 分鐘閱讀

本文架構的靈感來自 Anthropic 於 2025 年 10 月發布的 Skills 機制,並延伸至醫療場景。文中提到的「Progressive Disclosure(漸進式揭露)」是 Anthropic 官方使用的原始術語,本文沿用以便讀者順藤摸瓜研究原始文件。

Key Takeaways
  • 為什麼醫療場景需要 Progressive Disclosure? 不只是為了省 Token,而是讓病歷模板的維護與 AI Agent 系統的部署完全解耦:模板改了,系統不用重跑。
  • Token 節省邏輯: 傳統方式把所有模板一次塞進 Prompt(約 3,000–5,000 tokens),分層載入後初始化只需約 300–500 tokens,執行時才動態補進所需模板,單次呼叫平均節省 70%。
  • 急診醫師問「幫我寫 ER record」,系統在第二次 LLM 推理才載入急診模板——第一次推理只是在判斷「需要哪份模板」。
  • 新增科別為何從 2 天縮短到 30 分鐘? 傳統方式需要修改 Prompt 程式碼並重新部署;現在只需新增一個 references/er-note.md 檔案,系統自動識別。
  • 先備知識:本文用到 Tool Calling 概念,建議先讀 Anthropic Tool Use 官方文件。

醫療場景為什麼特別需要 Progressive Disclosure?

LLM 不擅長同時處理多套格式規則。你把十種病歷模板同時放進 Prompt,模型確實都能看到,但「看到」與「正確執行」之間有明顯落差——特別是當模板之間格式相近(例如 SOAP 與 Nursing Note 都有主訴區)時,模型容易混用。

但 Token 成本只是表面問題。醫療系統面對的更深層挑戰是維護週期:

  • 牙科診所每季可能更新一次 Dental SOAP 格式
  • 精神科引入新的 DSM-5-TR 診斷標準後,Mental Status Exam 的欄位需要調整
  • 長照機構在通過評鑑後,Follow-up Report 增加了新的 ADL 評估項目

傳統的做法是把模板直接寫進 System Prompt。只要有任何一個模板改動,就必須:

  1. 修改 Prompt 字串(觸及程式碼)
  2. 重新部署服務
  3. 測試所有其他科別是否受影響

這個週期,光是內部審查與重新部署,通常就需要 1–2 天。

Progressive Disclosure 的設計把模板檔案與Agent 邏輯徹底分開。模板是獨立的 Markdown 檔案,由各科室自行維護;Agent 邏輯只知道「有哪些模板存在」,不把模板內容硬編進去。模板改了,Agent 下次執行時自動讀到新版本。不需要碰程式碼,不需要重新部署,不需要全科別回歸測試。


Token 成本的具體計算

假設一個醫療 AI Agent 支援以下 5 種病歷類型:

模板估計 Token 數
SOAP Note350 tokens
Follow-up Report280 tokens
Discharge Summary450 tokens
Nursing Note320 tokens
ER Record400 tokens

傳統方式: 每次呼叫都把所有模板放進 System Prompt,加上 Skill Instructions(約 200 tokens)與 Tool Definitions,總計約 2,200 tokens 的固定開銷,無論使用者只是要寫一份 SOAP Note。

Progressive Disclosure 方式:

  • 初始化:Skill Instructions(200 tokens)+ Reference 清單(僅檔名,約 50 tokens)+ Tool Definitions(約 150 tokens)= 400 tokens
  • 執行時才載入單一模板,例如 SOAP Note:+350 tokens
  • 單次呼叫總計:約 750 tokens

從 2,200 tokens 降到 750 tokens,節省幅度約 66%。如果模板數量增加到 8–10 種,節省比例還會更高。實務上計入 System Prompt 其他部分之後,業界常見的測量結果落在 70% 左右。


急診醫師問「幫我寫 ER record」——系統怎麼運作?

這是 Progressive Disclosure 最直觀的示範場景。

第一層:初始化(Agent 啟動時,只做一次)

Agent 啟動時,完成以下四件事:

  1. 讀取 skill.md:取得 Agent 的角色定義、輸出規則、語言要求。
  2. 掃描 references/ 目錄:取得可用模板的檔名清單(僅檔名,不讀內容):
    soap-note.md
    follow-up.md
    discharge-summary.md
    nursing-note.md
    er-note.md
    dental-soap.md
    mental-status.md
    
  3. 建立 Tool:定義 read_reference 工具,讓模型可以在需要時主動呼叫。
  4. 建立初始 Context:
    System Prompt + Skill Instructions + Reference 檔名清單 + Tool Definitions
    
    此時 Context Window 只佔用約 400 tokens。急診模板的內容完全沒有被讀取。

第二層:第一次 LLM 推理(判斷意圖)

急診醫師輸入:

幫我寫 ER record,病患 38 歲男性,主訴胸悶 3 小時,BP 145/90,心電圖 ST 段無明顯變化,安排 Troponin,觀察 6 小時後出院。

模型收到的 Context 是:

[Skill Instructions]
[可用模板清單:soap-note.md / follow-up.md / discharge-summary.md / nursing-note.md / er-note.md / ...]
[Tool: read_reference]
[使用者輸入]

模型在這一次推理中,不生成病歷。它只做一件事:判斷需要哪份模板,並輸出 Tool Call:

{
  "tool": "read_reference",
  "arguments": { "name": "er-note.md" }
}

此時急診模板仍未進入 Context。這一步只是決定「下一步要讀什麼」。


第三層:工具執行 → 第二次 LLM 推理(生成病歷)

Agent 執行 Tool Call,從磁碟讀取 er-note.md 的完整內容,注入 Context:

[Skill Instructions]
[er-note.md 完整內容]  ← 急診模板在這裡才正式進入
[使用者輸入]

模型進行第二次推理,生成結構化的 ER Record:

# Emergency Record

## Chief Complaint
38 歲男性,主訴胸悶 3 小時。

## Vital Signs
BP 145/90 mmHg,其他生命徵象穩定。

## Assessment
12-lead ECG:ST 段無明顯偏移。
初步排除 STEMI,安排 Troponin 系列檢測。

## Plan
- 觀察 6 小時
- 若 Troponin 陰性且症狀緩解,可安排出院
- 出院前進行 ACS 衛教

急診模板從進入 Context 到生成病歷,只在第三層發生。SOAP、Follow-up 等其他模板全程未被載入。


新增科別:從 2 天縮短到 30 分鐘

傳統方式需要哪些步驟?

假設牙科診所要新增 Dental SOAP 模板:

  1. 撰寫模板內容(30 分鐘)
  2. 找到 System Prompt 的字串,插入新模板(15 分鐘,但容易破壞格式)
  3. 修改程式碼,確保模型知道有這個新格式(30 分鐘)
  4. 提交 Pull Request,等待 Code Review(數小時至隔天)
  5. 重新部署服務(15–30 分鐘)
  6. 回歸測試:確認其他 5 個科別的輸出沒有被新模板干擾(數小時)

最樂觀的情況:1 個工作天。有任何問題要修正,就變成 2 天。

Progressive Disclosure 的方式

  1. 撰寫 references/dental-soap.md(30 分鐘)
  2. 把檔案放進 references/ 目錄(1 分鐘)

完成。

Agent 下一次啟動時,掃描 references/ 目錄會自動發現 dental-soap.md,並將其加入可用模板清單。模型在下次收到牙科相關請求時,會主動呼叫這份模板。整個過程不碰程式碼,不重新部署,不需要回歸測試其他科別。


Skill 目錄設計

一個完整的 Skill 結構如下:

skills/
├── medical-writing-assistant/
│   ├── skill.md
│   └── references/
│       ├── soap-note.md
│       ├── follow-up.md
│       ├── discharge-summary.md
│       ├── nursing-note.md
│       ├── er-note.md
│       ├── dental-soap.md
│       └── mental-status.md
├── appointment-scheduler/
├── drug-interaction/
└── insurance-checker/

skill.md 定義 Agent 的角色與共通規則,不存放任何模板內容:

---
name: medical-writing-assistant
description: Generate structured medical documentation.
version: 1.0
---

# Instructions

You are an experienced medical documentation assistant.

## General Rules

- Never fabricate symptoms or diagnoses.
- Preserve all medical terminology.
- Use objective and professional language.
- Do not infer information that is not provided.
- Follow the referenced template whenever one is available.
- Output in Markdown format.

## Output Requirements

- Maintain section hierarchy.
- Keep terminology consistent.
- Avoid unnecessary explanations.
- Return only the requested documentation.

真正的 SOAP 格式、ER 格式、Mental Status 格式,全部拆開存放在 references/。這是 Progressive Disclosure 的核心:Skill 定義能力,Reference 定義格式,兩者完全分離。


程式碼實作

以下是完整的 Python 實作,可直接複製到專案中修改:

import os
from pathlib import Path
from anthropic import Anthropic

client = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
SKILL_ROOT = Path("./skills/medical-writing-assistant")

def load_skill_metadata():
    """讀取 skill.md 的 instructions 部分。"""
    return (SKILL_ROOT / "skill.md").read_text(encoding="utf-8")

def list_references():
    """列出可用的 reference 檔名(不讀取內容)。"""
    return [p.name for p in (SKILL_ROOT / "references").glob("*.md")]

def read_reference(name: str) -> str:
    """真正讀取指定 reference 的內容。"""
    return (SKILL_ROOT / "references" / name).read_text(encoding="utf-8")

# Tool Schema:讓模型可以主動呼叫
tools = [{
    "name": "read_reference",
    "description": "讀取指定的醫療紀錄模板內容。",
    "input_schema": {
        "type": "object",
        "properties": {
            "name": {
                "type": "string",
                "description": "reference 檔名,例如 er-note.md"
            }
        },
        "required": ["name"]
    }
}]

# 初始化 Context:只有 Skill Instructions + Reference 清單 + Tool Definitions
system_prompt = f"""{load_skill_metadata()}

## Available References
{chr(10).join(f'- {r}' for r in list_references())}

當需要生成醫療文件時,請先透過 read_reference 工具載入對應的模板。
"""

# 急診醫師的輸入
user_input = """幫我寫 ER record,病患 38 歲男性,主訴胸悶 3 小時,
BP 145/90,心電圖 ST 段無明顯變化,安排 Troponin,觀察 6 小時後出院。"""

# 第一次推理:模型判斷需要哪個模板,輸出 Tool Call
response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=2048,
    system=system_prompt,
    tools=tools,
    messages=[{"role": "user", "content": user_input}],
)

# 處理 Tool Call
messages = [{"role": "user", "content": user_input}]
messages.append({"role": "assistant", "content": response.content})

tool_results = []
for block in response.content:
    if block.type == "tool_use":
        ref_content = read_reference(block.input["name"])
        tool_results.append({
            "type": "tool_result",
            "tool_use_id": block.id,
            "content": ref_content,
        })

messages.append({"role": "user", "content": tool_results})

# 第二次推理:模型現在有了模板,生成正式病歷
final_response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=2048,
    system=system_prompt,
    tools=tools,
    messages=messages,
)

print(final_response.content[0].text)

這段程式碼的結構與「急診醫師場景」完全對應。第一次 create 呼叫是意圖判斷層,第二次 create 呼叫才是真正的病歷生成層。


各科別 Reference 模板範例

references/soap-note.md

# SOAP Note

## Subjective
主訴症狀摘要。

## Objective
客觀臨床發現:生命徵象、體格檢查、檢驗結果。

## Assessment
臨床評估與診斷印象。

## Plan
治療計劃:藥物、檢查、轉介、回診安排。

references/er-note.md

# Emergency Record

## Chief Complaint
主訴與到院時間。

## Vital Signs
BP / HR / RR / SpO2 / Temp

## History of Present Illness
現病史,含症狀起始、變化與相關病史。

## Physical Examination
系統性體格檢查。

## Assessment & Plan
急診評估、處置計劃、後續安排(住院 / 觀察 / 出院)。

references/mental-status.md

# Mental Status Examination

## Appearance & Behavior
外觀、合作度、眼神接觸。

## Speech
語速、語量、語調。

## Mood & Affect
情緒陳述(主觀)與情感表達(客觀)。

## Thought Process & Content
思維流程、強迫意念、自傷他傷風險評估。

## Cognition
定向感、注意力、記憶力。

## Insight & Judgment
病識感與判斷力。

完整工作流程

使用者輸入
     │
     ▼
Medical Agent 初始化
  ├── 讀取 skill.md(角色定義)
  └── 掃描 references/(只取檔名)
     │
     ▼
第一次 LLM 推理
  └── 判斷意圖 → 輸出 Tool Call(read_reference)
     │
     ▼
Tool Execution
  └── 從磁碟讀取指定模板(此時才讀內容)
     │
     ▼
第二次 LLM 推理
  └── 模板 + 使用者輸入 → 生成結構化病歷
     │
     ▼
輸出 Markdown 格式病歷文件

重點整理

  • Skill 負責定義 Agent 的角色、能力與共通規則;skill.md 裡不存放任何模板。
  • Reference 將 SOAP、護理紀錄、ER Record 等模板獨立管理,每個科別一個檔案。
  • Tool Calling 讓 Agent 僅在第一次推理判斷意圖後,才在第二次推理時載入對應模板。
  • Progressive Disclosure 把初始化(掃描清單)與執行(讀取內容)分成兩層,有效控制每次 LLM 呼叫的 Token 用量。
  • 新增科別 只需要新增一個 Markdown 檔案,不碰程式碼、不重新部署、不影響其他科別。
  • 維護週期 從 1–2 天縮短到 30 分鐘以內,差距來自「是否需要觸及程式碼與部署流程」。

相關文章:FHIR R4 與台灣醫療數據整合

療
ABOUT THE AUTHOR
療心智能團隊

醫療 AI 實作團隊

我們關心的不是 AI 能不能看懂病歷,而是患者離開醫院後那 99% 的時間有沒有人接住。這裡的文章來自我們開發 DietMate、CareMate 與 Taiwan Health MCP 的第一手經驗,技術、產業與倫理都談。

討論區 (0 則留言)

加載評論中...