今日は EAS Workflows を使って、数分で Expo アプリ用の AI QA Agent を構築します

CallstackのエンジニアがEAS WorkflowsとAI SDKで軽量なQAエージェントを構築し、AI生成のExpoアプリコードをiOSとAndroidで自動検証。

日本語
コピー
Build an AI QA Agent for Expo Apps with EAS Workflows in minutes today

本記事は Michał Pierzchała によるゲスト投稿です。同氏は Callstack の R&D インキュベーターの主任エンジニアで、agent-device と React Native Testing Library の作者です。

AI agent は大量のコードを素早く吐き出すのが得意だ。コードが増えればコードベースへの PR も増え、agent が生成するコードの規模に追随してスケールする品質保証の仕組みがますます必要になる。

AI agent がバックエンドのコードベースを触る場合、統合テストがあればたいていは事足りる。フロントエンドはそこまで楽観できない。UI を生み出すコード、たとえばモバイルの iOS / Android アプリを生成させると、最新のモデルはしばしば見事な結果を出す。結果を確認しなくてもいいほどだ(React の宣言的 UI のおかげで簡単になった)。だが、多くの場合で外してくる。ハードコアな React Native 開発者がコードしか読めず、手元にモバイル端末がない状況を想像してほしい。コードだけを見て、その人が正しく仕上げられる確信はどれくらいあるだろうか。ヒント:あまりない。検証こそが鍵だ。

これはまさに、私たちが Expo アプリ向けに埋めたかった穴だ。本記事では、既存のツールだけで、追加コストなしにそれを実現する方法を紹介する。さっそく始めよう。

EAS Workflows を使えば、ビルドの再利用、Android と iOS でのカスタム job の実行、GitHub の pull request へのコメント投稿がすでにできる。今日、大掛かりな自前プラットフォームを持ち込まずに軽量な QA agent を組むには、これで十分だと分かった。

QA Agent ワークフロー

最小限のテンプレートをここに置いた:callstackincubator/eas-agent-device

構成は意図的に小さくしてある:

  • CNG を使う Expo アプリ

  • オーケストレーションは EAS Workflows

  • AI SDK で書いた極小の Node.js QA agent

  • Android と iOS の自動化に agent-device

  • Android と iOS の QA 結果を添えた GitHub コメント

狙いは「AI」というラベルではなく、数分で動くベースラインが手に入り、あとはチームが必要とするカバレッジに応じて広げていけることにある。

目標

pull request ごとに、次のことをしたい:

既存のモバイル release ビルドを可能な限り再利用し、最新の JS を載せる

emulator または simulator を起動する

アプリをインストールして起動する

agent に UI を調べさせ、スクリーンショットを撮らせる

PR に短い QA サマリーを貼る

それだけ。大掛かりなテストフレームワークではないし、すべての E2E テストを置き換える気もない。モバイル UI の変更の周りに、実用的な QA のフィードバックループを一つ足すだけだ。

EAS Workflows がこの用途に向いている理由

一番の理由は、EAS Workflows がモバイル CI 特有の事情をそもそも分かっていることだ。

そのまま使える機能:

  • fingerprint ネイティブの変更を検出する

  • get-build 再利用できるビルドを見つける

  • repack JS しか変わっていなければネイティブの再ビルドをスキップする

  • linuxmacos runner。仮想化つきで Android / iOS のデバイスを動かせる

  • github-comment 結果を PR に送り返す

モバイルの自動化を汎用 CI に無理やり押し込む必要はなく、パイプライン全体をモバイルツールが元々ある場所に置いておける。設定もずっと見通しがよくなる。

ここで補足すると、Android の job は Android Emulator を起動するために linux-medium-nested-virtualization イメージが必要で、これは一から入れることになる。iOS Simulator には macos-medium イメージ(またはそれ以上)が要るが、シミュレータ自体はすぐ使える。これらのマシンがどれだけ柔軟で、どこまでスクリプトで制御できるかには正直驚いた。

