Claude Code × Medical Application

【Claude Code】系統的文献レビュー × AI サブエージェント Part1:検索式の組み立てと subagent の分担

1. はじめに

検索の段(アニメーション)— PICO の P と I をブロックにし、query-builder が式を試して件数を見て直し、式を固定してスクリプトが全件を取る

Part1 は SR の最初の工程、検索です。

1-1. この段の目的

SR の検索の目的は、組み入れるべき研究を、取りこぼさずに候補へ入れることです。ここで拾えなかった論文は、後のスクリーニングでは取り返せません。そのため検索では、件数が増えても漏れの少なさ(Recall)を優先します。ただし候補は、次のスクリーニングで1件ずつ読める量(数百〜千件程度)に収めます。

本試行では、この段で次の2つを確かめ、次の段への入力を作ります。

中身 測り方
問い 人の手を入れずに、エージェントが PICO だけから作った PubMed の検索式で、元のレビューが組み入れた研究をどこまで拾えるか 検索 Recall=ベンチマークの答えのうち、検索の全ヒットに入った割合。原著は 0.711〜0.834
次の段への入力 Part2 のスクリーニングにかける候補を、再現できる形で固定する 候補の件数と、PMID の並びを保存した search.json

1-2. 原著との対比

原著 TrialMind 本試行
入力 PICO PICO(TrialReviewBench の値のまま)
検索式の作り方 PICO から Boolean query を作り、予備検索の抄録を参考に語を足し引きする subagent query-builder が PubMed コネクタ(MCP)で部分式を試し、件数と展開を見て直す
データベース PubMed PubMed
人の関与 — なし(案のまま使う。1本につき1回だけ走らせる)
指標 検索 Recall 検索 Recall(全ヒットで数える)

1-3. 手順と結果の要約

手順 中身 結果
① PICO を2つのブロックに分ける P(対象)と I(介入)だけを使い、C と O では絞らない 3本とも P AND I の形(31190844 は CD19 を別のブロックに)
② 式を試して直す query-builder が PubMed コネクタで部分式を投げ、件数と展開を見て直す 1本あたり3〜5回の試行で確定
③ 全件を取って固定する fetch_pubmed.py が全ヒットの書誌と抄録を取り、PMID の並びを保存する 683/698/484件(計 1,865件)
④ 答えと照らす ベンチマークの答え27本が全ヒットに入ったかを数える 検索 Recall 0.963(26/27)。原著の 0.711〜0.834 を上回ったが、条件の違いがあり比べられる値ではない(5章)

2. 手順

2-1. ① PICO から2つのブロックへ

PICO は、問いを対象(P)・介入(I)・比較(C)・評価項目(O)の4つで書く型です。PICO の決め方は解説ページ「【業務説明】系統的文献レビュー」の 4.1 に、検索式の組み方(MeSH と自由語、ブロックと AND・OR)は 4.2 にあります。本試行の入力は、TrialReviewBench に入っている3本の PICO そのままです。

レビュー P(対象) I(介入) C(比較) O(評価項目)
33746596 Patients with relapsed/refractory multiple myeloma (RRMM) CAR-T therapy N/A 奏効率・完全奏効率・MRD 陰性率・再発率・無増悪生存期間の中央値、グレード3〜4の CRS と神経毒性
31190844 Patients with diagnosed hematological malignancies Autologous CD19 chimeric antigen receptor-T cell therapy Standard care or alternative treatments Survival outcomes and efficacy of the therapy
37168849 Patients with relapsed/refractory acute myeloid leukemia (RR-AML) Chimeric antigen receptor T cell (CAR-T) therapy N/A 完全奏効率・全奏効率、CRS・ICANS・GVHD の発生

O が長い2本は、ベンチマークの英文を日本語で要約しました(原文は bench/reviews.jsonl)。

