見出し画像

出勤状況AI報告ボット|Gemini API × Slack API × GAS

リモートワークの普及に伴い、多くの企業でSlackをはじめとするチャットツールでの勤怠報告が定着しています。これは業務開始を円滑にする一方で、新たな課題も生んでいます。報告時刻のばらつきや休暇連絡との混在により、メンバー同士で出勤状況を把握するには、確認が必要となるケースが少なくありません。特に、報告がないメンバーが休暇取得者なのか、あるいは報告を失念しているのかを判断するのは、見過ごされがちな管理コストとなっていました。

本稿では、これらの課題を解決するために開発した、Google Apps Script (GAS) と Gemini API、Slack API を活用した勤怠状況の自動レポートシステムについて、その仕組みを解説します。


システム概要

本システムは、Slackの勤怠報告チャンネルへの投稿を自動的に集計・分析し、日々の出勤状況を所定のチャンネルへレポートするものです。全体の処理フローは以下の通りです。

1. ログデータの蓄積
毎日定刻(AM 10:00)、GASがSlack APIを介して勤怠報告チャンネルの投稿を取得し、Googleドキュメントに時系列で記録します。

[09:44:45] オフィス勤務: <!here>
*`【出勤】`*2025年10月22日 9:44 JST
山田 花子 さんは*オフィス勤務*です。
本日午後から夏期休暇頂きます。

[09:51:27] 在宅勤務: <!here>
*`【出勤】`* 2025年10月22日 9:51 JST
山下 次郎 さんは*在宅勤務*です。

[09:52:05] オフィス勤務: <!here>
*`【出勤】`* 2025年10月22日 9:52 JST
鈴木 一郎 さんは*オフィス勤務*です。

2. 状況分析と判定
毎日定刻(AM 11:00)、別のGASが起動し、蓄積されたログデータと当日の出勤対象者リストを、プロンプトと共にGemini APIへ送信。APIは受け取った情報を基に、各メンバーの状況(出勤報告済み、休暇連絡済み、未報告)を判定します。

  1. レポートの自動生成・投稿: Gemini APIによる分析結果を基に、GASがレポートを整形し、指定されたSlackチャンネルへ自動投稿します。

  2. 営業日判定: Googleカレンダーを参照し、システムの実行を営業日のみに限定。土日祝日には稼働しない設計としています。

この自動化により、管理者は手作業での確認業務から解放され、報告の確認漏れやコミュニケーションコストの削減が期待できます。


システム構成と技術詳細

本システムの実現にあたり、以下の技術要素を連携させています。

1. Google Apps Script (GAS) による自動化

定時実行機能を活用し、Slack APIからログデータ取得、Googleドキュメントへの書き込み、Gemini APIへのリクエスト、Slackへの通知という一連のプロセスを自動化しています。
Google cloudやFirebaseでの実装も考えましたが、社内向けなので、スタンドアローンのGASであればサーバーレスで実行できるため、インフラコストがかからない点が利点です。

2. Googleドキュメントによるデータストア

Slackから取得したテキストベースのログを保存する簡易的なデータベースとして利用しています。構造化データが不要な今回の要件においては、セットアップの容易さから最適な選択肢でした。

3. Gemini APIによる高度な文脈判断

本システムの中核を担うのがGemini APIです。単なるキーワードのマッチングでは困難な、「休暇」という意図を含む自然言語の投稿と、単に投稿が存在しない「未報告」という状態を、チャットログの文脈から判別します。この自然言語理解能力が、システムの信頼性を担保しています。

4. プロンプト設計の要点

生成AIから期待通りの出力を得るためには、プロンプトの設計が重要です。本システムでは、以下の要素を盛り込むことで、出力の精度と形式を制御しています。

  • 明確なインプット/アウトプット定義: 入力データと、期待する出力形式を具体的に指示します。

  • 厳密な条件設定: 判定ロジックを言語化して伝えます。

  • 出力例の提示: 理想的な出力フォーマットの例を示すことで、AIの自己修正を促し、より安定した結果を得られるように設計しています。
    ( ${…}はGAS内で取得した変数です)

# Googleドキュメントに保存された勤怠ログ
${docText}

# 本日の日付
${today}

# 指示文章
出勤報告をしていない人を洗い出し、報告してください。

# 出力例:
${today}:勤怠連絡がない、または休暇を取得している方は以下の通りです。
山田 太郎さん: 体調不良のため休暇
鈴木 花子さん: 本日の出勤・休暇連絡がありません
また、本日の出勤報告は以下の方々です。
山田 太郎さん: 9:50
鈴木 花子さん: 9:50

# 条件:
該当者がいない場合は以下のメッセージにしてください

## 出力例:
${today}:本日は全員報告は以下の方々です。
山田 太郎さん: 9:50
鈴木 花子さん: 9:50


定時実行トリガーの強化

最後に、GASの時間主導型トリガーにはいくつか不便な点がある。

  1. 分ベース では1分おき・5分おき・10分おき・15分おき・30分おきのみ。

  2. 時間ベース では1時間おき・2時間おき・4時間おき・6時間おき・8時間おき・12時間おきのみ。

  3. 日付ベース では午前0時〜各1時間おき。

  4. 週ベース では特定の曜日に加えて午前0時〜1時間おき。

  5. 月ベース では特定の日に加えて午前0時〜1時間おき。

  6. 特定の日時 では「年」「月」「日」「時」「分」まで設定しないといけない。

つまりトリガーの設定画面だけでは「毎日午前10時15分」のような指定は実現できない。これを解消するため、GASで毎日実行後に、翌日の年月日時分を自動的にトリガー設定するようにした。

function setDailyTrigger() {
  // 既存のトリガーを削除
  const triggers = ScriptApp.getScriptTriggers();
  for (const trigger of triggers) {
    if (trigger.getHandlerFunction() === 'kintai_start') {
      ScriptApp.deleteTrigger(trigger);
    }
  }
  
  // 翌日のDateオブジェクトを作成
  const now = new Date();
  const year = now.getFullYear();
  const month = now.getMonth();
  const day = now.getDate() + 1;
  const date = new Date(year, month, day, 10, 15); // 翌日の時間指定
  
  // トリガーを設定
  ScriptApp.newTrigger('kintai_start').timeBased().at(date).create();
}

function kintai_start() {
  // 定期実行したい処理をここに記述
  kintai();
  // 処理終了時に再び翌日のトリガーを設定
  setDailyTrigger();
}

生成AIを既存の業務フローに組み込むことで、これまで自動化が困難であった非構造化データの扱いや、文脈判断を伴うタスクの効率化が可能となります。本事例が、皆様の業務改善の一助となれば幸いです。

いいなと思ったら応援しよう!