# Pipeline Persistence

> Pipeline persistence — save, load, and reuse structured search plans. Triggers: pipeline, 管道, search plan, 搜尋計畫, 重複搜尋, saved search, 排程, schedule, workflow, DAG

- Skill: `u9401066-pubmed-search-mcp/pipeline-persistence` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds add u9401066-pubmed-search-mcp/pipeline-persistence`
- Raw SKILL.md: https://api.skillmd.com/api/skills/u9401066-pubmed-search-mcp/pipeline-persistence/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: u9401066 (https://skillmd.com/u/u9401066-pubmed-search-mcp)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/u9401066-pubmed-search-mcp/pipeline-persistence

---


# Pipeline 持久化 — 結構化搜尋計畫管理

## 描述
將複雜的搜尋流程保存為可重複使用的 Pipeline YAML 配置。支援：
- 從模板快速建立（PICO、comprehensive、exploration、gene_drug）
- 自訂 DAG（有向無環圖）多步驟管道
- 雙層儲存（workspace + global）
- Schema-exact 驗證 + 有限度的安全 normalization

## 觸發條件
- 「把這個搜尋存起來」、「建立搜尋計畫」
- 「每週跑一次這個搜尋」、「保存這個 pipeline」
- 「列出我的管道」、「上次的搜尋可以再跑嗎」
- 「把剛才的搜尋轉成 search plan」

---

## 🌟 快速開始

### 方法 1: 用模板（最簡單）

```python
# 保存一個 PICO 模板 pipeline
save_pipeline(
    name="icu_remimazolam_vs_propofol",
    config="""
template: pico
template_params:
  P: ICU patients requiring sedation
  I: remimazolam
  C: propofol
  O: delirium incidence, sedation quality
""",
    tags=["anesthesia", "sedation", "ICU"],
    description="Weekly monitoring: remimazolam vs propofol ICU sedation"
)

# 執行已保存的 pipeline
unified_search(pipeline="saved:icu_remimazolam_vs_propofol")
```

### 方法 2: 自訂 DAG（完整控制）

```python
save_pipeline(
    name="brca1_comprehensive",
    config="""
steps:
  - id: expand
    action: expand
    params:
      topic: BRCA1 breast cancer
  - id: pubmed
    action: search
    params:
      query: BRCA1 breast cancer
      sources: [pubmed]
      limit: 50
  - id: expanded
    action: search
    inputs: [expand]
    params:
      strategy: mesh
      sources: [pubmed, openalex]
      limit: 50
  - id: merged
    action: merge
    inputs: [pubmed, expanded]
    params:
      method: rrf
  - id: enriched
    action: metrics
    inputs: [merged]
output:
  format: markdown
  limit: 30
  ranking: quality
""",
    tags=["genetics", "oncology"],
    description="BRCA1 breast cancer comprehensive search with MeSH expansion"
)
```

---

## 7 個 MCP 工具

### save_pipeline — 保存管道

```python
save_pipeline(
    name="weekly_remimazolam",     # 唯一名稱 (英數 + _ -, max 64)
    config="<YAML or JSON>",       # Pipeline 配置
    tags=["tag1", "tag2"],        # 最多 20 個 canonical 字串標籤
    description="...",             # 人類可讀描述
    scope="auto"                   # "workspace" | "global" | "auto"
)
```

**Fail-closed contract：**
- action/template 只接受下列 canonical 值；alias 與拼字錯誤直接拒絕
- template 參數只使用頂層 `template_params`；已退役的頂層 `params` 直接拒絕
- step ID 必須明確且唯一；dependency ID 必須精確引用前面的 step
- 未知 `on_error`、output format 或 ranking 不會被猜測或改寫

### list_pipelines — 列出管道

```python
list_pipelines()                    # 列出所有
list_pipelines(tag="ICU")           # 按標籤過濾
list_pipelines(scope="workspace")   # 只看工作區
```

### load_pipeline — 載入管道

```python
load_pipeline(source="weekly_remimazolam")            # 從已保存
load_pipeline(source="file:path/to/pipeline.yaml")    # 從檔案
```

### delete_pipeline — 刪除管道

```python
delete_pipeline(name="old_search")  # 刪除配置 + 歷史
```

### get_pipeline_history — 查看執行歷史

```python
get_pipeline_history(name="weekly_remimazolam", limit=5)
# 顯示：日期、文章數、新增/移除文章、狀態
```

### schedule_pipeline — 建立或更新排程

```python
schedule_pipeline(name="weekly_remimazolam", cron="0 9 * * 1")
```

### unschedule_pipeline — 移除排程

```python
unschedule_pipeline(name="weekly_remimazolam")
```

---

## 4 個內建模板

### pico — PICO 臨床問題

```yaml
template: pico
template_params:
  P: ICU patients requiring sedation
  I: remimazolam
  C: propofol
  O: delirium incidence
  sources: [pubmed]        # 可選，預設 pubmed
  limit: 20              # 可選
