2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AskOK — Slackで社内業務改善ボット

2
Last updated at Posted at 2026-09-25

AskOK — Slackで「聞きたいのに聞けない」を解くボット

社内では「聞きたいのに聞けない」「聞いても反応がない」「忙しくて返せない」が同時に起きる。
AskOK は、特定の Slack チャンネルに投稿するだけで、ボットが受け取り、Backlog / Bitbucket / Slack の過去知を横断で先に返し、足りなければチャンネル参加者へ橋渡しする。
人の発言の代行はせず、チャンネル参加が同意になる。

触ってほしいポイント

  1. 特定チャンネルに投稿する → すぐリアクション+出典つき要約がスレに出ること
  2. 人への橋渡しが helpers チャンネル参加者のみで、代弁投稿しないこと

現場でありがちな失敗

  1. 聞きにくい — 「そんなことも知らないの?」と言われそうで、質問をためらう
  2. 聞いても反応がない — #random は「誰かが返すだろう」で止まる
  3. 忙しくて返せない — 関わりたい気持ちはあるが、常時レスは負担。かといって ボットに自分の言葉を代弁されるのは嫌

3つ目が効いている。「AIが自動で答えてくれる」だけでは解けない。
人が関わるかどうかを、人が決められる形にする必要があった。

意思 表明の仕方
質問したい #askok に投稿する
聞かれてもよい #askok-helpers に参加する(=同意)
もう関わりたくない チャンネルを退出する

登録フォームも管理画面も作っていない。チャンネル参加そのものが同意になっている。


お題との接続

お題に対し、いつもの Slack 上で「既存知 → 合意した人」の二段にした。
専用 Web アプリを主UIにしないのは、課題が Slack 上で起きているから。別アプリを開かせると続かない。


AskOK とは

形態 Slack ボット(専用の Web 画面は作らない)
稼働 AWS Lambda + API Gateway。常時稼働(誰の PC も要らない)
検索対象 Backlog / Bitbucket / Slack(本番接続)
実装した会話 横断Q&A・出典提示・担当案内・helpers 橋渡し・Backlog 起票

使い方(短い)

  1. 答え手は #askok-helpers に参加する(=聞かれてもよい同意)
  2. 聞き手は #askok に質問を投稿する(メンション不要)
  3. スレの要約を見る。足りなければキーワードを足して聞き直す
  4. 人に聞きたければ「helpersに聞いて」→ 候補が出る → もう一度送ると共有される
  5. 関わりたくなくなったら #askok-helpers を退出する

デモの流れ(4手)

  1. #askok に質問 → 👀 → スレに要約が返る
  2. 「helpersに聞いて」→ 候補が出る
  3. もう一度「helpersに聞いて」→ #askok-helpers に共有される
  4. 元スレのリンクから戻って、人が自分の言葉で答える

見せどころは2つ。
検索結果のダンプではなく会話になっていることと、
人を巻き込む前に同意を取っていること。


システム構成(概念)

Slack (#askok)
  → API Gateway
  → Lambda(受信役:署名検証 → 即 200)
  → Lambda(処理役:横断検索・対話・投稿)※同一関数を非同期 invoke
  → DynamoDB(会話状態 / イベント重複排除)
  → Backlog / Bitbucket / Slack search

なぜ「受信」と「処理」を分けたか

Slack Events API は 3秒以内に 200 を返さないとリトライしてくる。
一方、横断検索は十数秒かかる。素直に書くと、同じ質問に何度も回答してしまう。

そこで 1つの Lambda を2つの役で使う。

  1. 受信役: 署名検証 → 自分自身を非同期 invoke → すぐ 200(実測ウォーム約170ms)
  2. 処理役: event_id の条件付き書き込みで重複排除 → 検索・要約 → スレ返信

関数を2つに分けなかったのは、環境変数もコードも同じものを2箇所で管理したくなかったから。


AIにやらせたこと/やらせなかったこと

プロダクトの中では

検索で上位 hit を絞ってから OpenAI に渡し、出典付きで会話として返す。
全チャンネル履歴を毎回プロンプトに詰めない。キー未設定や API 失敗時はテンプレ回答にフォールバックする。

A2(橋渡し理由)・A3(答え手向け返信案)は未実装。

作るときに効いたのは「止めた」場面

場面 どう止めたか
検索結果をそのまま並べる回答 「何が書いてあるか分からない」→ 会話形式に作り直した
DM が検索結果に出た 気づいた時点で除外。回答は他人にも見える
引用に生のメンションが混ざった <@U…> をそのまま返すと関係ない人に通知が飛ぶ → 平文に無害化
Windows の Compress-Archive で作った zip エントリ名が \ になり Lambda がモジュールを解決できない → zip を自前で組み立てた

「AI に書かせた量」ではなく「AI の出力をどこで疑ったか」が本題だった。


こだわった判断

判断 理由
専用 Web アプリを作らない 課題は Slack 上で起きている
#askok / #askok-helpers の2本 聞く側と答える側の意思を分ける。登録画面は不要
ボタンではなく自由入力 会話として自然で、キーワードを足して聞き直せる
代弁しない 現場の拒否感そのものが要件
即メンションしない 候補を見せて同意を取ってから
依存パッケージを配布物に入れない Lambda の起動を軽くする。配布物は 100KB 未満

検索結果から意図的に外したもの

除外 理由
DM・グループDM 個人的なやり取りが第三者に見える
#askok / #askok-helpers 受付口であって知識ソースではない
AskOK 自身の過去回答 自分の出力を根拠にして循環する

手戻り・失敗談

  • Slack の3秒制約 — 検索を同期でやるとリトライ地獄。受信/処理の分離で解消した
  • Socket Mode → HTTP Events — ローカル検証と本番常時稼働の切り替えで詰まった。署名付き疎通確認を先に用意してから Slack に Request URL を貼る順にした
  • User Token の検索権限 — 便利だが個人の権限に依存する。運用に載せるなら専用アカウントが要る
  • メンションの再投稿 — 検索ヒットの本文をそのまま返すと通知事故になる。表示前に必ず無害化する

学び

  • 「全自動で答える」より、「既存知 → 同意した人」の二段のほうが現場の拒否感に合う
  • AI は要約に強いが、何を根拠に渡すかと何を絶対に出さないかは人が決める
  • Slack ボットは「動いた」より「誰にも迷惑をかけない」が先に来る(DM除外・メンション無害化・同意後の橋渡し)

今後

  • A2/A3(橋渡し理由・答え手向け返信案)
  • シークレットを環境変数から Parameter Store などへ移す
  • Slack 検索用の専用アカウント
  • Teams コネクタ(現状は未接続)

正直に足りていないところ

  • A2/A3 は未実装。A1(スレ要約)は OpenAI 接続済み
  • Teams は未接続
  • シークレットが Lambda 環境変数のまま

評価用の触り方・チャンネル案内は Slack 側に置いている(本記事には公開URL・社内ドメイン・アカウントIDは書かない)。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?