Snowflake Cortex Agents のバージョン管理および GitHub Actions での CI/CD を考えみた

Snowflake Cortex Agents のバージョン管理および GitHub Actions での CI/CD を考えみた

Snowflake Cortex Agents のバージョン管理とGitHub Actions を用いた CI/CD について考え、実際に検証してみました。
2026.08.31

こんにちは、データ事業本部のキタガワです。

最近 Snowflake の Cortex Agents に入門しました。

今回は Cortex Agents のバージョニング周りを、特に GitHub Actions を用いた CI/CD の観点から検証します。

なお、こちらで作成したソースコードは以下のリポジトリで公開しています。

https://github.com/cm-kitagawa-zempei/snowflake-cortex-agents-versioning

Cortex Agents におけるバージョニング

Cortex Agents はバージョン管理ができます。

バージョンは Snowsight の AI & ML > Agents から該当の Cortex Agent を選択し、右上の時計アイコンから確認できます。

alt text

この Cortex Agent だと Version 1 から 4 まであり、未 Publish の Draft バージョンが 1 つある状態です。

バージョンには大きく分けて、 live バージョン と named バージョンの 2 種類があります。Draft は live バージョンに相当し、開発用として使うことが想定されています。開発が完了し、本番環境で使う場合には live バージョンをコミットして新しい named バージョンを作成します。named バージョンにはエイリアスやコメントをつけることができます。

alt text

named バージョン

named バージョンは Cortex Agent 作成時点で VERSION$1 が自動的にコミットされ、以後コミットごとに VERSION$2, VERSION$3, ..., VERSION$N というように増えていきます。コミット後に編集できるのはエイリアスやコメントのみで、Cortex Agent 自体の設定は変更できません。これにより安定したバージョン運用ができるようになっています。

live バージョンをコミットするには以下のような SQL を実行します。

-- Commit the live version to create a named version
ALTER AGENT my_agent COMMIT
  COMMENT = 'Production release for Q1';

またステージから直接 named バージョンを作成することもできます。

-- Create a named version from a stage
ALTER AGENT my_agent ADD VERSION FROM @my_stage/agents/my_agent
  COMMENT = 'Imported from feature branch';

エイリアス

エイリアスは開発者やプログラムが特定のバージョンを識別しやすくするために使うことができます。productionstaging, canary, rollback などがよく使われます。エイリアスを付与することでバージョンの識別番号に依存することなく、API や SQL で特定のバージョンを指定することができるようになります。

エイリアスの付与には以下のような SQL を実行します。

-- Assign an alias to a named version
ALTER AGENT my_agent
  MODIFY VERSION VERSION$3 SET ALIAS = production;

エイリアスは付与した後も別の named バージョンに付け直すことができるので、本番デプロイ後の切り戻しにも使用できます。

またバージョンショートカットとして以下のような識別子が別途用意されています。[1]

Shortcut Description
LIVE The current live version (displayed as DRAFT in the UI)
FIRST The first committed named version
LAST The most recently committed named version
DEFAULT The version set as the default for the agent

特に DEFAULT は Snowflake CoWork でもルーティングされるバージョンなので GitHub Actions でのデプロイ後には、そのバージョンを DEFAULT に設定した方が良いと思います。[2]

特定のバージョンを DEFAULT に設定するには以下のような SQL を実行します。

-- Set the default version
ALTER AGENT my_agent
  SET DEFAULT_VERSION = 'VERSION$3';

GitHub Actions での CI/CD 検討

ここまでの内容を踏まえて GitHub Actions での CI/CD を検討します。
バージョニング機能を利用した Cortex Agents の開発からデプロイまでの CI/CD のワークフローとしては次のように設定しました。

開発者の作業としては次のような流れを想定します。

  1. Snowsight で Cortex Agent を作成/編集する
  2. GET コマンドにより指定したバージョンの設定が書かれている agent_spec.yaml を取得する
  3. 取得した agent_spec.yaml を GitHub に Push する

GitHub Actions のワークフローとしては次のように検討しました。

  1. Push された agent_spec.yaml を snow stage copy でステージにコピーする
  2. ステージから ADD VERSION により新しいバージョンを作成する
  3. 作成されたバージョンに MODIFY VERSIONproduction エイリアスを付与する
  4. 作成されたバージョンを SET DEFAULT_VERSION で DEFAULT に設定する

