
【ServiceNow PDI】Integration HubのカスタムスポークでGeminiへ質問を投げられる「何でも相談フォームアプリ」の実装手順まとめ
ServiceNowが提供する開発者学習向け無償のPDI環境では、残念ながらServiceNowの生成AI機能である「Now Assist」が利用できません。
そこで、「PDIでもお手軽に生成AI機能を呼び出して、お役立ちアプリがさくっと簡単に作れると良いなぁ」と考え、今回の投稿にて、ServiceNowのIntegration HubカスタムスポークからGemini API経由で生成AIのGeminiに質問が投げられるアプリの作成にチャレンジしたいと思います。
今回作成するアプリに含まれる機能は以下です。
・Workspaceのフォーム画面から問い合わせを行い、フロー経由でGoogle APIへ問い合わせを実施
・JSONで受領した回答を抽出し、Workspace画面の回答フォームへ表示
1.アプリの開発環境と準備
今回のアプリは、PDIのZurichバージョンで作成を行いました。
以前の投稿と同様に、Integration Hub Enterprise Packプラグインを有効化しておきます。
※プラグインの有効化は以下投稿を参考にしてください。
続いて、Google APIが利用できるように、GoogleのAPIキーを取得しておきます。まずGoogleのアカウント取得が必要です。Googleへログインを行ってから、以下のAPIキー取得用のURLへアクセスします。
ここで、プロジェクトを作成し、[APIキーを作成]ボタンで作成します。


APIキーを後ほどIntegraton Hubのスポークに貼り付けて利用するので、どこかに退避しておきます。

2.問い合わせフォーム用アプリの作成
本投稿では、すっかりお馴染みとなりました、App Engine Studio(AES)でアプリを簡単に作成してゆきます。
では、App Engine Studio画面を起動します。
ファイルナビゲータより、[app e]と入力し、リストされた[App Engine Studio]メニューを選択します。

App Engine Studio画面の[アプリを作成]より今回利用するアプリケーションの作成を開始します。

カスタムアプリケーションの設定は以下のような形です。
・アプリケーション名:Ask Gemini Anything
・ロール定義:admin、user


アプリケーションの器ができたので、続けてカスタムテーブルを作成してゆきます。
データメニューの[追加]よりカスタムテーブルを追加します。



・テーブルラベル:Ask Gemini Anything
・自動番号を有効化
・プリフィックス:ASKGEMI


テーブル作成完了後に、フィールドを2つ追加します。
・問い合わせフォーム:Geminiへの質問入力用途
・回答フォーム:Geminiからの回答表示用途
※双方のフィールドの最大長は、できる限り大き目のサイズで指定しておいてください。とくに、回答フォームには、Geminiからの回答文が入ってくる予定です。

続けて、アプリ専用画面としてWorkspaceの作成を行います。
エクスペリエンス メニューの[追加]を押下します。


名前、URL、ロールをそのまま受け入れて、[続行]を押下します。

テーブルはカスタムテーブルが指定されているので、そのまま受け入れます。

WorkSpaceで表示させるフォームを作ります。
フォーム表示画面より、ビューを[Workspace Ask Gemini Anything 0]を切り替えます。※表示されないときは、ブラウザをリロードすることで表示されます。

問い合わせフォームと回答フォームの2つを配置します。

これでアプリ側は完成です。
3.Open AI接続を行うカスタムスポークの作成
Integration Hubのスポークを作成してゆきます。
ワークフロースタジオからスポークを作成します。

ワークフロースタジオの[新規]メニューより、[スポーク]を選択します。

アプリケーションスコープは、上記のステップで作成した「Ask Gemini Anything」を選択します。説明に、任意の文章を加えて、設定を進みます。

今回は、アクションデザイナーを使ってカスタムスポークを作成してゆきます。

アクションの定義画面に進み、[アクションを作成]メニューより、[アクションデザイナー]を選択します。

アクションの定義を行います。
・アクション名:Get Answer from Gemini
・アプリケーション:Ask Gemini Anything

アクションデザイナーで定義するステップは以下の4つです。
①入力変数の定義:アプリからGeminiへ問い合わせる質問の受け付け
②RESTステップ:Open AIへRESTを使って質問を送信し、応答を受領
③Scriptステップ:応答を抽出するための簡易ローコードステップ
※JSON Parserは今回は使わず、Scriptステップで対象要素をさくっと抜き出すローコードステップを実装して対応します。
④出力の定義:フローを介しアプリ側へ表示させる回答の受け付け
次に利用するREST電文の様式ですが、GoogleのGemini APIのリファレンスにあるREST様式(curlコマンド利用)のサンプルの以下を参考にします。
curl "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer GEMINI_API_KEY" \
-d '{
"model": "gemini-2.0-flash",
"messages": [
{"role": "user", "content": "Explain to me how AI works"}
]
}'※1. curl :REST ステップのベースURLに指定するURL
※2. content-Type:JSONを求めるヘッダー
※3. Authorization:APIキーを送付するためのヘッダー
※4. model:Geminiのモデルの選択。gemini-2.5-flashと設定すると、最新の2.5バージョンへの問い合わせも可能。
※5. message :content要素部分に質問内容を入れて要求を送信します。
では、①の入力変数を定義してゆきます。
[入力の作成]メニューより、入力変数を作成します。
・ラベル:Question、[タイプ]をString


②のREST APIステップを定義します。
入力変数ステップの下の[+]メニューを選択し、[REST]をアクションに追加します。

