Devin API × Slack APIで不具合一次調査を自動化する仕組みを整えました

はじめに

こんにちは、Voicyでプロダクトエンジニアをしているきーくん(@komura-c)です。

VoicyではAIコーディングエージェントの活用を進めており、2025年4月から自律型AIソフトウェアエンジニアDevinを導入しています! DevinはデフォルトでSlack連携ができるため、社内ではSlack経由で@Devinとメンションし、コードの修正や調査などの作業を依頼することが増えてきました。

今回は、そんなDevinで不具合報告から一次調査ができる仕組みを整えたので実際にやってみた内容を記事としてまとめました!

Slack AppとDevin APIを組み合わせるパターンは汎用的なので、Devinの導入を検討している方や、すでに導入しているが活用方法を模索している方の参考になれば幸いです。

背景

Voicyという音声プラットフォームをユーザーのみなさんに使っていただいている以上、アプリケーションの不具合への対応はとても重要です。発生した問題に対して、エンジニアはいかに素早くかつ正確に対処できるかを心がけています。

一方で、新規機能開発など他の業務も同時に進める必要があります。そのため以前から、限られたリソースの中で、不具合が報告されてから一次調査に着手するまでの初速を最大化できないかと考えていました。

そこでAIエージェントの登場を受け、うまく活用すれば不具合調査を効率化できると考えました。日頃からDevinを開発でよく使っていたため、不具合調査もDevinに任せてみることにしました。

標準のSlack連携の課題

Voicyでは現在、プロダクトの不具合報告をSlackの専用チャンネルで行い、Jiraに自動起票する運用をしています。DevinにはもともとのSlack連携がありますが、今回のケースではいくつか考慮すべき課題がありました。

Devinの権限

DevinのSlack連携はSlackユーザーにDevinへの権限があるかをチェックしているため、DevinのOrganizationに登録しているユーザーしか依頼できません。今回のケースでは自動で調査を依頼したいので、Devin APIを利用するか、Slackにユーザーとして投稿する必要がありました。Slackにユーザーとして投稿するユーザートークンは便利ですが、退職などで該当ユーザーがいなくなると移行の必要があるため避けたいと考えました。

チャットベースの連携による制約

DevinのSlack連携はチャットを基準に作られているため、Slackから依頼するとその後の調査ややりとりのスレッドすべてに反応します。asidemuteで反応しないようにすることや別スレッドを作ることもできますが、できるだけ自動でやりたかったこともあり、Devin APIを利用することにしました。

以上の考慮を元に、Slackの不具合チャンネルに投稿されたメッセージをトリガーにして、Devinが自動で一次調査を行う仕組みを整えました。

全体構成

全体のフローは次のとおりです。

  1. 社員が問い合わせなどから不具合を確認しSlackのチャンネルに投稿
  2. SlackのEvent Subscriptionsで専用サーバーにリクエストを送信
  3. 専用サーバーからDevin APIでDevinに調査リクエストを送信
  4. Devinセッションが開始されたことをセッションURLと共にSlackのスレッドに返信
  5. Devinがコード調査・分析を行う
  6. Devinが調査結果をSlackのスレッドに返信(Slack MCP)

やったこと

仕組みを整える上でのポイントを紹介します。

Slack Appのセットアップ

Slackチャンネルへの投稿を検知するためにSlack Appを作成します。Slack APIからアプリを作成し、以下の設定を行います。

Event Subscriptions の設定

Event Subscriptionsを有効化し、Request URLにサーバーのエンドポイントを指定します。Subscribe to bot eventsで以下のイベントを追加します。

  • message.channels — パブリックチャンネルへのメッセージ投稿を検知

BotのスコープとしてOAuth Scopesの設定が必要なので、Bot Token Scopesに以下を追加します。

  • channels:history — チャンネルのメッセージを読み取る
  • chat:write — メッセージを投稿する(調査結果のスレッド返信用)

アプリをワークスペースにインストールしたら、Bot User OAuth Tokenと、Basic Information から専用サーバーで使うSigning Secretを控えておきます。

Slackイベントの受信とフィルタリング

Slack Appから送信されるイベントを受信してハンドリングするサーバーを実装します。Claude Codeを使ってPythonで実装しました。

# HTTP Mode用のApp(signing_secretを使用)
app = App(
    token=SLACK_BOT_TOKEN,
    signing_secret=SLACK_SIGNING_SECRET,
    process_before_response=True,  # ハンドラをHTTPレスポンス前に実行(3秒超でSlackがリトライする可能性あり)
)