Cortex Agents の作成や編集を Snowsight に寄せているのは、現状 Snowsight の使い勝手がとても良いからです。作成・編集と動作確認のイテレーションを簡単に回すことができます。

また Cortex Agents を作るときは当然 Semantic View なども使うことになるので、そのあたりも Snowsight で完結させたいというのが理由です。今は Preview 段階ですが Workspace から Cortex Agents や Semantic View の作成ができるようになっているようですので、将来性を鑑みても Snowsight に寄せるのは有効な選択肢かなと思います。

GitHub Actions でデプロイする Cortex Agent は開発用の Cortex Agent とは別のオブジェクトとして作成する想定です。イメージとしては開発スキーマで開発用のエージェントを Snowsight で作成して、本番スキーマは GitHub Actions 経由のみでデプロイするという感じです。

簡単のため、ここでは開発用と本番用の Cortex Agent を同一データベースの別スキーマに置く想定です。実際には開発用と本番用の Cortex Agent は別データベースやアカウントに置くことが多いと思いますが、その場合でも大きくは変わらないと思います。流れは次の図のとおりです。

GitHub Actions での CI/CD 実装

前項で検討した内容の実装を行います。

ここでの前提として作業環境は以下で実施しました。

  • macOS Tahoe バージョン 26.6.2
  • Snowflake CLI version: 3.20.0

またここでは Cortex Agents の作成や WIF、Role の設定等については省略します。

agent_spec.yaml の取得

まず適当に作成した Cortex Agent の agent_spec.yaml を GitHub に Push します。KITAGAWA_TEST_DB.AGENT_DEV に GENERAL_AGENT という名前で Cortex Agent を作成しました。少し修正も加えたので現在は Version 2 まで進んでいます。

alt text

SHOW VERSIONS で agent_spec.yaml のディレクトリパスが確認できます。この SQL で取得できる spec_file_path を LIST に渡し、実際のファイル名を確認しています。

-- DEFAULT バージョンの agent_spec.yaml ディレクトリパスの取得
SHOW VERSIONS IN AGENT KITAGAWA_TEST_DB.AGENT_DEV.GENERAL_AGENT
->> SELECT "spec_file_path" FROM $1 WHERE "is_default" = 'true';

-- ファイル名の確認
-- SHOW VERSIONS で取得したディレクトリパスを LIST に渡す
LIST snow://agent/KITAGAWA_TEST_DB.AGENT_DEV.GENERAL_AGENT/versions/version$2/
->> SELECT "name" FROM $1;

ここでは name 列に /versions/version$2/agent_spec.yaml という値が入っていました。この値をもとに GET でファイルを取得します。

実行はローカルクライアントの Snowflake CLI から行います。

# Snowflake CLI から GET
snow sql -q "GET snow://agent/KITAGAWA_TEST_DB.AGENT_DEV.GENERAL_AGENT/versions/version\$2/agent_spec.yaml file:///tmp/;"

/tmp/ にファイルがダウンロードされているのでこれをリポジトリの適切なディレクトリに移動します。

mkdir -p ./cortex_agents/GENERAL_AGENT/
mv /tmp/agent_spec.yaml ./cortex_agents/GENERAL_AGENT/

GitHub Actions の設定

荒削りですが以下のようなワークフローを作成しました。

リポジトリの cortex_agents/<AGENT_NAME>/agent_spec.yaml を対象にデプロイを行います。変更があったものを対象に matrix で並列実行します。作成される Cortex Agent はディレクトリ名から導出するようにしました。

name: Deploy Cortex Agent

on:
  push:
    branches:
      - main
    paths:
      - "cortex_agents/*/agent_spec.yaml"
  workflow_dispatch:
    inputs:
      agent_name:
        description: "Deploy target agent name (cortex_agents/<AGENT_NAME>)"
        required: true

permissions:
  id-token: write
  contents: read

defaults:
  run:
    shell: bash

env:
  # 接続情報
  SNOWFLAKE_ACCOUNT: ${{ secrets.SNOWFLAKE_ACCOUNT }}
  # デプロイ先
  AGENT_DATABASE: KITAGAWA_TEST_DB
  AGENT_SCHEMA: AGENT_PROD
  STAGE_NAME: AGENT_SPECS