接続の詳細で、
・接続:インラインで接続を定義
※今回は、REST APIのリクエスト内にAPIキーも含めて認証を通します。
・ベースURL:https://generativelanguage.googleapis.com/v1beta/openai/
要求の詳細で、
・リソースパス:chat/completions
・HTTPメソッド:POST

次に、ヘッダー個所の定義です。
ここは大事なOpen AIへ接続するために重要なポイントのAuthorizationヘッダーがあるので、注意が必要です。
・Content-Type:application/json
・Authorization:Bearer XXXXXX
※Bearer文字後にスペースを入れ、XXXXXX部分に、先の手順で取得したAPIキー文字列を貼り付けます。この設定が不正だと、400エラーで応答され、応答を正しく受領できません。

続いて、要求本文(JSONペイロード)を定義します。
1)以下のサンプルを要求本文へ貼り付けます。
{
"model": "gemini-2.0-flash",
"messages": [
{"role": "user", "content": "Explain to me how AI works"}
]
}2)content要素部分の"Explain to me how AI works"文を削除して、そこに入力変数のデータピルより、Questionをドラッグ&ドロップで配置します。

ここまでの作業を保存しておきます。
この時点で、正しくOpen AIへ要求が投げられるかをテストします。
[テスト]ボタンを押下します。
・Question に簡単な質問内容を入力し、[テストを実行]を押下

実行後に作成された詳細レポートを確認します。
応答本文に期待する回答文字列が含まれていれば、Google Open AIへの接続が正しくできています。

この画面で、得られた応答本文部分をクリックします。
表示中 response_bodyがポップで開かれます。
・生のテキストタブを選択し、応答本文部分をコピーしてメモ帳などに退避しておきます。
※回答文字列を取り出す要素抽出に際して、参考になります。

③のScriptステップによる回答文字列の抽出と出力変数に代入する処理を作成します。
RESTステップ下の[+]より、Scriptステップを追加します。
今回利用はしないのですが、JSON Parserステップで取り出した応答の生テキストで構造化ペイロードビューで階層表示をさせてみます。
※この作業は行わなくて良いです。以下サンプルを参考にしてください。
choices[0] -> message -> contentに回答が含まれていることが分かりました。

Scriptステップへの入力変数を定義します。
・GeminiResponse:値に、REST Stepの応答本文をドラッグ&ドロップで配置
・スクリプトは以下サンプルを貼り付けます。
(function execute(inputs, outputs) {
// === JSONをパース ===
var json = JSON.parse(inputs.GemiResponse);
// === content要素を抽出 ===
var extract_output = json.choices[0].message.content;
// === 出力変数にセット ===
outputs.gemianswer = extract_output;
})(inputs, outputs);※1. JSON.parseステップには、入力変数値を指定
※2. 要素抽出に、先のJSON Parserで表示した階層ノードを参考に指定
※3. 出力変数として用意した、geminianswerへ回答を代入

画面下部へスクロールして、出力変数を定義します。
・GeminiAnswer : タイプをStringで作成

④の出力変数を定義します。
アクションステップの[出力]へ移動し、[出力の作成]より定義します。
・Gemini_Answer : タイプをStringで定義

出力の編集モードを無効化し、入力変数Gemini_Answerの値に、スクリプトステップで得られた変数のGemiAnswerをドラッグ&ドロップで配置します。

完了後に、スポークの[公開]を行います。Geminiへの質問を投げるシステム連携の機能部品が完成しました。
4.カスタムスポークを呼び出すフローの作成
ここからフローの作成を行ってゆきます。
AESのロジックと自動化メニューの[追加]より作成を開始します。

フローを定義します。
・フロー名:Ask Gemini Anything Flow
※フロー名は英数文字列で指定してください。
・実行方法:システムユーザー

Flow Designer編集画面で、フローステップを作成します。
トリガーの定義を行います。
・トリガー:レコードの作成時
・テーブル:カスタムテーブル「Ask Gemini Anything」を指定

アクションステップを追加してゆきます。
[アクション]追加より、カスタムスポークを指定します。
・検索フィールドでGeiminiと入力し、Ask Gemini Anythingに含まれるアクションの[Get Answer from Gemini]を追加

続いて、レコードの更新ステップを追加します。
・レコード:トリガーのRecordをドラッグ&ドロップで配置
・フィールド:回答フォームへ、スポークの呼び出しステップより受領できる変数Gemini_Answerをドラッグ&ドロップで指定

フローを保存し、[アクティブ化]します。
これでアプリケーションの作成は完了しました。
5.アプリケーションの動作確認
AESのWorkspaceをプレビューボタンで開きます。

新規レコード作成で、問い合わせフォームに質問事項を入力し、[保存]ボタンを押下すると、フォームの入力内容がGoogle Geminiへ問い合わせとして送信されます。

Geminiからの応答が受領されると、回答フォームのフィールドが更新されます。
※回答に時間を要す場合に、Geminiからの応答に遅延が入ることが考えられます。この場合、回答フィールドが更新されるまでモーダル状態にするか、一時的に「実行処理中」などのステータスをUI上に一時表示などの工夫を入れた方が良いかもしれません。

如何でしたでしょうか? ServiceNowのIntegration Hubにあるカスタムスポーク機能を使い、Gemini APIへ接続し、質問を投げて回答を受領できる簡易アプリを作成してみました。
PDI環境という条件でも生成AIが利用できるアプリが作成できるのは面白いという点、またカスタムスポークを使うことで、生成AIへの接続が簡単に行えるという点の2つを享受頂けたのではないでしょうか。
本投稿が、皆様のServiceNowのアプリ開発に際して参考にしていただければ幸いです。次回投稿も楽しみにお待ちください。