e-Gov法令APIでClaudeに条文を正確に引用させる手順
条文を記憶から書かせず、e-Gov法令APIで原文を取ってから引用させる方法。elm指定と時点指定の呼び出し、Claude Code用のスクリプトと照合の手順をまとめます。
Claudeに法令の条文を引用させるなら、条文を思い出させず、e-Gov法令APIで原文を取得してから引用させるのが確実です。APIは認証なしで呼べるHTTPのAPIで、条や項まで絞って本文だけを返せます。
この記事では、法令IDの調べ方、条文の取得、過去の時点の指定、Claude Codeへの組み込み、引用が原文と一致するかの照合までを順に扱います。例には、フリーランス保護法として知られる「特定受託事業者に係る取引の適正化等に関する法律」と、労働基準法を使います。
条文を覚えさせず、原文を取りに行かせる
法令の条文は、改正のたびに文言が変わります。モデルが覚えているのは学習時点までの文言で、直近の改正が入った条文は、記憶が古いままの可能性があります。しかも引用は「一字一句同じ」であることが価値なので、少しの言い換えでも別の条文になります。
契約書の確認でも、Claudeの説明は条文の理解を助ける下調べに留め、引用は原文で照合する流れが安全です。この考え方はClaudeに契約書を読ませて条項を確認する方法でも触れています。ここでは照合の手間そのものを、API呼び出しに置き換えます。
流れは3段です。
条文を引用するまでの流れ
- 1
法令IDを確定する
法令名から、法令一覧取得APIで法令IDを引きます。
- 2
条文を要素指定で取得する
法令本文取得APIに法令IDと
elmを渡し、必要な条・項だけを取ります。 - 3
取得した本文だけを引用に使う
Claudeには取得した本文をそのまま引用させ、解釈は引用の外に書かせます。
法令APIで使う取得口
法令API Version 2のベースURLはhttps://laws.e-gov.go.jp/api/2です。仕様書には6つのエンドポイントが載っています。
| エンドポイント | 役割 | 条文引用での出番 |
|---|---|---|
/laws | 役割法令一覧の取得 | 条文引用での出番法令IDを調べる |
/law_revisions/{id} | 役割法令の履歴一覧 | 条文引用での出番改正の経緯を見る |
/law_data/{id} | 役割法令本文の取得 | 条文引用での出番条文の取得本体 |
/keyword | 役割本文のキーワード検索 | 条文引用での出番条文の候補探し |
/attachment/{履歴ID} | 役割添付ファイルの取得 | 条文引用での出番別表や図が必要なとき |
/law_file/{形式}/{id} | 役割本文ファイルの取得 | 条文引用での出番全文をファイルで欲しいとき |
条文を引用するだけなら、/lawsと/law_dataの2つで足ります。
手順1:法令IDを引く
法令IDは、505AC0000000025のような英数字の文字列です。法令名の一部をlaw_titleに渡すと、部分一致で候補が返ります。仕様書ではlaw_titleが「法令名又は法令略称」の部分一致と書かれており、略称でも引けます。
curl -s --get "https://laws.e-gov.go.jp/api/2/laws" \
--data-urlencode "law_title=フリーランス" \
--data-urlencode "limit=3" \
| jq -r '.laws[] | [.law_info.law_id,
.revision_info.law_title] | @tsv'「フリーランス」で引くと、505AC0000000025と正式名称の組が1件返りました。日本語のパラメータは、--data-urlencodeでURLエンコードして渡します。
法令IDのかわりに、法令番号や、改正履歴を指す法令履歴ID(505AC0000000025_20241101_000000000000000)も、本文取得APIにそのまま渡せます。
手順2:条文を要素指定で取得する
本文取得APIは、elmパラメータで取得する要素を絞れます。指定しなければ全文が返り、データが大きいとエラーになることがあります。仕様書にも、サイズが大きいときはSwagger UI以外で実行するよう注意書きがあります。引用が目的なら、最初からelmで絞るのが現実的です。
elmの書き方には規則があります。
- 条は
MainProvision-Article_3のように、本則(MainProvision)に条番号をつなげる - 要素をつなぐ区切りはハイフン、番号の前は
_ - 第3条第1項なら
MainProvision-Article_3-Paragraph_1
フリーランス保護法の第3条を取るには、次のように呼びます。json_format=lightを付けると、パースしやすい簡易版のJSONで返ります。
curl -s --get \
"https://laws.e-gov.go.jp/api/2/law_data/505AC0000000025" \
--data-urlencode "elm=MainProvision-Article_3" \
--data-urlencode "json_format=light" \
| jq '.law_full_text.Article | {ArticleTitle, ArticleCaption}'返却JSONのrevision_info.law_revision_idには、取得した条文が属する履歴ID(今回は505AC0000000025_20241101_000000000000000)が入ります。引用の出典として、この履歴IDを残しておくと、どの版の条文かを後から示せます。
枝番の条は「アンダースコア」で書く
「第三十八条の二」のような枝番の条は、Article_38_2と書きます。ハイフンでArticle_38-2と書くと、ハイフンは要素の結合記号なので別の意味になり、400エラーになります。実際に労働基準法で試すと、Article_38_2は「第三十八条の二」を返し、Article_38-2は「要素(elm)に合致する要素が法令本文に存在しません。」(コード400021)を返しました。
手順3:過去の時点の条文を引く
asofに日付を渡すと、その日付以前で最新の改正履歴の本文が返ります。契約が結ばれた当時の条文を確かめたいときに使えます。
労働基準法の第36条第1項で、asofだけを変えて呼んだ結果です。
asofの指定 | 返った履歴ID |
|---|---|
2019-01-01 | 返った履歴ID322AC0000000049_20180706_430AC0000000071 |
2020-01-01 | 返った履歴ID322AC0000000049_20190401_430AC0000000071 |
指定した日付により、返る履歴が切り替わります。履歴IDには日付が含まれるので、どの時点の版かを引用の出典にそのまま残せます。履歴IDを直接指定した場合、asofは無視されます。
Claude Codeに取得を任せる
ここからが、Claudeを組み込む部分です。毎回curlのコマンドを組み立てさせると、パラメータの付け忘れや、整形の揺れが出ます。取得を2つの小さなスクリプトに固定し、Claudeにはそれを呼ばせるだけにします。
まず、条文を取るスクリプトです。出力の1行目に出典(法令名と履歴ID)を付け、2行目以降が本文です。
#!/usr/bin/env bash
# 使い方: egov-article.sh <法令ID> <elm> [YYYY-MM-DD]
set -euo pipefail
law_id="$1"; elm="$2"; asof="${3:-}"
args=(--get "https://laws.e-gov.go.jp/api/2/law_data/${law_id}"
--data-urlencode "elm=${elm}" --data-urlencode "json_format=light")
if [ -n "$asof" ]; then args+=(--data-urlencode "asof=${asof}"); fi
curl -sS --fail-with-body "${args[@]}" | jq -r '
.revision_info as $r
| "出典: \($r.law_title) / 履歴ID \($r.law_revision_id)",
([.law_full_text | .. | strings] | join("\n"))'次に、法令名から法令IDを引くスクリプトです。
#!/usr/bin/env bash
# 使い方: egov-law-id.sh <法令名の一部>
set -euo pipefail
curl -sS --fail-with-body --get "https://laws.e-gov.go.jp/api/2/laws" \
--data-urlencode "law_title=$1" --data-urlencode "limit=5" |
jq -r '.laws[] | [.law_info.law_id, .revision_info.law_title,
.revision_info.current_revision_status] | @tsv'egov-article.shの本文部分は、JSONの中の文字列を再帰的に集めて改行でつなぐだけの作りです。本文取得APIのJSON形式は仕様書で試行版とされており、構造が変わる可能性があります。特定のキー名に依存しない抽出にしておけば、構造が少し変わっても動き続けます。
実行すると、第3条は次のように返ります(長い条文は途中を省略しています)。
出典: 特定受託事業者に係る取引の適正化等に関する法律 / 履歴ID 505AC0000000025_20241101_000000000000000
(特定受託事業者の給付の内容その他の事項の明示等)
第三条
1
業務委託事業者は、特定受託事業者に対し業務委託をした場合は、直ちに、…
ただし、これらの事項のうちその内容が定められないことにつき正当な理由が…
2
2
業務委託事業者は、前項の規定により同項に規定する事項を電磁的方法により…項番号の「1」「2」「2」が単独の行で混ざります。簡易版のJSONでは、項番号の文字列も本文と同じ階層に入るためです。引用に使うのは「業務委託事業者は、…」から始まる行だけです。
CLAUDE.mdに引用ルールを書く
スクリプトを置いたら、使い方をCLAUDE.mdに書きます。CLAUDE.mdはセッションの開始時にClaudeが読むプロジェクトの指示ファイルです。
## 法令の引用ルール
- 条文を引用するときは、記憶から書かず、必ず scripts/egov-article.sh で原文を取得する
- 法令IDが不明なときは、先に scripts/egov-law-id.sh で law_id を確定する
- 引用は取得した本文の行をそのまま使い、直前に出典行(法令名と履歴ID)を添える
- 取得に失敗したら条文を推測で補わず、失敗したと報告する
- 解釈や要約は、引用ブロックの外に書く最後の2行が効きます。取得に失敗したときの挙動を決めておかないと、Claudeが親切心で記憶から補ってしまうためです。
スクリプトだけを許可する
毎回の確認を減らすため、2つのスクリプトだけを許可します。curlそのものを許可するより、スクリプト単位で許可するほうが範囲を絞れます。.claude/settings.jsonには次のように書きます。
{
"permissions": {
"allow": [
"Bash(./scripts/egov-article.sh *)",
"Bash(./scripts/egov-law-id.sh *)"
]
}
}Claude Codeの権限ドキュメントには、Bash(curl http://github.com/ *)のようにcurlの引数でURLを絞る書き方は、バリエーションを取りこぼすので壊れやすいという注意があります。URLをスクリプトの中に閉じ込めれば、許可ルールは「このスクリプトを呼んでよい」の一点で済みます。
キーワード検索は候補探しに使う
条番号が分からないときは、キーワード検索APIで本文を横断検索できます。keywordは必須で、第*条のようなワイルドカードや、AND・OR・NOTの検索式も使えます。
curl -s --get "https://laws.e-gov.go.jp/api/2/keyword" \
--data-urlencode "keyword=書面又は電磁的方法により" \
--data-urlencode "law_num=令和五年法律第二十五号" \
--data-urlencode "limit=1" \
| jq '.items[0].sentences[0]'ただし、このAPIが返すtextは、ヒットした箇所を含む断片で、キーワードの部分は<span>タグで囲まれます。実際の呼び出しでも、文の途中から始まる断片が返りました。仕様書の例ではpositionにMainProvision-Article_21-Paragraph_3のような位置が入りますが、実際の呼び出しではmainprovisionとしか返らない場合がありました。
そのためキーワード検索は、引用そのものには使わず「どの法令・どの条らしいか」の候補探しに限ります。候補が決まったら、本文取得APIでelmを指定して全文を取り直し、引用はその結果から行います。
取得でつまずくポイント
実際に呼んで出会う症状を、原因別に表にまとめます。
| 症状 | 原因と対処 |
|---|---|
400 と 400021 のメッセージ | 原因と対処elmに合致する要素が無い。条番号か枝番の書き方(_と-)を見直す |
404 と「取得結果が0件です。」 | 原因と対処キーワード検索で該当する本文が無い。検索式を緩める |
| 本文がBase64の文字列で返る | 原因と対処response_formatとlaw_full_text_formatが異なる組み合わせ。どちらかをそろえるか、Base64をデコードする |
| 全文取得でエラー | 原因と対処本文サイズが大きすぎる。elmで条・項に絞る |
| 先頭に項番号の行が混ざる | 原因と対処簡易版JSONの仕様。引用に使う行を本文の文だけに絞る |
Base64の件は、仕様書に「JSONレスポンスで本文をXMLにした場合」と「XMLレスポンスで本文をJSONにした場合」の説明があり、どちらも形式が異なる場合はBase64で返ると書かれています。実際にresponse_format=jsonとlaw_full_text_format=xmlで呼ぶと、本文がBase64の文字列で返りました。形式を指定しないか、json_format=lightだけで使うと、この問題は起きません。
終了コードも覚えておきます。紹介したスクリプトは、400や404のときcurlが終了コード22で止まります。Claudeがエラーを黙って読み飛ばさないよう、CLAUDE.mdで「失敗したら報告する」と決めておくのはこのためです。
引用が原文と一致するか照合する
CLAUDE.mdで頼んでも、Claudeが最後の文書を書くときに言い回しを整えてしまう余地は残ります。機械で確かめられる形にしておくと安心です。
手順はシンプルです。取得した本文をfetched.txtに保存し、Claudeには引用した文を1行ずつquotes.txtにも書き出させます。次のコマンドで、取得した本文に完全一致する行が無い引用行だけが出力されます。
./scripts/egov-article.sh 505AC0000000025 MainProvision-Article_3 \
| tail -n +2 > fetched.txt
grep -vFxf fetched.txt quotes.txt-Fは固定文字列、-xは行全体の一致、-vは一致しない行の表示です。試しに、第3条第2項の正しい引用と、「業務委託事業者は、必ず書面で明示しなければならない。」という実在しない一文をquotes.txtに入れて実行すると、後者だけが出力されました。出力が空なら、すべての引用行が原文に存在します。
この照合は、Claudeに「検証して」と頼む運用より確実です。判定にモデルを通さないためです。
依頼文の例
最後に、実際に頼むときの文面です。法令名と条番号、時点を明示します。
フリーランス保護法の第3条を、scripts/egov-article.sh で取得して引用して。
引用は取得結果の本文をそのまま使い、直前に出典行を付けること。
そのうえで、第1項が求める明示事項を、引用の外で3点に要約して。
quotes.txt にも引用行を書き出して。法令名が通称のままでも、egov-law-id.shが法令IDを引けるので、Claudeは先に法令IDを確定してから本文を取得します。法令の解釈そのものは、取得した条文を材料にした下調べとして使い、実務の判断は原文と専門家の確認を踏まえて行います。資格試験の学習で条文を確認する使い方は、Claudeの学習モードで社労士・行政書士・宅建を勉強する方法にもあります。
まとめ
条文の正確さは、プロンプトの言い回しではなく、取得経路で決まります。法令IDは/lawsで確定し、条文は/law_dataのelmとasofで絞って取る。引用はその出力から行い、grepで原文との一致を確かめる。この3点が揃えば、Claudeの役割は「原文を並べて解釈の下調べをする」ことに限定されます。
CLAUDE.mdの規約に、pytestやvitestのコマンドを書くのと同じ要領で、取得スクリプトの呼び出しを書けば、法令を扱うプロジェクトの共通ルールになります。規約の書き方はClaude CodeにpytestのCLAUDE.md規約を教えるが参考になります。