query-builder は、PICO を概念のブロックに分けます。ブロックにするのは原則 P(対象)と I(介入)だけです。O(評価項目)や研究デザインで絞ると、抄録に書かれていない論文が落ち、Recall が下がるからです。ブロックの中は MeSH と自由語([tiab])を OR で並べ、ブロック同士を AND で結びます。

多発性骨髄腫のレビュー(PMID 33746596)の最終案は、次の1本でした。

("Multiple Myeloma"[MeSH Terms] OR "multiple myeloma"[tiab] OR "myeloma"[tiab] OR RRMM[tiab])
AND
("Receptors, Chimeric Antigen"[MeSH Terms] OR "Immunotherapy, Adoptive"[MeSH Terms]
 OR "chimeric antigen receptor"[tiab] OR "CAR-T"[tiab] OR "CAR T"[tiab] OR "CAR-T cell"[tiab]
 OR CART[tiab] OR "CAR T-cell"[tiab] OR "CAR-modified"[tiab] OR "BCMA"[tiab]
 OR "idecabtagene"[tiab] OR "ciltacabtagene"[tiab])

PICO の P は「relapsed/refractory multiple myeloma」ですが、relapsed/refractory はブロックにしていません。再発・難治かどうかは、スクリーニングの基準で判定します。

2-2. ② 件数と展開を見て直す

query-builder は部分式ごとにコネクタで試し、返ってきた件数(total_count)と、PubMed が実際に解釈した式(query_translation)を見て直します。いちばん直しが多かったのは、CD19 を標的とする CAR-T のレビュー(PMID 31190844)です。

試行の記録 — PMID 31190844 の検索式。4,483件から698件へ

最初の式は CD19 を CAR の語と OR で並べていたので、CD19 と書かれているだけの論文まで拾い、4,483件になりました。CD19 を別のブロックにして AND で結ぶと 605件に下がり、語を足して 698件で確定しました。

3本の最終案は次のとおりです。

レビュー ブロック 演算子の数 試行の回数 全ヒット
33746596 多発性骨髄腫 P AND I 15 3 683件
31190844 CD19 CAR-T CAR AND CD19 AND 血液がん 14 4 698件
37168849 急性骨髄性白血病 P AND I 12 5 484件

式の全文と試行の記録は、リポジトリの reviews/<PMID>/eval-3/query.md にあります。query-builder の返答を一字も変えずに写したものです。

2-3. ③ 全件を取って固定する

確定した式は、スクリプト fetch_pubmed.py が E-utilities で実行し、全ヒットの書誌・抄録・出版日を取ります。全ヒットの PMID の並び、式、取得日時は search.json に保存して commit しました(理由は 4-3)。

2-4. ④ 答えと照らす

最後に、ベンチマークの答え(元のレビューが組み入れた研究の PMID)が全ヒットに入っているかを数えます。答えは、ここまでのどの段にも渡していません。

3. 結果

3-1. 検索 Recall

検索 Recall は、元のレビューが組み入れた研究(ベンチマークの答え)のうち、検索の全ヒットに入った割合です。

検索 Recall — 本試行3本と原著の範囲
レビュー 組み入れ 全ヒット 検索 Recall 拾えなかった研究
33746596 9 683 1.000(9/9) —
31190844 7 698 1.000(7/7) —
37168849 11 484 0.909(10/11) 28864289
計 27 1,865 0.963(26/27)

拾えなかった 28864289 は、NK-92 由来の活性化 NK 細胞の第1相試験で、CAR を持ちません。CAR の語のブロックには当たらないので、検索式を直しても拾えない種類の取りこぼしです。元のレビュー自身の基準は CAR-T なので、ベンチマークの答えの側が基準から外れていると考えています(Part2 で再び出てきます)。

3-2. PRISMA の件数

33746596 31190844 37168849
検索で同定(PubMed) 683 698 484
重複 0 0 0
拾えなかった答えを足した数 0 0 1
スクリーニングへ 683 698 485

