Community研究与数据分析github.com

HighBridgeDragon/jp-diet-minutes-skill

Search Japanese Diet (Kokkai) meeting minutes via the official NDL Kokkai API — an Agent Skill for Claude Code / Cursor / Copilot. 日本の国会会議録調査スキル。

jp-diet-minutes-skill 是什么?

jp-diet-minutes-skill is a Claude Code agent skill that search Japanese Diet (Kokkai) meeting minutes via the official NDL Kokkai API — an Agent Skill for Claude Code / Cursor / Copilot. 日本の国会会議録調査スキル。.

兼容平台✓Claude Code~Codex CLI✓Cursor
npx skills add HighBridgeDragon/jp-diet-minutes-skill

Installed? Explore more 研究与数据分析 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

National Diet Minutes Search Skill

Investigates Japanese National Diet minutes from the start of the Diet (1947) onward via the NDL (National Diet Library) Minutes Search System API. No authentication required. Invoked using bash scripts/<script>.sh wrapper.

Imperial Diet minutes (up to 1947) are handled by a separate API and are not covered.

Basic Rules

  • Base URL: https://kokkai.ndl.go.jp/api/
  • Response format: recordPacking=json (always enforced by wrapper scripts)
  • Authentication: Not required
  • Invocation method: Use bash scripts/<script>.sh. Direct use of WebFetch / Invoke-RestMethod etc. is only for corner cases not covered by the wrapper (see "Cases requiring raw curl" below)
  • Rate limit: The official documentation states "mechanical access must avoid multiple requests; leave intervals of several seconds." Parallelization is prohibited; sequential calls should be spaced 2–3 seconds apart.
  • Query length limit: 2,000 bytes (Japanese characters are approximately 9 bytes each when URL-encoded)

Endpoint Selection

Select the appropriate wrapper script based on user requests. The amount of information and token consumption increases in the order list-meetings.sh < search-by-*.sh < fetch-meeting.sh, so progressively narrow down from lighter options.

"Show me statements made by Member ○○"
  → bash scripts/search-by-speaker.sh ○○ [from] [until] [limit] --sort <keys>
  ※ `--sort` is required. Representative value: `date-desc` (newest first)

"Search for statements about △△"
  → bash scripts/search-by-keyword.sh △△ [from] [until] [limit] --sort <keys>
  ※ `any` search (AND). Multiple keywords separated by spaces. `--sort` required.

"Extract witness questioning (including references and public commenters)"
  → bash scripts/search-by-role.sh 参考人 [from] [until] [limit] --sort <keys>
  ※ `role` is one of: 証人 / 参考人 / 公述人. `--sort` required.

"Show me a list of meetings for Committee ○○"
  → bash scripts/list-meetings.sh ○○ [from] [until] [limit] --sort <keys>
  ※ Lightweight. Only returns meeting metadata (no speech text). `--sort` required (only `date-asc` / `date-desc`).

"Show me all statements for a specific meeting" / "Full minutes of Committee ○○ on YYYY-MM-DD"
  → Step 1: Use `bash scripts/list-meetings.sh` to identify the target meeting's `issueID`
  → Step 2: Use `bash scripts/fetch-meeting.sh <issueID>`
  ※ Returns the full meeting in a single request, so it can be large. Always narrow down first.

See api-reference.md, parameters.md, response-format.md, recipes.md for details.

Usage of Each Endpoint

1. search-by-speaker.sh — Search statements by member name (most frequent)

