AI会議メモをGoogleカレンダー登録前にPythonで検査する
会議メモから予定を作るなら、登録処理より先に日時を検査する仕組みを入れた方がいいです。カレンダーAPIは形式が合っていれば予定を受け付けます。開始より終了が早い予定でも、意図が違っていても止めてくれません。
音声で会議を記録し、そのまま日程調整まで進める機能が増えました。便利になるほど、予定の誤登録は目立たずに残ります。営業なら先方との打ち合わせを30分ずらしたつもりが、社内レビューを上書きしていた、くらいで十分困ります。
今日、検査用のJSONを流したら、開始が10:00で終了が9:30というデータがそのまま引っかかりました。画面で読むと気づきにくいのに、条件にすると一発です。ここ地味に効きます。
この記事では、会議メモから抜き出した予定をJSONにし、Google Calendarへ渡す前にPythonだけで止める方法を置いておきます。外部サービスへの書き込みはしません。
先に決めるのは「予定のJSON」の形
会議メモの文章をそのまま登録対象にすると、検査する側がつらくなります。抽出する段階で、次の4項目だけをJSON配列にそろえます。
[
{
"title": "A社 定例",
"start": "2026-07-25T10:00:00+09:00",
"end": "2026-07-25T10:30:00+09:00",
"attendees": ["tanaka@example.com"]
}
]
日時は YYYY-MM-DDTHH:MM:SS+09:00 のISO 8601形式に固定します。2026/7/25 10時 のような表記を残すと、月日やタイムゾーンの解釈が後段まで持ち越されます。
カレンダーの予定は、後から直せても相手の時間までは戻せません。ここだけは文章の自然さより、機械で読める形を優先します。
会議メモを要約するツールには、こんな指示を足しています。
会議メモから予定だけを抽出してください。
title、start、end、attendees を持つ JSON 配列だけを返します。
start と end は ISO 8601 形式で、必ず UTC オフセットを付けます。
日付・時刻・参加者のどれかが曖昧な予定は配列に入れません。推測で補わないでください。
曖昧な予定を自動登録しない、と先に決めるのが肝です。抽出件数は少し減りますが、確認待ちの方が誤登録より安いです。
登録の前に止めるPythonスクリプト
この図の meeting_guard.py までを、予定登録の直前に挟みます。
# meeting_guard.py
import json
import sys
from datetime import datetime, timedelta
REQUIRED = ("title", "start", "end")
def parse_datetime(value):
if not isinstance(value, str):
raise ValueError("日時が文字列ではありません")
if value.endswith("Z"):
value = value[:-1] + "+00:00"
dt = datetime.fromisoformat(value)
if dt.tzinfo is None:
raise ValueError("タイムゾーンがありません(例: +09:00)")
return dt
def validate(events):
errors = []
for index, event in enumerate(events, start=1):
missing = [key for key in REQUIRED if not event.get(key)]
if missing:
errors.append(f"{index}件目: 必須項目がありません: {', '.join(missing)}")
continue
try:
start = parse_datetime(event["start"])
end = parse_datetime(event["end"])
except ValueError as exc:
errors.append(f"{index}件目: {exc}")
continue
if end <= start:
errors.append(f"{index}件目: 終了日時が開始日時より前です")
if end - start > timedelta(hours=8):
errors.append(f"{index}件目: 8時間を超える予定です")
if not event.get("attendees"):
errors.append(f"{index}件目: 参加者が空です")
return errors
if __name__ == "__main__":
if len(sys.argv) != 2:
raise SystemExit("使い方: python3 meeting_guard.py events.json")
with open(sys.argv[1], encoding="utf-8") as file:
events = json.load(file)
errors = validate(events)
if errors:
print("登録を止めました。")
print("\n".join(f"- {error}" for error in errors))
raise SystemExit(1)
print(f"{len(events)}件を確認しました。登録してよい予定です。")
たとえば、次の2件を events.json に入れて実行します。
[
{"title": "A社 定例", "start": "2026-07-25T10:00:00+09:00", "end": "2026-07-25T09:30:00+09:00", "attendees": ["tanaka@example.com"]},
{"title": "企画レビュー", "start": "2026-07-25T13:00:00", "end": "2026-07-25T14:00:00", "attendees": []}
]
python3 meeting_guard.py events.json
手元での出力です。
登録を止めました。
- 1件目: 終了日時が開始日時より前です
- 2件目: タイムゾーンがありません(例: +09:00)
1件目のような予定は、Calendar API側から見れば日時の文字列として正しいため、通ってしまうことがあります。2件目も同じです。日本時間で登録したつもりでも、実行環境や連携先の既定タイムゾーンで別の時刻になる余地が残ります。
なお、8時間の上限は僕の例です。終日研修を登録するチームなら、12時間に変えるか、この条件を外してください。業務ルールをコードに置く時は、正解を決め打ちしない方が長く使えます。
Calendar APIの成功だけでは足りない理由
APIが返す成功は「受け取った」という意味です。「会議メモの意図どおり」は含みません。だから、登録前の検査と、登録後に人が確認する表示を分けています。
このスクリプトで止められるのは、必須項目の欠落、終了時刻の逆転、タイムゾーン抜け、長すぎる予定、参加者の空欄です。既存予定との重複や、参加者のメールアドレスが正しいかまでは判断しません。その二つは、カレンダーの空き時間照会や社内の連絡先台帳と照合する段階で足せます。
最初から全部を自動化しようとすると、例外処理が先に膨らみます。まずは壊れると痛い条件だけ止める。この順番が現場では回しやすいです。
現場では、登録ボタンの手前に置く
この検査を通ったJSONだけを、GASやZapier、Calendar APIへ渡します。エラーなら通知を出して、元の会議メモに戻す。予定を作る処理とは別の小さな工程にしておくと、後から条件を足しても影響範囲が狭くなります。
会議メモの自動化は、要約の精度だけで評価しがちです。でも業務で効くのは、間違った予定を登録しないことです。登録前の数十行があるだけで、安心して自動化を広げられる範囲が変わります。