原著のスクリーニングは「組み入れ研究をすべて含む候補」の中で順位を付けています。それに合わせて、37168849 だけは拾えなかった1件を候補の最後に足しました。screener には、足したことを伝えていません。3本の候補は計 1,866件で、これが Part2 の入力です。

4. この作業の組み方

4-1. 試す段と取る段を分ける

検索の2段 — 式を試す段と、全件を取る段

検索には道具を2つ使いました。Anthropic 公式の PubMed コネクタ(MCP)と、E-utilities を直接呼ぶスクリプト fetch_pubmed.py です。

コネクタは試行錯誤に向いています。件数と展開がすぐ返るので、エージェントが式を直しながら進められます。一方で、1回の式は演算子20個まで、返す件数は200件までという制限があり、数百件の書誌と抄録を一括で取るのには向きません。そこで、式を決めるまでをコネクタ、決まった式で全件を取るのをスクリプトに分けました。

段 担当 やること 残すもの
式を試す subagent query-builder 部分式を試して直す 試した式・件数・展開(query.md)
全件を取る fetch_pubmed.py esearch で全ヒットの PMID、efetch で書誌と抄録 式・期間・取得日時・PMID の並び(search.json)

試してみて分かったコネクタの癖は、agent 定義に書き込みました。たとえば、期間の上限 date_to だけを渡すと絞り込みが効かず、date_from と両方渡す必要があります。

4-2. query-builder の道具を絞る

query-builder の定義(.claude/agents/query-builder.md)の先頭は次のとおりです。

name: query-builder
description: レビューの PICO と承認済みの適格基準から PubMed の Boolean query を作り、
  公式 PubMed コネクタで部分式ごとに試して直す。(略)本検索(fetch_pubmed.py)はしない
tools: mcp__plugin_pubmed_PubMed__search_articles, mcp__plugin_pubmed_PubMed__get_article_metadata
model: sonnet

道具はコネクタの7つのうち、検索と書誌の取得の2つだけです。

  • Read を持たない:正解(ベンチマークの答え)のファイルを読めない。PICO と期間の上限は、本体が委任メッセージで渡す
  • 関連論文と全文の道具を外す:find_related_articles と get_full_text_article を使うと、元のレビューの参考文献から正解が漏れる
  • Write を持たない:試行の記録は返答として返し、本体が query.md に書く

コネクタの7つの道具は、settings.json の permissions.allow に名前で1つずつ足しています。ワイルドカードにすると、プラグインに道具が増えたとき勝手に許可されるからです。

4-3. 取ったものを固定する

PubMed の relevance 順(Best Match)は、呼び出すたびに少し揺れます。取り直すと並びが変わり、後の順位付けの評価が再現できません。そこで fetch_pubmed.py は、全ヒットの PMID の並び・式・PubMed が解釈した式・取得日時を search.json に書き、これを commit しました。抄録は著作権があるので commit しません。リポジトリを手元で動かすときは、固定した PMID から抄録だけを取り直します(--from-search)。

API key はリポジトリの .env からスクリプトが読み、Claude 自身は .env を開けません(permissions.deny)。リクエストはすべて POST にして、key が URL やエラーメッセージに載らないようにしました。

4-4. 件数を記録する

段ごとの件数は skill /prisma-record がスクリプト prisma_record.py を呼んで数え、和が合うことを確かめてから prisma.json に書きます。Claude が数字を手で写すことはしません。手で直したときは PostToolUse の hook check_prisma.py が同じ和(同定 − 重複 = スクリーニング + 未スクリーニング、など)を検査し、合わなければ Claude に知らせます。

4-5. 人が決めたこと

人が決めたこと 理由
検索期間の上限を、元のレビューの公開日にする 元のレビューが見られなかった論文を、正解と比べる土俵に入れない
query-builder は1本につき1回だけ走らせ、最終案をそのまま使う よい案を選ぶために作り直すと、人の判断が入る
本体は委任メッセージに条件を書き足さない 書き足した条件は、人の指示と区別できなくなる
答えを見たあとで、検索式を直さない 答えに合わせて直した Recall は、評価にならない