```

**自動產生的 DAG：**
```
pico → search_p  ──┐
     → search_i  ──┤
     → search_c  ──┼→ merged → enriched
```

### comprehensive — 多資料庫 + MeSH 擴展

```yaml
template: comprehensive
template_params:
  query: CRISPR gene therapy safety
  sources: [pubmed, openalex, europe_pmc]  # 可選
  limit: 30                             # 可選
  min_year: 2020                        # 可選
```

**自動產生的 DAG：**
```
expand → search_expanded  ──┐
         search_original  ──┼→ merged → enriched
```

### exploration — 種子論文探索

```yaml
template: exploration
template_params:
  pmid: "33475315"
  limit: 20        # 每個方向的限制
```

**自動產生的 DAG：**
```
related  ──┐
citing   ──┼→ merged → enriched
refs     ──┘
```

### gene_drug — 基因/藥物搜尋

```yaml
template: gene_drug
template_params:
  term: BRCA1
  sources: [pubmed, openalex]  # 可選
  limit: 20                  # 可選
  min_year: 2020             # 可選
```

---

## 10 個可用 Action

| Action | 說明 | 主要參數 |
|--------|------|----------|
| `search` | 文獻搜尋 | `query`, `sources`, `limit`, `min_year`, `max_year` |
| `pico` | Agent-provided PICO handoff search | `P`, `I`, optional `C`, recommended `O` |
| `expand` | MeSH/同義詞擴展 | `topic` |
| `details` | 取得文章詳情 | `pmids` |
| `related` | 相關文章 | `pmid`, `limit` |
| `citing` | 引用文章 | `pmid`, `limit` |
| `references` | 參考文獻 | `pmid`, `limit` |
| `metrics` | iCite 引用指標 | （從 inputs 取得） |
| `merge` | 合併結果 | `method`: `union` / `intersection` / `rrf` |
| `filter` | 過濾結果 | `min_year`, `max_year`, `article_types`, `min_citations`, `has_abstract` |

---

## 雙層儲存模型

```
Workspace scope (.pubmed-search/pipelines/)
├── 每個專案獨立
├── 可納入 git 追蹤
└── 團隊共享

Global scope (~/.pubmed-search-mcp/pipelines/)
├── 跨專案共用
├── 個人偏好
└── 通用模板
```

**解析順序：** workspace 優先 → global fallback

---

## 生產級範例

### 範例 1: 週報搜尋 — 麻醉藥物監控

```yaml
name: weekly_anesthesia_monitoring
steps:
  - id: search_remimazolam
    action: search
    params:
      query: remimazolam
      sources: [pubmed, europe_pmc]
      limit: 50
      min_year: 2024
  - id: search_dex
    action: search
    params:
      query: dexmedetomidine ICU sedation
      sources: [pubmed]
      limit: 50
      min_year: 2024
  - id: merged
    action: merge
    inputs: [search_remimazolam, search_dex]
    params:
      method: union
  - id: filtered
    action: filter
    inputs: [merged]
    params:
      has_abstract: true
      article_types: [journal-article, clinical-trial, randomized-controlled-trial]
  - id: enriched
    action: metrics
    inputs: [filtered]