まずはこの workflow 構成から

中心となる workflow はシンプルで、1 画面に収まる:

jobs:
  fingerprint:
    type: fingerprint

  android_get_build:
    type: get-build
    params:
      platform: android
      profile: qa-release

  android_repack:
    type: repack

  android_build:
    type: build

  qa_android:
    runs_on: linux-medium-nested-virtualization
    steps:
      - uses: eas/checkout
      - uses: eas/install_node_modules
      - uses: eas/download_build
      - id: provision_android_emulator
        run: bash ./scripts/agent-qa/provision-android-emulator.sh
      - id: run_agent_qa
        run: bash ./scripts/agent-qa/run-and-export.sh "${{ steps.download_build.outputs.artifact_path }}"
        env:
          AGENT_DEVICE_SESSION: qa-android
          AGENT_DEVICE_PLATFORM: android

  qa_comment:
    type: github-comment

iOS も同じ考え方で、macOS worker 上で simulator 向けにビルドするだけだ。Android と iOS を並行して動かす完全版はリポジトリにある:.eas/workflows/agent-qa-mobile.yml

重要な設計判断:bootstrap と QA を分ける

これは強くおすすめする。

一見すると、agent に全部やらせたくなる。アプリのインストール、起動、ナビゲーション、検査、報告まで。だが実際にやってみると、システムは不必要に脆くなる。agent はこちらのツールの使い方を間違えるし、読むように言った説明を読まないし、使っている CLI には存在しない flag をでっち上げる(私はやられた)。

AI agent に安定して働いてもらい、たまにしか当たらない賭けにしないためには、workflow をできる限り決定的に保つのが肝心だ。agent-device を使えばこうした手順は簡単にスクリプト化でき、デバイスへのアプリのインストールと起動で bootstrap の引数が常に正しくなる:

#!/usr/bin/env bash

# Phase 1: deterministic bootstrap
agent-device install "${APP_ID}" "${APP_PATH}"
agent-device open "${APP_ID}" --relaunch

agent-device どのプラットフォームを動かすべきか分かるのは、job で AGENT_DEVICE_PLATFORM 環境変数を設定しているからだ。

QA フローのうち、スクリプト化が難しい部分は agent に任せられる。agent は PR から受け入れ基準を推測し、accessibility tree を通じてトークンを節約しながら UI を調べ、少しだけナビゲーションし、スクリーンショットを撮り、何が起きたかを要約する

# Phase 2: variable agent-driven flow
npm run agent-qa

この1か月、私はいろいろな agent を組んできたが、経験から言うと、この分割のおかげでワークフロー全体が格段に信頼できるものになる。agent が artifact のパスやインストールコマンドを推測する必要は一切なくなる。

agent は驚くほど小さくできる

アプリがすでに動いている状態なら、agent に必要なツールはほんの少しだ:

  • PR のコンテキストを読む

  • agent-device skill をロードする

  • agent-device 経由で snapshotpressscreenshot といった UI 操作を実行する

  • 最終レポートを書く

簡略版はこんな感じになる:

import { ToolLoopAgent } from 'ai';

const agent = new ToolLoopAgent({
  model: 'openai/gpt-5.4-mini',
  instructions: `
    You are a mobile QA agent running inside EAS Workflows.
    Treat the app as a black box.
    Infer acceptance criteria from the PR.
    The app is already installed and launched.
    Use agent-device to inspect the UI, navigate, take screenshots, and write a report.
    If the result is visually plausible but not fully confirmed from structured UI output, use "unsure".
    You must call write_report exactly once.
  `,
  tools: {
    get_pr_context,
    load_skill,
    read_skill_file,
    agent_device,
    write_report,
  },
});

これだけあれば素早く始められ、十分な出来になるまで反復できる。私が使ったのは Vercel の AI SDK で、制御しやすさとすぐ使える手軽さのバランスがいい。その上、彼らの AI Gateway サービスを通せばお気に入りのモデルすべてにアクセスできる(少なくとも今のところ追加料金なし)。別のサブスクリプションを増やしたくなければ、慣れた OPENAI_API_KEY を使い、openai provider に切り替えてもいい。これは OpenAI に限らず他の provider でも同じだ。

