sattoで会議招集をサッと終わらせる

これは ["satto | 生成AIエージェント Advent Calendar 2024"](https://qiita.com/advent-calendar/2024/satto) の24日目の記事です。



# はじめに
sattoのアプリノードでは、Googleサービスと簡単に連携することが可能です。
今回は、Googleカレンダーとスプレッドシートを活用して、スプレッドシートで設定した人にインビテーションを送るスキルを作ろうと思います。


# 想定読者
 - sattoユーザー
 - 会議招集を楽にしたい方

# アウトプットイメージ
スプレッドシートでメーリングリスト及びリストの概要を設定することで、コンテキスト（インプットとなるデータ）から対象リストを予測（選択）して会議通知を行います。

https://x.com/3_nipa/status/1866854121904763002


# フロー図
```mermaid
flowchart TB
    A[インプット] --> B[AI：スケジュールの概要生成]
    B[AIノード①：スケジュールの概要生成] --> C[スプレッドシート：メアドリスト抽出]
    C[スプレッドシート：メアドリスト抽出] --> D[AIノード：グループ抽出＆グループ特定]
    D[AIノード②：グループ抽出＆グループ特定] --> E[AI：メアド抽出（スプレッドシートから取得したもの）]
    E[AI：メアド抽出（スプレッドシートから取得したもの）] --> F[AI：参加者整形（データ整形）]
    F[AI：参加者整形（データ整形）] --> G[Googleカレンダー：カレンダー追加]
```


# 実際に作っていくよー！
## インプットノード
パラメータは3つセットしています。
- スケジュール件名
    - パラメータの説明：スケジュール登録する際のスケジュール件名を抽出する
- スケジュール開始日時
    - パラメータの説明：スケジュール登録する時の開始日時を抽出する
- スケジュール終了日時
    - パラメータの説明：スケジュール登録する時の終了日時を抽出する。もし開始日時しかなければ開始日時の１時間後を終了日時とする

## AIノード①：スケジュールの概要生成
このノードでは、コンテキストのテキストもしくは画像からスケジュールの概要を出力するためのノードです。

```
"{{CONTEXT.TEXT}} {{CONTEXT.IMAGE}} "から{スケジュールの概要}の内容だけを生成しなさい

# スケジュールの概要
- スケジュールの件名の補足事項だけを出力しろ。
- 何もない場合は、" "空白を入れてください。

### 補足
- 指示の復唱はしません。
- 自己評価はしません。
- 結論やまとめは書きません。
- 最終成果物以外は出力しません。
```

## スプレッドシート：メアドリスト抽出
このノードでは、スプレッドシートからメールアドレスのリストを取得することができます。

```
メソッド：GET
リクエストURL：https://sheets.googleapis.com/v4/spreadsheets/<SPREADSHEET_ID>/values/<SHEET_NAME>!A2:D
```


## AIノード②：グループ抽出
このノードでは、スプレッドシートから取得した情報を整形/必要な情報を抽出するノードです。

```
{{スプシの結果}} の中で、ユニークなカテゴリ（最初の要素）を順番通りに抜き出して、{アプトプット形式}のような2次元リストを出力してください。

# アウトプット形式
[["グループA","グループAの説明"],["グループB", "グループBの説明"],["グループC","グループCの説明"]]

### 補足
- 指示の復唱はしません。
- 自己評価はしません。
- 結論やまとめは書きません。
- 最終成果物以外は出力しません。
```


## AIノード③：グループ特定
このノードでは、グループ名を特定/予測していきます。
今回は、予測できなかった場合にデフォルトで送られるグループを用意することにしました。
→ 自分だけにすることで失敗しても影響範囲を小さくすることができます。
```
# 命令
- {#データベース}の中から{#ユーザの入力}に近しいグループ名だけを1つ選択しなさい。近しいものがない場合は、デフォルトのものを選択してください。

# データベース
{{グループ抽出の結果}}

# ユーザ入力
"{{CONTEXT.TEXT}}{{CONTEXT.IMAGE}}"

### 補足
- 指示の復唱はしません。
- 自己評価はしません。
- 結論やまとめは書きません。
- 最終成果物以外は出力しません。
```

## AIノード④：メアド抽出
取得したスプレッドシートの情報からメールアドレスだけを抽出するノードです。
インプットになるデータの構造を伝えることで、（肌感覚ですが）精度が上がります。

```
#命令
- {#データベース}の中から{#ユーザの入力}のに該当するメールアドレスを全て抽出してください。

#データベースの説明
- {{スプシの実行結果}} のvaluesには、スプレッドシートに蓄積されているデータが入っています。

#データベース内のvaluesの説明
[["グループ名","グループ名の説明","氏名","メールアドレス"],["グループ名","グループ名の説明","氏名","メールアドレス"]]のような配列になっています。

### 補足
- 指示の復唱はしません。
- 自己評価はしません。
- 結論やまとめは書きません。
- 最終成果物以外は出力しません。

#データベース
{{スプシの実行結果}}

#ユーザの入力
{{グループ特定の結果}}
```


## AIノード⑤：参加者整形
ここでは、GoogleカレンダーのBodyに組み込める形式（2次元配列）に整形して、インビテーションを送れる用にします。

```
# 命令
{input}のメアドを{アウトプット形式}に合わせた2次元配列の形式で出力してください。

# input
{{メアド抽出の結果}}

# アウトプット形式
[{"email":"メールアドレス1"},{"email":"メールアドレス2"}]

### 補足
- 指示の復唱はしません。
- 自己評価はしません。
- 結論やまとめは書きません。
- 最終成果物以外は出力しません。
```

## Googleカレンダー：カレンダー追加
実際に、スケジュールの件名、概要、開始日時、終了日時、参加者の情報をGoogleカレンダーに送ります。
```
メソッド：POST
リクエストURL：https://www.googleapis.com/calendar/v3/calendars/primary/events
Header：{"Content-Type":"application/json"}
Body：
{
    "summary":"{{スケジュールの件名}}",
    "description":"{{スケジュールの概要生成の出力結果}}",
    "start":{"dateTime":"{{スケジュールの開始日時}}"},
    "end":{"dateTime":"{{スケジュールの終了日時}}"},
    "attendees":{{参加者整形の出力結果}}
}

```

## AIノード⑥：出力用
このAIノードでは、カレンダーの実行結果を出力（確認）用として出力するノードです。
```
# input
{{カレンダーの実行結果}}

# 成果物
Input内容からスケジュール登録した場合、スケジュールの件名、詳細、開始日時、終了日時を出力する
なお、スケジュール登録が失敗したら失敗したことを伝える

# 注意事項
- 指示の復唱はしません。
- 自己評価はしません。
- 結論やまとめは書きません。
- 成果物のみ出力する
```


# 最後に
1つのAIノードでたくさんの指示・処理を行うことで回答の正確さを失う可能性があります。
今回はその出力結果の正確性を担保するために、1つのAIノードになるべく小さなタスク/指示を行うことで精度を担保することができました。
また、sattoのスキルの中にメールアドレスをハードコーディング（直接アドレスを記載）するのではなく、スプレッドシートの情報を基にすることで柔軟に追加削除することが可能になります。

sattoの活用例は、Xの[#satto_skill](https://x.com/search?q=%23satto_skill&src=typeahead_click&f=live)で閲覧することができます
色々なサービスとAPI連携して、ぜひ独自のスキルを作成してみてください。
もちろん、作ってみたらXにて#satto_skillで投稿も楽しみにしてます！