3つ目は、実際に起きたことから決めました。最初に人が検索式を承認した段で、「P は multiple myeloma の語だけ」という条件が委任メッセージに入っていました。人の指示ではなく、本体が書き足したものでした。原著と比べる流れ(eval-3)では、委任メッセージを3本とも同じ形に固定し、<...> の差し替えだけにしています。

5. 言えること・言えないこと

網羅性の2つの限界 — 元レビューの組み入れ50本、答え27本、検索で当たった26本

言えること

  • 人の判断を入れずに、エージェントが作った式で、ベンチマークの答え27本のうち26本を PubMed から拾えた
  • 拾えなかった1本は、式の語の不足ではなく、CAR を持たない研究が答えに入っていたため

言えないこと

  • 原著より検索がうまい、とは言えない。原著は候補を何件まで絞ったかを書いていない。本試行は全ヒット(数百件)で数えた。レビューも3本しかない
  • 網羅的に検索できた、とは言えない。網羅性の限界は2つある。(a) PubMed にあるのに式に当たらない「検索式の限界」は、検索 Recall に表れる。(b) PubMed に無い論文の「データベースの限界」は、ベンチマークの答えが PMID の一覧なので測れない。元のレビュー3本は本文で計50本を組み入れていて、そのうち23本は答えに無い(33746596 では14本に PMID が無く、大半は学会抄録)
  • 原著と同じ手順で作った、とは言えない。agent 定義には「予備検索の上位の抄録から語を拾う」と書いたが、3本とも query-builder は抄録を読まず、PICO と一般的な同義語だけで式を作った。そのことは本人が「未確認・気になる点」に書いている

最後の点は、エージェントに任せるときの要点でもあります。手順を定義に書いても、その通りに動くとは限りません。試行の記録を一字も変えずに残しておいたから、手順と違うことが後から分かりました。

6. まとめ

この段の目的は、組み入れるべき研究を取りこぼさずに候補へ入れることと、それをエージェントだけでどこまでできるかを確かめることでした。人の判断を入れない流れで、検索 Recall は 3本の計で 0.963(26/27)、候補は 1,866件です。

組み方としては、検索の段を試す段(subagent query-builder + PubMed コネクタ)と取る段(fetch_pubmed.py)に分けました。エージェントには道具を2つだけ渡して正解から切り離し、件数と展開はコネクタが返した値だけを記録させ、取った PMID の並びは固定しました。

ただしこれは、PubMed の中での網羅性です。PubMed だけを検索する本試行は、業務の SR の検索の代わりにはなりません。

次のステップ

Part2 ではスクリーニングを扱います。Part1 で集めた 1,866件を、LLM が書いた適格基準のまま、基準ごとに 1/0/−1 で判定し、合計で順位を付けます。本体1つで判定したときに起きたこと(context・引用・線引きのぶれ)と、それを受けて分けた subagent screener、逐語引用を検査する hook、原著との Recall@20・@50 の比較を示します。

出典

  • Wang Z, Cao L, Danek B, Jin Q, Lu Z, Sun J. Accelerating clinical evidence synthesis with large language models. npj Digit Med 2025;8:509, doi:10.1038/s41746-025-01840-7(arXiv:2406.17755)
  • TrialReviewBench(Hugging Face: zifeng-ai/TrialReviewBench、Apache-2.0)
  • NCBI. Entrez Programming Utilities Help(E-utilities). https://www.ncbi.nlm.nih.gov/books/NBK25499/
  • Page MJ et al. The PRISMA 2020 statement. BMJ 2021;372:n71
  • Anthropic, Claude Code Docs(subagents / MCP / hooks / permissions)

コードは GitHub で公開しています: github.com/HerzLeben/pubmed-slr-screening