@app.message("")
def handle_message(message, say):
    """受信メッセージを処理し、Devin APIに転送する"""
    # 対象Slackチャンネルからのメッセージのみを処理
    if message.get("channel") not in TARGET_CHANNEL_IDS:
        return

    # 通常のBotメッセージを無視(ワークフローメッセージは許可)
    if message.get("bot_id") and not message.get("workflow_id"):
        return

    # スレッドの返信を無視(トップレベルメッセージのみ処理)
    if message.get("thread_ts"):
        return
    
    # メッセージに含まれる情報を抽出
    channel = message.get("channel")
    text = message.get("text", "")
    thread_ts = message.get("ts")

    prompt = f"""以下の不具合報告について、コードベースを調査してください。
## 不具合報告
{text}

## 出力フォーマット
以下のフォーマットで調査結果をまとめてください。
- 該当箇所(ファイルパスと行番号)
- 推定される原因
- 影響範囲
- 推奨する対応方針

## 結果の投稿先
調査が完了したら、Slackチャンネル(channel_id: {channel})のスレッド(thread_ts: {thread_ts})に結果を投稿してください。"""
    
    # Devin APIの呼び出し
    response = call_devin_api(prompt)

    # スレッドに返信
    say(
        text=f"""🤖Devinが一次調査を開始しました。\n次のURLのDevinセッションを参考にしてください。\nSession ID: {response['session_id']}\nURL: {response['url']}""",
        thread_ts=thread_ts,
    )

Devin APIへのリクエスト

フィルタリングを通過したメッセージに対して、Devin APIにセッション作成リクエストを送信します。

def call_devin_api(prompt: str) -> dict:
    """Devin APIにプロンプトを送信し、新しいセッションを作成する"""
    url = f"{DEVIN_API_BASE_URL}/sessions"
    headers = {
        "Authorization": f"Bearer {DEVIN_API_KEY}",
        "Content-Type": "application/json",
    }
    response = requests.post(url, headers=headers, json={"prompt": prompt}, timeout=30)
    response.raise_for_status()
    return response.json()

Devin APIの/sessionsエンドポイントにプロンプトを送ると、Devinが新しいセッションを開始してコードベースの調査を始めます。

工夫したポイント

トップレベルメッセージのみのフィルタリングと無限ループ防止

Slackのイベントには、トップレベルのメッセージだけでなくスレッド内の返信も含まれます。そのまま処理すると、Devin自身の返信に再度反応してしまい、無限ループが発生します。対策として、次の2点をチェックしています。

  • thread_tsフィールドのチェック: トップレベルメッセージ(thread_tsが存在しないもの)にのみ反応させる
  • bot_idフィールドのチェック: Bot自身の投稿を除外し、Botの投稿がトリガーにならないようにする

この2つの条件を組み合わせることで、人間がチャンネルに投稿したトップレベルメッセージだけがDevinへの調査リクエストにつながるようになっています。

調査結果の投稿

Devinの調査結果をSlackに投稿してほしかったのですが、ドキュメントを確認したところ、メッセージAPIをハンドリングする以外に調査完了イベントを取得する方法がないことがわかりました。一方で、DevinにはSlack MCPサーバーをすでに連携していました。そこで、プロンプトに「Slackに送信してください」と記載することで、MCPサーバー経由で投稿できることに気づき、解決できました。

実際の成果

この仕組みにより、不具合報告からDevinの一次調査開始までの所要時間が5分以内になりました。

導入前 導入後
一次調査の着手 エンジニアが手動で着手 Devinが自動で即時開始
初動までの時間 エンジニアが優先対応 5分以内
エンジニアの負担 一次調査から対応 Devinの調査結果を元に対応

Slackの不具合報告でDevinが調査する様子

個人的な学び・感想

実際にAIエージェントが動くサーバーを一から構築するのは、メンテナンスコストなど少人数のスタートアップではハードルがあると思っていたので、メンテナンスコストを抑えた上で、Devinを活用してシンプルにやりたいことができたという実感があります。

アイデアを思いついてからはスムーズで、コーディングはClaude Codeに依頼したらすぐにできたので良い時代だと思いました。

Slack Appでイベントを受信し、フィルタリングしたうえでDevin APIでリクエストを送るというシンプルな構成ですが、不具合一次調査の初動を速める効果は大きいと感じます。

おわりに

今回は、Slackの不具合チャンネルへの投稿をトリガーにしてDevinが自動で一次調査を行う仕組みの構築方法を紹介しました。

今回紹介した仕組みはVoicy固有のものではなく、不具合の一次調査という課題は多くの開発現場に共通するものだと考えています。 ぜひ参考にしてみてください。

ここまで記事をお読みいただきありがとうございました!