output:
  format: markdown
  limit: 30
  ranking: recency
```

### 範例 2: 種子論文深度探索

```yaml
name: explore_landmark_paper
steps:
  - id: seed_details
    action: details
    params:
      pmids: ["33475315"]
  - id: related
    action: related
    params:
      pmid: "33475315"
      limit: 30
  - id: citing
    action: citing
    params:
      pmid: "33475315"
      limit: 30
  - id: refs
    action: references
    params:
      pmid: "33475315"
      limit: 30
  - id: merged
    action: merge
    inputs: [related, citing, refs]
    params:
      method: rrf
  - id: enriched
    action: metrics
    inputs: [merged]
output:
  format: markdown
  limit: 25
  ranking: impact
```

### 範例 3: 系統性文獻回顧 — SGLT2 + 心衰竭

```yaml
name: sglt2_heart_failure_review
steps:
  - id: pico
    action: pico
    params:
      P: Type 2 diabetes with heart failure
      I: SGLT2 inhibitors
      C: standard care
      O: hospitalization, mortality
  - id: mesh_expand
    action: expand
    params:
      topic: SGLT2 inhibitors heart failure outcomes
  - id: search_pico_p
    action: search
    inputs: [pico]
    params:
      element: P
      sources: [pubmed, europe_pmc]
      limit: 100
  - id: search_pico_i
    action: search
    inputs: [pico]
    params:
      element: I
      sources: [pubmed, europe_pmc]
      limit: 100
  - id: search_expanded
    action: search
    inputs: [mesh_expand]
    params:
      strategy: mesh
      sources: [pubmed, openalex]
      limit: 100
  - id: merged
    action: merge
    inputs: [search_pico_p, search_pico_i, search_expanded]
    params:
      method: rrf
  - id: filtered
    action: filter
    inputs: [merged]
    params:
      min_year: 2018
      has_abstract: true
  - id: enriched
    action: metrics
    inputs: [filtered]
output:
  format: markdown
  limit: 50
  ranking: quality
```

---

## Agent 產生 Pipeline 的最佳實踐

### 從中斷的搜尋回復

先讀 server-side durable state，不要依賴對話記憶或 `.github/hooks/_state`：

```python
read_session(request={"action":"search_runs"})
read_session(request={"action":"search_run","run_id":"<selected-run-id>"})
read_session(request={"action":"replay_search","run_id":"<selected-run-id>"})
```

`replay_search` 只回傳 credential-free `unified_search` arguments，不會自動執行或消耗
provider quota。Agent 檢查 source status、artifact audit 與使用者意圖後，再明確呼叫
`unified_search`。如果原 run 已有 artifact，優先讀 artifact，只有需要最新結果時才 replay。

### 將對話搜尋轉為 Pipeline

Agent 在完成一次成功搜尋後，可以：

```python
# 1. 回顧剛才的搜尋策略
# 2. 轉化為 Pipeline YAML
save_pipeline(
    name="auto_from_session",
    config="""
steps:
  - id: main_search
    action: search
    params:
      query: "<剛才的查詢>"
      sources: [pubmed, openalex]
      limit: 50
  - id: enriched
    action: metrics
    inputs: [main_search]
output:
  limit: 20
  ranking: balanced
""",
    description="Auto-generated from search session"
)

# 3. 下次直接重複
# unified_search(pipeline="saved:auto_from_session")
```

### 常見模式

| 場景 | 推薦模板 | 說明 |
|------|----------|------|
| 臨床問題 A vs B | `pico` | Agent 提供 P/I/C/O；後端執行含 O 的 precision/recall 搜尋 |
| 主題綜合搜尋 | `comprehensive` | 多源 + MeSH 擴展 |
| 已知重要論文 | `exploration` | 三方向探索（related/citing/refs） |
| 基因/藥物研究 | `gene_drug` | 詞彙擴展 + 多源 |
| 複雜工作流 | 自訂 DAG | 完全控制每個步驟 |