完全な agent はこちら:scripts/agent-qa/index.ts——できるだけ短く書くようにしている。

必要なものだけを報告する

出力は小さく、かつ役に立つものにする。うちのテンプレートでは、各プラットフォームにつき検証ステータスを1つ返し、値は passedfailedblockedunsure のいずれかだ。そのあとに小さなセクションが続き、サマリー、実行したチェック、見つかった問題、スクリーンショット、そして折りたたみブロックに入れた完全な JSON レポート(主に QA 検証が失敗したときのデバッグ用)を載せる。

最後のステータス unsure が重要だ。モバイル UI は、構造化された自動化の出力だけできれいに検証できるとは限らない。accessibility tree が大きく助けになることもあれば、スクリーンショットが最も強い証拠になることもある。agent が結果をきれいに証明できないなら、正直にそう言い、画像を添えるべきだ。

知っているふりをするより、はるかにマシである。

最後の一手:Pull Request にコメントを1つ残す

人手で検証するときと同じで、作業の下に短いコメントを1つ残すだけで、agent が何を検証し、何を検証しなかったかをだいたい把握できる。しかも視覚的な確認付きで——この変更がアプリを壊していないか本当に判断するには、それがしばしば必要になる。PR コメント1つで十分に機能する:

## Agent QA

| Platform | Status    |
| -------- | --------- |
| Android  | ✅ passed |
| iOS      | 🤔 unsure |

### Android
Short summary...
Screenshots

### iOS
Short summary...
Screenshots

これで結果は reviewer がもともと目にする場所に現れ、必要な情報と視覚的フィードバックがすぐ手の届くところにある。

QA Agent のビフォーアフター
私たちの QA Agent からのコメントが、私たちのアプリを「見て」いました!

💡GitHub のコメントにはスクリーンショットをアップロードする公式 API がないので、この例では画像の置き場所として Vercel Blob をサードパーティのクラウドストレージとして使っている。自分の用途に合ったもの、たとえば AWS S3 に置き換えてもいい。

今すぐ始めたい人へのアドバイス

Expo dashboard で GitHub プロジェクトを EAS Workflows に接続する。

まずは Android など、1つのプラットフォームから始める。

CNG を使い、ネイティブビルドの再利用はオンのままにする。

QA ビルド profile は本番環境と分ける。

bootstrap は決定的に保つ。

agent にはブラックボックスとして振る舞わせる。

PR コメントは1つだけ。10種類の別々の成果物を出すのではない。

スクリーンショットは早めに入れる。効果が大きい。

これが動くようになってから、少しずつ広げていく:

  • iOS を追加する

  • スクリーンショットを Blob ストレージにアップロードする

  • より良い selector を入れる

  • 成功した探索的なチェックを、より確定的なフローに変えていく

結論

有用なモバイル QA 自動化を得るのに、巨大な AI テストプラットフォームは要らない。

Expo と EAS Workflows がインフラの大部分をすでに用意してくれている:

  • ビルド再利用:素早く反復でき、再パッケージで最新の JS bundle を取得できる

  • モバイル CI worker:スクリプト実行能力と仮想化を備え、シミュレータとエミュレータがいつでも使える

  • ワークフロー編成:これらすべてをつなぐ

  • GitHub 連携:認知負荷を下げ、検証を Pull Request の中に留める

その上に、特注の QA agent を驚くほど小さく作れる。しかも TypeScript ベースの AI SDK のおかげで、必要な形にいくらでも作り変えられる(かなり柔軟だ)。

だからこのやり方が気に入っている:今日すぐ組めて、数分で、シンプルなテンプレートから始められ、本当にもっと必要になったときだけ拡張すればいい。

ここから始めよう:callstackincubator/eas-agent-device

出典: Expo Blog← ホームへ戻る