jobs:
  detect:
    runs-on: ubuntu-latest
    outputs:
      agents: ${{ steps.targets.outputs.agents }}
    steps:
      - uses: actions/checkout@v7
        with:
          fetch-depth: 0

      - name: Detect target agents
        id: targets
        env:
          INPUT_AGENT_NAME: ${{ inputs.agent_name }}
          BEFORE_SHA: ${{ github.event.before }}
        run: |
          if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then
            agents=$(jq -cn --arg a "${INPUT_AGENT_NAME}" '[$a]')
          elif git cat-file -e "${BEFORE_SHA}" 2> /dev/null; then
            # push 前のコミットと比較
            agents=$(git diff --name-only --diff-filter=d "${BEFORE_SHA}" HEAD -- 'cortex_agents/*/agent_spec.yaml' \
              | cut -d/ -f2 | sort -u | jq -Rnc '[inputs]')
          else
            # 比較元が無い場合、全エージェントを対象にする
            agents=$(git ls-files 'cortex_agents/*/agent_spec.yaml' \
              | cut -d/ -f2 | sort -u | jq -Rnc '[inputs]')
          fi
          echo "Target agents: ${agents}"
          echo "agents=${agents}" >> "$GITHUB_OUTPUT"

  deploy:
    needs: detect
    if: needs.detect.outputs.agents != '[]'
    runs-on: ubuntu-latest
    strategy:
      matrix:
        agent_name: ${{ fromJSON(needs.detect.outputs.agents) }}
    env:
      AGENT_NAME: ${{ matrix.agent_name }}
    steps:
      - uses: actions/checkout@v7

      - name: Install Snowflake CLI
        uses: snowflakedb/snowflake-actions@v3
        with:
          use-oidc: true

      - name: Copy agent spec file to stage
        run: |
          snow stage copy \
            "cortex_agents/${AGENT_NAME}/agent_spec.yaml" \
            "@${AGENT_DATABASE}.${AGENT_SCHEMA}.${STAGE_NAME}/${AGENT_NAME}/" \
            --overwrite \
            --temporary-connection

      - name: Check if agent exists
        id: check
        run: |
          count=$(snow sql --temporary-connection --format json -q "
            SHOW AGENTS LIKE '${AGENT_NAME}' IN SCHEMA ${AGENT_DATABASE}.${AGENT_SCHEMA};
          " | jq 'length')
          echo "exists=$([ "${count}" -gt 0 ] && echo true || echo false)" >> "$GITHUB_OUTPUT"

      # 初回デプロイ: エージェント作成(VERSION$1 が自動コミットされる)
      - name: Create agent (first deploy)
        if: steps.check.outputs.exists == 'false'
        run: |
          {
            echo "CREATE AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME}"
            echo "  FROM SPECIFICATION"
            echo "\$\$"
            cat "cortex_agents/${AGENT_NAME}/agent_spec.yaml"
            echo "\$\$;"
          } > create_agent.sql
          snow sql --temporary-connection -f create_agent.sql

      # 2回目以降: ステージから新バージョンを追加
      - name: Add version
        if: steps.check.outputs.exists == 'true'
        run: |
          # live バージョンが残っていると ADD VERSION が失敗するため、先に COMMIT する。
          live=$(snow sql --temporary-connection --format json -q "
            SHOW VERSIONS IN AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME};
          " | jq 'map(select(.name == null)) | length')
          if [ "${live}" -gt 0 ]; then
            snow sql --temporary-connection -q "
              ALTER AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME}
                COMMIT COMMENT = 'Auto-commit leftover live version';
            "
          fi

          snow sql --temporary-connection -q "
            ALTER AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME}
              ADD VERSION FROM @${AGENT_DATABASE}.${AGENT_SCHEMA}.${STAGE_NAME}/${AGENT_NAME}
              COMMENT = 'Deployed from GitHub Actions (${GITHUB_SHA})';
          "

      - name: Set alias and default
        run: |
          # SHOW VERSIONS から最新の named バージョンを解決する
          version=$(snow sql --temporary-connection --format json -q "
            SHOW VERSIONS IN AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME};
          " | jq -r 'map(select(.name != null)) | max_by(.created_on) | .name')
          if [ -z "${version}" ] || [ "${version}" = "null" ]; then
            echo "::error::No named version found for ${AGENT_NAME}"
            exit 1
          fi
          echo "Latest version: ${version}"

          snow sql --temporary-connection -q "
            ALTER AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME}
              MODIFY VERSION ${version} SET ALIAS = production;

            ALTER AGENT ${AGENT_DATABASE}.${AGENT_SCHEMA}.${AGENT_NAME}
              SET DEFAULT_VERSION = '${version}';
          "