Returns only statements matching the search conditions. Most token-efficient. --sort is required, making the user explicitly aware of the API sort order specification (countermeasure #41).

# Extract statements by member name (partial match OR), descending by date
bash scripts/search-by-speaker.sh 岸田文雄 2024-01-01 2024-12-31 50 --sort date-desc

See bash scripts/search-by-speaker.sh -h for full argument specifications (including details on possible sort keys).

The response is a speechRecord[] array. Each element contains meeting metadata (issueID, session, nameOfHouse, nameOfMeeting, date, etc.) flattened.

2. search-by-keyword.sh — Keyword search (any search, AND)

Full-text search of speech text. Multiple keywords are AND-joined separated by spaces. --sort required.

# AND search: statements containing both "マイナンバー" and "個人情報", descending by date
bash scripts/search-by-keyword.sh 'マイナンバー 個人情報' 2024-01-01 2024-12-31 50 --sort date-desc

See bash scripts/search-by-keyword.sh -h for full argument specifications. Response structure is identical to search-by-speaker.sh.

3. search-by-role.sh — Search statements by role (e.g., witness questioning)

Filters by the speaker's role (speakerRole). Used to extract witness questioning, reference statements, and public commenter statements. --sort required.

# Only reference statements, descending by date
bash scripts/search-by-role.sh 参考人 2024-01-01 2024-12-31 50 --sort date-desc

role must be one of: 証人 (witness) / 参考人 (reference) / 公述人 (public commenter). Specifying anything else will cause the API to reject with HTTP 400.

See bash scripts/search-by-role.sh -h for full argument specifications.

4. list-meetings.sh — Meeting list (lightweight index)

Returns only meeting metadata. Does not include speech text, making it suitable for generating lists and narrowing down. Used to identify issueID. --sort required (only date-asc / date-desc).

# List of Budget Committee meetings for a specific day, ascending by date
bash scripts/list-meetings.sh 予算委員会 2024-03-01 2024-03-31 50 --sort date-asc

See bash scripts/list-meetings.sh -h for full argument specifications.

The response is a meetingRecord[] array. The speechRecord[] under each element contains only the minimum set of speech metadata (speechID, speechOrder, speaker, speechURL). To get the full text, call search-by-* or fetch-meeting.sh.

5. fetch-meeting.sh — Full meeting text (last resort)

Returns the full text of a meeting. Heavy because it returns all statements in a single request. Call after identifying the issueID via list-meetings.sh.

# Fetch full meeting by issueID
bash scripts/fetch-meeting.sh 121405254X00220241004

See bash scripts/fetch-meeting.sh -h for argument specifications. maximumRecords is fixed at 1 (since issueID is unique). --sort is not applicable because it retrieves a single meeting (use jq for post-processing of output if needed).

fetch-meeting.sh's speechRecord[] contains all fields (speech, speakerYomi, speakerGroup, speakerPosition, speakerRole, startPage, createTime/updateTime).

Token Saving Guidance

bash scripts/fetch-meeting.sh can be several hundred KB to MB per meeting. Follow these rules:

  1. Prefer search-by-*.sh: For speech units, it retrieves only the necessary parts. bash scripts/fetch-meeting.sh should be used only when the user explicitly requests a "full meeting text."
  2. Explicitly specify maximumRecords: The default of 30 is sufficient in many cases; can be omitted. When retrieving many records, increase up to the limit (search-by-*/list-meetings: 100, fetch-meeting: 10) to reduce the total number of requests.
  3. Use two-stage search: First narrow down with list-meetings.sh or search-by-*.sh to get the issueID, then if needed, use fetch-meeting.sh for the full text. Do not call fetch-meeting.sh from the start.
  4. Retry with variations on 0 hits: For member names, try 福島 みずほ / 福島瑞穂 / hiragana sequentially. For group names, always use the full official name (自民党 ❌ / 自由民主党 ✅).

Pitfalls in Result Filtering

After receiving the response, note the following:

  1. Rows with speechOrder = 0 are meeting record headers: Structural information such as agenda, items for deliberation, etc., not actual statements. The speaker is fixed as 会議録情報. Exclude rows where speechOrder is 0 when aggregating statements.
  2. Values of imageKind: By default, besides 会議録 (minutes), 目次 (table of contents), 索引 (index), 附録 (appendix), and 追録 (supplement) may be mixed in. When extracting statements, filter to rows where imageKind is 会議録. The request parameters contentsAndIndex and supplementAndAppendix both default to false, so they can usually be omitted. Specify true only if you explicitly want to include them.
  3. closing returns null instead of false: For regular sessions without a closed session flag, it returns null. Determine if it is a closed session review only when closing is true (compare with true, not with false).
  4. Invalid values in nameOfHouse are silently ignored: The API returns HTTP 200 with results where the filter was not applied. Verify that the intent was reflected by checking the validity of numberOfRecords.
  5. Line breaks in speech text are CRLF (\r\n): Not just LF. Normalization may be necessary during text processing.
  6. Response structure of search-by-*.sh is flat: Does not have a meetingRecord wrapper like fetch-meeting.sh. Branching is needed if writing a common parser.
  7. API sort order is fixed as "descending by meeting date": The official specification guarantees descending order, and there is no sort parameter on the API side (same for search-by-speaker, search-by-keyword, list-meetings, and fetch-meeting). The --sort parameter in this skill's wrapper scripts is not an API parameter but a client-side sort post-processing via jq (required in search-by-*.sh / list-meetings.sh). While convenient, when using maximumRecords for partial retrieval, only the most recent N items are returned.
    • Determining the latest statement: OK as the first item of a partial retrieval (maximumRecords=1 is sufficient).
    • Determining the oldest statement: Do not determine from a partial retrieval result. Either retrieve all items via pagination to the end of numberOfRecords, or narrow down the period using from / until until the hit count ≤ maximumRecords before determining.
    • Secondary sort within the same day is ascending by speechOrder (measured, not in official specification): If you hit the tail directly with startRecord=<numberOfRecords>&maximumRecords=1 without narrowing the period, due to fixed descending order, you will get the last statement of the oldest date within the period (max speechOrder), missing the true first statement. Narrow the period using from/until until numberOfRecords ≤ 100, retrieve all, and confirm with a single request using --sort date-asc,speech-order-asc (see recipes/oldest-speech-by-speaker.md for details).
  8. Combining any and speaker results in an intersection (significantly fewer results): If you specify both any=A&speaker=A to search for statements by Member A, only statements satisfying both conditions (Member A speaking while including their own name) are returned, which is far fewer than either alone (measured: speaker=石原慎太郎 alone: 2,098 items / combined: 647 items). Use speaker alone for all statements by Member A, and any alone for references to A. For usage by intent, see the relevant section in parameters.md and recipes/speaker-vs-any-disambiguation.md.
  9. (19004)startRecord out of range refers to numberOfRecords of the same query: The error message (19004)startRecord には 1 から検索件数までの値を指定してください。 means that the "number of search results" refers to numberOfRecords from the same query (measured, not explicitly in official specification). Determining startRecord from another query (simple search without from/until, speaker alone vs combined, previously cached values) will trigger error 19004. To isolate the cause, send a single request with startRecord=1&maximumRecords=1 using the same query and re-check numberOfRecords. This frequently occurs in cases of intersection (item 8) or when adding from/until reduces the count (see api-reference.md's 19004 explanation for details).

Common Search Pattern Examples

Statements by a member within a specific period

bash scripts/search-by-speaker.sh 石破茂 2024-10-01 2024-10-31 100 --sort date-desc

Tracking bill deliberation (chronological)

bash scripts/search-by-keyword.sh マイナンバー法 2023-01-01 '' 100 --sort date-asc

Extracting Prime Minister's speeches

The speakerPosition argument is not supported by the wrapper, so use raw curl:

# Not supported by wrapper; use raw curl
curl -s 'https://kokkai.ndl.go.jp/api/speech?speakerPosition=%E5%86%85%E9%96%A3%E7%B7%8F%E7%90%86%E5%A4%A7%E8%87%A3&nameOfMeeting=%E6%9C%AC%E4%BC%9A%E8%AD%B0&from=2024-01-01&recordPacking=json'

Witness questioning

bash scripts/search-by-role.sh 参考人 2024-01-01 '' 100 --sort date-desc

Full minutes of a specific meeting (two-stage)

# Step 1: Identify issueID (nameOfHouse filter not supported by wrapper; manually select from the list)
bash scripts/list-meetings.sh 予算委員会 2024-03-01 2024-03-01 50 --sort date-desc

# Step 2: Fetch full text
bash scripts/fetch-meeting.sh <issueID>

Pagination

Common to all endpoints.

  • Pass nextRecordPosition from the response as startRecord for the next request
  • Determining the last page:
    • JSON: nextRecordPosition value is null
    • XML: The <nextRecordPosition> element itself is absent
  • Leave intervals of several seconds for sequential retrieval (rate limit)

Output Format

Recommended format when presenting statements to the user:

【Speaker】○○○○ (Affiliated faction / Title)
【Meeting】XXXth Diet, House of ○○, ○○ Committee, No. X (YYYY-MM-DD)
【Statement】
Quotation of the speech text (normalize CRLF to line breaks)

【Source】National Diet Minutes Search System https://kokkai.ndl.go.jp/txt/<issueID>/<speechOrder>

When presenting a meeting list:

【Meeting List】N items
- YYYY-MM-DD: XXXth Diet, House of ○○, ○○ Committee, No. X
  https://kokkai.ndl.go.jp/txt/<issueID>
- ...

Cases Requiring Raw curl

The following parameters are not covered by wrapper scripts. When needed, call the API directly with curl / Invoke-RestMethod:

  • sessionFrom / sessionTo (session number filter)
  • contentsAndIndex / supplementAndAppendix (table of contents, index, appendix)
  • closing=true (closed session review only)
  • Secondary filters like nameOfHouse / nameOfMeeting (not included in wrapper arguments)
  • Pagination (sequential calls with startRecord + nextRecordPosition)
  • Simultaneous specification of any and speaker (for intentional intersection, e.g., self-reference by a member; see recipes/speaker-vs-any-disambiguation.md pattern 3)

Example: Extracting only Budget Committee meetings from the 213th Diet (requires sessionFrom/sessionTo, not supported by wrapper)

curl -s 'https://kokkai.ndl.go.jp/api/meeting_list?sessionFrom=213&sessionTo=213&nameOfMeeting=%E4%BA%88%E7%AE%97%E5%A7%94%E5%93%A1%E4%BC%9A&maximumRecords=30&recordPacking=json'

Tools that interpose an internal summarization model (e.g., WebFetch) have been observed to hallucinate fields not present in the response. Do not use them for raw data acquisition (see response-format.md for details).

Detailed References

  • api-reference.md: Endpoint specifications, pagination, error responses
  • parameters.md: Full specification of search parameters, search methods, combination examples
  • response-format.md: Response structure, actual JSON samples, measured pitfalls
  • recipes.md: Complex pattern collection (member × keyword filter, etc., cases not covered by scripts)

相关技能