はじめに
こんばんは、mirukyです。
Amazon ConnectのコンタクトフローをエクスポートしたJSONでGit管理していると、PRを出す前の差分確認で困ります。フローを少し変えただけでGitHubの差分が真っ赤かつ大量になり、本質的な変更が読み取りづらくなるんですよね。Amazon Connectを使用したプロジェクトでは、あるあるなのではないかと思います。もちろん、PRをレビューする側の負担も大きくなります。
JSONの差分を取るツールは昔からありますが、Amazon Connectに合った形でビジュアル的にわかりやすく出力してくれるものは多くありません。なら、AIを使いましょう。
この記事では、基本的にPRを出す側の視点で、エクスポートしたフローのJSONからdevelopブランチとの分岐点以降の差分を取り、Mermaidの図として見る方法を紹介します。この方法を使えば、結果的にレビュアーの負担も軽減することができます。
着想はAWS公式のサンプルから得ていますが、結局のところプロンプト1個です。AWSサンプルではAmazon Bedrockを経由していますが、この記事では手軽さ重視で手元のClaudeやCodexを使って実現します。この記事では、Codex CLI(gpt-5.5)とClaude Opus 4.8の両方で同じJSONとプロンプトを試し、出力の見え方も比べます。
目次
- 生のJSON差分がレビューしづらい理由
- 着想元のAWSサンプルの中身
- ローカルのLLMでdevelopブランチとの差分をMermaid化する
- セットアップと実行手順
- 実践、Codex CLI(gpt-5.5)
- 実践、Claude Opus 4.8
- Claude Opus 4.8とCodex CLI(gpt-5.5)を比べる
- 実務で使うときはどうすればよいか
1. 生のJSON差分がレビューしづらい理由
前提とする運用はシンプルです。コンタクトフローをJSONエクスポートしてGitHubで管理し、デプロイはAmazon Connectインスタンス上で手動で実行します。featureブランチで作業してdevelopブランチに集約し、PRを出す前にローカル段階で変更を把握したい、というものです。
ところがコンタクトフローのJSONは、各アクションが一意の Identifier を持ち、Metadata にデザイナー上の座標を持ちます。このためIDが振り直されたりブロックを動かしたりするだけで、ロジックが同じでも差分が大量に発生します。文言を1つ変えただけでも次のようになります。
{
- "Identifier": "a1b2c3d4-1111-1111-1111-111111111111",
+ "Identifier": "f9e8d7c6-9999-9999-9999-999999999999",
"Type": "MessageParticipant",
- "Parameters": { "Text": "mirukyコンタクトセンターへようこそ" }
+ "Parameters": { "Text": "mirukyコンタクトセンターへお電話ありがとうございます" }
},
"ActionMetadata": {
- "a1b2c3d4-1111-1111-1111-111111111111": { "position": { "x": 320, "y": 20 } }
+ "f9e8d7c6-9999-9999-9999-999999999999": { "position": { "x": 360, "y": 140 } }
}
文言が1つ変わっただけなのに、IDと座標がかなり邪魔になります。PRを出す側としても、どこが本質的な変更なのかを説明しづらくなります。アマコネ案件に従事した方は共感していただけるかと思うのですが、この作業は結構面倒くさいです。なので、差分を丁寧に追う前に、実際に動かして想定したフロー通りに動くかチェックしてOK、という確認に寄せたくなる場面もあります。
ただ、言うまでも無いですが、フローブロックが意図せず消えていてデグレている可能性もあるので普通に危険です(フローが繋がっていなければアマコネインスタンス上で警告がでますが、万が一繋がってしまっていれば気づけません)。
PRを出す前に、自分で差分を説明できる状態にしておくのが安全であり、結果的にレビュアーの負担軽減にも繋がります。
2. 着想元のAWSサンプルの中身
aws-samples は、AWSがGitHub上で公開しているサンプルコード集です。AWS Samplesの説明では、AWSサービスの具体的なユースケースやシナリオを示す教育用の実装例であり、サポート対象プロダクトそのものではない、とされています。
この中に、コンタクトフローの差分を可視化する connect-contact-flow-comparison-github-action があります。フローのJSONがpushされると起動し、直前のコミットと現コミットを比較してMermaid入りのHTMLレポートを出力するGitHub Actionです。内部ではGitHub API経由で変更前後のJSONを取得し、Amazon Bedrock上のClaude 3.5 Sonnetに比較を依頼しています。
下のREADMEでは、指定したコンタクトフローのディレクトリ配下に変更がpushされるとワークフローが動き、比較結果のHTMLとBedrock APIのメトリクスレポートをGitHub Actionsのartifactとして出力する流れが説明されています。
注目すべきは差分判定の本体 compare_contact_flows() で、やっているのは「①2つのJSONを読む」、「②比較を依頼するプロンプトを組む」、「③Bedrock経由でClaudeに投げる」、「④返ってきたコードブロックを保存する」の4つだけです。
与えられるプロンプトは「Mermaidで差分を描き、削除は赤、追加は緑、変更はオレンジにし、LambdaやキューのARNや名前まで漏れなく要約せよ」という内容です。
下の src/get_flows.py の compare_contact_flows() 周辺では、JSON読み込み、プロンプト生成、Bedrock呼び出し、生成されたHTMLの保存処理がまとまっています。
Bedrockの呼び出し、リトライ、トークン数やレイテンシのメトリクス収集は src/bedrock_utils.py 側に分かれています。
ここで重要なのは、 コンタクトフローを構造解析するコードが1行もない ことです。突き合わせも図の生成もLLMに任せており、Bedrockの用途は言ってしまえばClaudeを動かすだけの場所です。そのため、手元のClaudeやCodexで同じプロンプトを動かせば、同じ考え方をローカルでも再現できます。
3. ローカルのLLMでdevelopブランチとの差分をMermaid化する
AWSサンプルがCIとBedrockで行っていた処理を、ローカルのgitとLLMエージェントに置き換えます。
比較の起点を直前コミットではなくdevelopブランチとの分岐点にするのがポイントで、ブランチ全体の変更を未コミットの状態でも見られます。さらにLLMに比較させると、 IDや座標のゆらぎを無視して意味的な差分だけを抜き出せる ため、PRを出す前のセルフレビューと説明準備がかなり楽になります。しかも、これをPRのdescription(コメント)に貼れば、レビュアーも確認が楽になるでしょう。
4. セットアップと実行手順
ここでやることは、比較用に 変更前のJSON と 変更後のJSON を2つ用意し、それをClaudeやCodexに渡すことです。
この記事では、次の状態を前提にします。
- コンタクトフローのJSONをGit管理している
- 作業ブランチはfeatureブランチ
- 比較元はdevelopブランチとの分岐点
- 変更したJSONはまだコミット前でもよい
- 手元でClaude CodeまたはCodex CLIを使える
4-1. 変更されたJSONを探す
まず、developブランチと今の作業ブランチがどこで分かれたかを取得します。
BASE=develop
MB=$(git merge-base "$BASE" HEAD)
MB は、developブランチと現在のブランチの分岐点です。ここを比較元にすると、コミット済みの変更だけでなく、作業ツリーに残っている未コミットの変更もまとめて見られます。
次に、分岐点から見て変更されたJSONを一覧します。
git diff --name-only "$MB" -- '*.json'
たとえば、次のような結果が出たとします。
backend/connect/dev/CustomerLookup-AI-Analyzer.json
このファイルを、比較対象のコンタクトフローJSONとして扱います。
4-2. 変更前と変更後のJSONを作る
既存フローを変更した場合は、developブランチとの分岐点にあるJSONと、現在の作業ツリー側のJSONをそれぞれファイルに出します。
FLOW_PATH=backend/connect/dev/CustomerLookup-AI-Analyzer.json
git show "$MB:$FLOW_PATH" > flow.base.json
cp "$FLOW_PATH" flow.current.json
ここで作っているファイルは、次の2つです。
-
flow.base.jsonは、developブランチとの分岐点にある変更前JSON -
flow.current.jsonは、現在の作業ツリー側の変更後JSON
既存フローの比較なら、この2ファイルをLLMに渡せば準備完了です。
4-3. 新規フローの場合は空JSONを使う
新しく追加したフローは、developブランチとの分岐点側にファイルが存在しません。その場合、git show は失敗します。
新規フローとして比較したい場合は、変更前を空のJSONにします。
FLOW_PATH=backend/connect/dev/new-inquiry-flow.json
printf '{}\n' > flow.base.json
cp "$FLOW_PATH" flow.current.json
プロンプト側で「Flow1が空なら新規作成として扱う」と指示しておけば、すべて追加扱いでMermaid化できます。
4-4. ClaudeやCodexに渡す
最後に、flow.base.json と flow.current.json をClaude CodeまたはCodex CLIに読み込ませ、次のプロンプトを渡します。AWSサンプルの指示を流用しつつ、出力先をMermaidとMarkdownに変えています。
2つの Amazon Connect コンタクトフロー JSON(変更前=Flow1/developブランチとの分岐点側、変更後=Flow2/作業ツリー側)を比較し、
差分を1つの flowchart TD と変更サマリで出力してください。
要件:
- 削除は赤、追加は緑、変更(パラメータや遷移の変化)はオレンジで色分けする
- InvokeLambdaFunction / InvokeFlowModule / TransferContactToQueue は名前やキューをノードに明記する
- 分岐(GetParticipantInput 等)はひし形にし、エッジに条件をラベル付けする
- 削除された遷移は赤の破線、追加された遷移は緑のエッジにする
- 変更サマリは ARN・キューID・Lambda名・文言・遷移の張り替え(旧→新)まで漏れなく書く
- Identifier や position は無視し、種類とパラメータと遷移で意味的に対応づける
- Flow1 が空なら新規作成として全て追加扱いにする
- 末尾に classDef added / changed / removed を付ける
- Mermaidは connect-flow-diff.mmd、変更サマリは connect-flow-diff.md に出力する
Flow1: <<< flow.base.json >>>
Flow2: <<< flow.current.json >>>
実際には、作業ディレクトリに flow.base.json と flow.current.json を置いた状態で、Claude CodeやCodex CLIに「この2ファイルを読んで、上のプロンプトどおりに差分を出してください」と依頼するだけです。
毎回貼るのが手間なら、エージェントに手順ごと覚えさせます。Claude Codeなら ~/.claude/skills/amazon-connect-flow-diff/SKILL.md に、Codexならプロジェクト直下の AGENTS.md に、上のgit手順とプロンプトを書いておけば、コンタクトフローの差分を頼むだけで動きます。
5. 実践、Codex CLI(gpt-5.5)
題材として、CustomerLookup-AI-Analyzer.json というコンタクトフローを使います。
今回の変更は、Lambdaのエラー時遷移です。
変更前は、ConnectCustomerLookup (Lambda)の エラーが通常の挨拶メッセージへ戻っていました。変更後は、エラー案内メッセージを再生してから切断する専用ルートへ張り替えています。
まず、GitHubの差分だけを見ると、IDや座標の変更が多く見えます。
この差分だけでも読めないわけではありませんが、conditionMetadata.id や position の追加が混ざるため、実際にどの遷移が変わったのかは追いづらいです。
そこで、flow.base.json と flow.current.json を用意し、Codex CLIに第4章のプロンプトを渡しました。
Codexは connect-flow-diff.mmd と connect-flow-diff.md を生成しました。生成されたMermaidは全体フローを含んでいましたが、記事では差分が分かる主要部分に絞って掲載します。
出力された変更サマリも、GitHubのJSON差分よりかなり読みやすくなりました。
概要
Lambda ConnectCustomerLookup のエラー時遷移が、
通常の挨拶メッセージへ戻るルートから、
エラーメッセージを再生して切断する専用ルートへ張り替えられました。
追加
- MessageParticipant
- 文言: エラーが発生しました。もう一度電話をかけ直してください。
- 遷移: NextAction / NoMatchingError -> DisconnectParticipant
- DisconnectParticipant
- 用途: エラー案内後の切断
変更
- InvokeLambdaFunction
- Lambda名: ConnectCustomerLookup
- 遷移の張り替え:
- 旧: NoMatchingError -> MessageParticipant「お電話ありがとうございます。」
- 新: NoMatchingError -> MessageParticipant「エラーが発生しました。もう一度電話をかけ直してください。」
削除
- 削除ノード: なし
- 削除された遷移:
- InvokeLambdaFunction ConnectCustomerLookup / NoMatchingError -> MessageParticipant「お電話ありがとうございます。」
GitHubの差分ではIDや座標変更に埋もれていましたが、Codexの出力では「Lambdaのエラー時遷移が変わった」「エラー案内メッセージと切断が追加された」という論理的な差分に整理されています。
実際に生成されたMarkdownには、Lambda ARN、Lex Alias ARN、TransferContactToQueue と InvokeFlowModule が差分該当なしであることも記録されていました。
6. 実践、Claude Opus 4.8
Claude Opus 4.8でも、同じ flow.base.json、flow.current.json、プロンプトを使って確認しました。入力条件はCodex版と同じです。違うのは、実行するエージェントだけです。
Claudeも無事 connect-flow-diff.mmd と connect-flow-diff.md を生成してくれました。Claude側の出力は、差分だけを短くまとめるというより、既存のコンタクトフロー全体を残したうえで、追加・変更・削除された遷移を色で示す形式でした。
記事掲載用に少し短くすると、次のような図になります。
Claudeの図で読み取りやすいのは、通常フローを残しながら、Lambdaエラー時の旧経路と新経路を同じ場所に並べている点です。NoMatchingError が以前は通常挨拶に流れていたこと、変更後はエラー案内に流れることが、図だけで追いやすくなっています。
検出結果としては、Codexと同じく次の変更を拾えています。
-
MessageParticipantのエラー案内文言が追加された -
DisconnectParticipantが追加された -
InvokeLambdaFunctionのNoMatchingError遷移が張り替えられた - 旧遷移である
NoMatchingError -> お電話ありがとうございます。が削除された
出力されたサマリを記事向けに整えると、次の内容です。
Claude側の生成結果
追加
- MessageParticipant
- 文言: エラーが発生しました。もう一度電話をかけ直してください。
- 遷移: NextAction / NoMatchingError -> DisconnectParticipant
- DisconnectParticipant
- 用途: エラー案内後の切断
変更
- InvokeLambdaFunction
- Lambda名: ConnectCustomerLookup
- 旧: NoMatchingError -> MessageParticipant「お電話ありがとうございます。」
- 新: NoMatchingError -> MessageParticipant「エラーが発生しました。もう一度電話をかけ直してください。」
削除
- 削除されたアクション: なし
- 削除された遷移:
- InvokeLambdaFunction ConnectCustomerLookup / NoMatchingError -> MessageParticipant「お電話ありがとうございます。」
Claude側で特に良かったのは、IDだけが変わったアクションを「意味的に同一」として分けていた点です。Amazon ConnectのJSONではIDが変わるだけでGit差分が大きく見えるため、PRで説明すべき差分と、見なくてよい差分を分けてくれるのは実務上かなり助かります。
一方で、Claudeが生成したMermaidは全体フローを細かく含んでいたため、そのままPR説明欄や記事に貼るには少し長めでした。とはいえ、検出した内容はCodex版と同じです。実務上は、ClaudeでもCodexでも問題なく使えます。
7. Claude Opus 4.8とCodex CLI(gpt-5.5)を比べる
同じ入力とプロンプトでも、エージェントによって図の作り方やサマリの粒度は変わります。今回の検証では、Claude Opus 4.8もCodex CLI(gpt-5.5)も本質的な差分を拾えました。
結論としては、 どちらを使っても問題ありません 。違いが出るのは、検出精度というより、出力の見せ方と要約の粒度です。
画像のとおり、変更検出と遷移の理解はどちらも問題ありませんでした。違いは、Claudeは全体フロー寄りで少し詳しく、Codexは差分中心で短めにまとまりやすい点です。PR前のセルフレビューという目的であれば、どちらを使っても十分です。
LLMで比較させる以上、出力は実行ごとに少しゆれます。PRを出す前の確認では、図だけに頼らず元のJSON差分とあわせて確認することをおすすめします。
8. 実務で使うときはどうすればよいか
この方法は、PRを出す前のセルフレビューとして使うのが一番自然です。動作確認する前に、Git上で「どのブロックが増えたのか」「どの遷移が変わったのか」をざっくり把握できます。
また、PR作成者が差分の要点を図と短いサマリで添えておけば、レビュアーは生のJSON差分を最初から全部追わなくても、確認すべき箇所に入りやすくなります。
8-1. PRには短い図と要約だけ添える
PRを出す側としては、ClaudeやCodexが出した内容をそのまま全部貼るより、次の3点に絞るのが読みやすいです。
- Mermaid図
- 追加、変更、削除の短いサマリ
- 確認してほしい遷移