いろいろ処理を書いていますが、基本的には前項で検討した内容を実現するための周辺処理であり、メインは snow stage copy でステージにコピーし、そのステージから ADD VERSION で新しいバージョンを作成、 MODIFY VERSION でエイリアスを付与、 SET DEFAULT_VERSION で DEFAULT に設定するという流れです。

live バージョンについては Cortex Agent 作成時に自動的に作成されるもので、これが残っていると ADD VERSION が失敗するため、先に COMMIT するようにしています。

動作確認

GitHub Actions の動作確認を行います。

ワークフローを設定した状態で最初のプッシュを行います。

alt text

alt text

Cortex Agent が作成され、エイリアスの付与と DEFAULT の設定が行われたことがわかります。

Snowsight から該当の Cortex Agent を確認します。

alt text

alt text

こちらでも本番用のスキーマに作成されており、 production エイリアスが付与されていることが確認できました。

次に agent_spec.yaml を修正して再度 Push してみます。

--- a/cortex_agents/GENERAL_AGENT/agent_spec.yaml
+++ b/cortex_agents/GENERAL_AGENT/agent_spec.yaml
@@ -12,4 +12,4 @@ tools:
 tool_resources:
   code_toolset_all:
     permission_policy:
-      type: "always_allow"
+      type: "always_ask"
git add .
git commit -m "Update GENERAL_AGENT agent_spec.yaml"
git push

今度は意図通り Add version ジョブと Set alias and default ジョブが実行され、バージョンが更新されました。

alt text

alt text

同じように Snowsight からも確認します。

alt text

バージョンは3まで進み、このバージョンにエイリアスが付け替えられていることが確認できました。

alt text

SHOW VERSIONS でも確認します。

SHOW VERSIONS IN AGENT KITAGAWA_TEST_DB.AGENT_PROD.GENERAL_AGENT;

alt text

まとめ

GitHub Actions を使って Cortex Agents のバージョン管理とデプロイを自動化する方法について検討してみました。Snowsight の機能は積極的に使いつつ、ユーザーに影響のある本番環境は一定のルールのもと運用することができるようになったのではないかと思います。

バージョンとエイリアスを適切に管理することで、本番での切り戻しも即座に行うことができます。

Cortex Agents を運用する明確なベストプラクティスと呼べるものはまだまだない状況だと思いますが、この記事が参考になれば幸いです。

それではまた次の記事でお会いしましょう。

参考

https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-versioning

脚注
  1. https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-versioning#version-shortcuts ↩︎

  2. このことについて明言したドキュメントは見つかりませんでしたが、Cortex Agents API の仕様および実際の挙動から推測しています。 ↩︎


Snowflake World Tour Tokyo 2026に参加しませんか?

Snowflakeの国内最大級イベント「Snowflake World Tour Tokyo」が2026年9月10日(木)・11日(金)にグランドプリンスホテル新高輪にて開催されます。
最新のAI・データ活用事例やライブデモを体感できる無料イベントです。

Snowflake World Tour Tokyoイベントに参加する


Snowflake Community Awards ファイナリストに選出されました

DevelopersIO で Snowflake 記事を執筆している かわばた が、Snowflake Community Awards「RISING COMMUNITY LEADER OF THE YEAR」部門・APJ枠のファイナリストに選ばれました。
最終選考の30%はコミュニティ投票です。記事がお役に立っていたようでしたら、9月15日(火)までにぜひ一票お願いします。フォームの「(4 of 6) RISING COMMUNITY LEADER OF THE YEAR」で Tomohiro Kawabata | Classmethod, Japan を選択、2分ほどで完了します。

投票フォームを開く


Snowflakeの導入支援はクラスメソッドに!

クラスメソッドでは Snowflake の導入を支援しております。
製品の詳細や支援の内容についてお気軽にお問い合わせください。

Snowflakeの詳細を見る

この記事をシェアする

関連記事