今回の例なら、「Lambdaエラー時の NoMatchingError が通常挨拶ではなくエラー案内へ向くようになった」と分かれば十分ですね。
8-2. ローカル確認とCI確認を分ける
手元で素早く確認するなら、Claude CodeでもCodex CLIでも十分です。flow.base.json と flow.current.json を作り、プロンプトを投げれば、数分でPR説明用の図とサマリを作れます。
チーム全体で同じ形式のレポートを残したい場合は、第2章のAWSサンプルActionのようにGitHub Actionsへ寄せるほうが運用しやすいです。ローカル確認はPR作成者のセルフレビュー、CI確認はチーム共通の補助資料、という感じの使い分けがおすすめです。
8-3. 巨大なフローは範囲を絞る
大きいコンタクトフローを丸ごと渡すと、図が大きくなりすぎます。トークン上限に近づくこともありますし、図が読みにくくなることもあります。
その場合は、変更されたアクションと、その前後の遷移だけを抜き出して渡します。全体フローを自分で確認したい場合でも、PRに添える図は差分の周辺に限定したほうが伝わりやすくなります。
8-4. 公開前にマスクする
実際の運用では、生成したMarkdownをそのままPRやドキュメント(Confluence等のラフなドキュメント)へ貼る前に、公開してよい情報だけが残っているか確認します。特に、LLMは「変更サマリに含めてほしい」と頼んだ項目を素直に書き出すため、便利な一方で確認漏れが起きやすいです。
おわりに
ここまでお読みいただきありがとうございます。
今回の要点です。
- Amazon ConnectのフローはIDや座標のノイズで、生のJSON差分がレビューしづらい
- AWSサンプルの比較ツールの本体をプロンプト1個に分解できたため、ローカルでも小さく再現できた
- 同じプロンプトを手元のClaudeやCodexで動かせば、developブランチとの分岐点以降の差分をMermaidで可視化でき、PR前のセルフレビューに使える
- ClaudeでもCodexでも実務上は問題なく、違いは図の見せ方とサマリの粒度だった
まずは手元のフロー1つで試してみてください。
ではまた、お会いしましょう。
参考リンク
Amazon Connect
ツール
- aws-samples/connect-contact-flow-comparison-github-action - GitHub
- README.MD - aws-samples/connect-contact-flow-comparison-github-action
- get_flows.py - aws-samples/connect-contact-flow-comparison-github-action
- bedrock_utils.py - aws-samples/connect-contact-flow-comparison-github-action








