🐥

BedrockでClaude Code Actionを実行するまで(OIDC)

に公開

日本には、Anthropicとの直接契約はないが、AWSとの契約はあるという開発環境が多く存在していると思います。この記事では、そのような環境でBedrock経由でClaude Code Actionを実行するための手順を記載します。公式のREADMEは5/24時点では不完全な状態で、issueを参照しながら必要な設定をまとめています。
READMEに書かれたymlの内容に過不足があったので、その内容を記録するためだけに記事を書いていたら、予想以上に前提やらを書くことになってしまった
ymlの設定だけが気になる方は.github/workflows の設定を見てください。
また、どんな感じのことができるか、についてはおためし実行を見てください。

前提の整理

Claude Code Action とは、Claude CodeをGitHub Actionで動かして、issueからPRを作成させたり、その他Claude Codeで可能なことをGitHubで発生するイベントをトリガーとしてGitHub Actionの環境で実行させるものです。
https://github.com/anthropics/claude-code-action

Claude Code は、利用者が任意の指示を与えることで、その指示をリモートに存在するClaudeに送信してClaudeにそれを実現するための作業を考えさせ、その作業や求められたソースコードの内容などをClaudeに追加で送信することを繰り返して指示を実現する、という仕組みです。Claude CodeのクライアントはPCなどで動作し、そのPCにあるリポジトリの内容などをClaudeに送信しながら、Claudeに解析処理を行わせ、必要であればPC内のソースコードを編集し、(ローカルで)commitすることもできます。[1]
ただし、Claude CodeはPCなどで動作するものなので、単独ではGitHubのイベントをトリガーにして動作することはありません。通常のClaude Codeの利用においては、人間がissueに対応するにあたってローカルでClaude Codeを実行する、といったことが想定されています。
そこで、GitHub Actionによって、GitHubのイベントをトリガーにして、GitHub Actionで用意されるDocker環境でClaude Codeを動かし、そこからClaudeに通信させる、というのがClaude Code Actionのやりたいことです。例えば、GitHubにissueを立てて@claudeというようにメンションすれば、GitHub Actionによってbotがそれっぽく応答して、それっぽく対応してPR作成(の手前)までやってくれる、ということになります。

Claude は、Anthropicが提供しているAIの名前です。ClaudeはAnthropicのAPIで直接利用することができますが、AWSの提供しているBedrock、Googleの提供しているVertexなどのいくつかのモデルをまとめたインターフェイスを経由して呼ぶこともできます。今回は、AWSでの契約がすでにあり、Bedrockを使ってClaudeを呼ぶ場合を対象としています。

連携の仕様・制約

Claude Code ActionでBedrockを利用するには、それを利用するための権限と認証が必要になります。具体的には、AWS側でIAMロールを作成し、このIAMロールをOIDCによってGitHub Action側で利用できるように設定する必要があります。また、このOIDCを利用するために、GitHub Appをカスタムで作成する必要があります。 GitHub Appをカスタムで作成する必要はありません(公式サンプルではカスタムの設定と列挙されているのですが、それは不要です)。

概念的な連携の整理

連携を概念的に整理すると以下のようになります。[2]

必要な設定

それでは、実際に必要な設定について説明していきます。

AWS側での設定

BedrockおよびClaudeを利用可能にする

もしBedrockでClaudeを利用したことがない場合は、Claudeを利用可能にするための申請が必要になります。

【重要】リージョンについてはus-west-2が無難かもしれません。2025/5/25時点ではcross-region inferenceによってap-northeast-1でもあまり問題がない可能性があります。

手順については、Amazon BedrockのIAMポリシーとユースケースの詳細を申告してからチャットを試すまでなどに記載があります。
※最新のUIでは内容が変わっている可能性があります。

(なお、これはうろ覚えですが、最初にinference profileを利用するときに、inference profileを使う設定を管理画面で行ったような記憶があります。ひょっとすると今は必要ないかも?)

OIDCプロバイダとしてGitHubを登録する

OIDCを利用するためには、AWS側でGitHub(GitHub Actions)をプロバイダとして登録する必要があります。手順は以下を参照してください。
GitHub Actions で OIDC を使用して AWS 認証を行う
※最新のUIでは内容が変わっている可能性があります。

この手順で、次のIAMロール登録で利用する信頼関係の oidc-provider/token.actions.githubusercontent.com が利用できるようになります。

IAMロールを登録する

以下のポリシーおよび信頼関係を持つIAMロールを作成します。

ポリシー:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": "*"
        }
    ]
}

信頼関係:「123456789012」の部分にはアカウントID(ハイフン無し)を入力します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RoleForGitHubActions",
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:uniaim-ticket/*:*"
                }
            }
        }
    ]
}

登録が完了したら、ロールのARNをコピーしておきます。ARNは
arn:aws:iam::123456789012:role/ROLE_NO_NAMAE_DAYO
のような形式です。

GitHubのWebでの設定

ClaudeのGitHub Appをインストールする

対象のリポジトリまたはorganizationにClaudeをインストールします。
https://github.com/apps/claude

なお、このアプリの代わりにカスタムアプリを自作して、それを利用することもできます。(おまけに記載)

シークレット「AWS_ROLE_TO_ASSUME」を設定する

対象のリポジトリのシークレット「AWS_ROLE_TO_ASSUME」に、先程作成したロールのARNを入力します。以下のような形式になっているはずです。
arn:aws:iam::123456789012:role/ROLE_NO_NAMAE_DAYO

.github/workflows の設定

ここまでの設定ができたら、GitHub Actionsを設定していきます。リポジトリに.github/workflowsが存在しなければフォルダを作成し、任意の名前(たとえばclaude.yml)で以下のようなymlを作成します。
注意事項として、リージョン指定している箇所が2箇所あります。us-west-2としており、またcross region inferenceで使用しているモデルのIDもusのものとなっています。リージョンを変更する場合はこれらに注意してください。

claude.yml
name: Claude Assistant
on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]
  issues:
    types: [opened, assigned]
  pull_request_review:
    types: [submitted]

jobs:
  claude-code-action:
    if: |
      (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
      (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
      (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
      (github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
    runs-on: ubuntu-latest
    env:
      ANTHROPIC_BEDROCK_BASE_URL: "https://bedrock-runtime.us-west-2.amazonaws.com"
    permissions:
      contents: read
      pull-requests: read
      issues: read
      id-token: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 1

      - name: Configure AWS Credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
          aws-region: us-west-2

      - uses: anthropics/claude-code-action@beta
        with:
          model: "us.anthropic.claude-sonnet-4-20250514-v1:0"
          use_bedrock: "true"

ここまでの設定をしてpushすると、Claude Code Actionが実際に動作するようになります。地味に重要なのがANTHROPIC_BEDROCK_BASE_URLで、これがないと動きません、、、

なお、OIDCのためにid-tokenの権限が必要ですが、カスタムアプリを使わない場合はactions/create-github-app-token@v2を明示的に利用してトークン生成する必要はありません(claude-code-actionが勝手にやってくれる)。

おためし実行

PRレビューコメント

実際に動かしてみます。上記の変更を含むPRを作成して@claudeを含むPRレビューのコメントを作成するか、または上記の変更をデフォルトブランチに取り込んで@claudeを含むissueを作成すると、Claude Code Actionが起動します。
この記事を作成するためにwriteやreadの権限を試していた箇所について、Claude Code Actionに説明させた場合の例は次のとおりです。まず命令に対してTODOリストを作成して、そのTODOを実行していくという形でClaude Codeのタスクが進行して、最終的な回答がコメントに記載されます。(少なくともこのPRの中の)コミット履歴も追いかけてコメントしてくれるようです。

なお、このissueの実行に際してのコストなどはGitHubのActionタブで確認できます。(単位は米ドル)

issueに対応させる

issueを作って、issue内での言及またはissueコメントでの言及によってClaude Code Actionを動かしてみます。カスタムアプリを使ったので若干見た目が違いますが、以下のように対応してくれます。

issueにコメントをつけて指示

Create PRのリンクで、メッセージが入力された状態のPRを作成できます。

PRを修正

上記のPRを作成したところ、eslint(prettier)でエラーになったので、エラーを修正させます。これで実際に直りました。

おまけ(カスタムアプリ)

Claude Code Actionの連携先としてカスタムアプリを指定することで、GitHub上に出てくるアプリ名やアイコンなどを自由に変更できます。

GitHub側の設定(カスタムアプリ)

カスタムアプリを登録して、秘密鍵を生成します。
このアプリを使いたいリポジトリ(またはorganization)にインストールします。

GitHub側の設定(シークレット)

APP_IDとAPP_PRIVATE_KEYを登録します。なお、このシークレット名は後述のymlと一緒のものを使っていればなんでもいいです。
APP_IDはカスタムアプリのID(数字で7桁ぐらいのもの)、APP_PRIVATE_KEYは-----BEGIN RSA PRIVATE KEY-----から始まる秘密鍵の内容すべて(-----BEGINや-----ENDも含む全ての行)です。

ymlの編集

claude.yml(または任意の名称)として保存しているymlに、以下の内容を- uses: anthropics/claude-code-action@betaの前に追加し、またuse_bedrock: "true"の次の行にgithub_tokenの設定を追加します。

anthropics/claude-code-action@betaの前
      - name: Generate GitHub App token
        id: app-token
        uses: actions/create-github-app-token@v2
        with:
          app-id: ${{ secrets.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}
use_bedrockの次の行
          github_token: "${{ steps.app-token.outputs.token }}"

ymlの編集が終わったら、pushします。これでカスタムアプリで動作するようになります。

その他使ってみてのコメント

時間の経過によって状況が変わる場合があります。

BedrockでのClaude Sonnet 4の一日に利用可能なトークン数とフォールバック

Bedrockが返却するエラーに503と429があります。うち429はトークン数によってよく発生するのですが、issueなどで503が返却されるケースについて言及がありました。AWSのクォータについて調べると、じつは以下のようなクォータがしれっと追加されています。

Model invocation max tokens per day for Anthropic Claude Sonnet 4 V1
10,000,000
10,000,000
利用不可
調整可能ではない

ただ、5/26の一日に入力だけで30,000,000トークンを超える処理を行ったのですが、503は一回しか観測されませんでした。(これまでもBedrockを利用してはいますが、一日でここまでは使っていませんでした)
ただ、503になって処理が全く進まなくても困るので、Claude Sonnet 4が動作しなかったときに3.7にフォールバックする設定を一応やってみました。(失敗すると中途半端なメッセージが残るので、4が正常動作していないことは把握できます。)

      - name: Claude Code (Sonnet 4)
        id: sonnet4
        continue-on-error: true
        uses: anthropics/claude-code-action@beta
        with:
          model: "us.anthropic.claude-sonnet-4-20250514-v1:0"
          use_bedrock: "true"

      - name: Claude Code (Sonnet 3.7)
        id: sonnet3_7
        if: steps.sonnet4.outcome == 'failure'
        uses: anthropics/claude-code-action@beta
        with:
          model: "us.anthropic.claude-3-7-sonnet-20250219-v1:0"
          use_bedrock: "true"

トークン超過対策

適当な使い方をすると、よくトークンが足りなくなります。シンプルに、トークンを使いすぎないように注意しろというと、実行できるようになったりします。(本質的な対策は後述)

情報に行き着くまでに時間がかかって終了する(構造化大事)

実際に使ってみてのちゃんとした(?)感想は、とにかく構造化が大事ということにつきます。つまり、入力の精度によってClaudeに何をやればよいかが伝わらなかったり、あるいは伝わっても調べるのにめちゃくちゃトークンを使ったり時間がかかったりします。
印象的だったのは、「問い合わせ設定の管理画面を修正しろ」というようなタスクで、日本語の「問い合わせ」を検索してどこで管理しているかということを調べるのにまず時間がかかり、さらにその管理画面の修正内容をどうするのがよいのか、他の一般的な画面を参考にしろと書いてしまうと すごくたくさんの他の画面 を調べだすという始末です。たしかに、Claudeにはそのような知識はないですよね。
反省して、CLAUDE.mdに構造についての情報を追加したり、DB設計がどこにあるとか、問い合わせ設定とはInquirySettingのことだと言及したり、具体的にこのデコレータを使えと指示してみたり、他の用例は一件調べれば十分と書いたり、ということをすると意図した通りにタスクが遂行されました。[3]

toolsを生やす

多分MCPサーバーを作る感覚と同じなのだと思いますが、Claude Code ActionにそのAction内で取りうる手段、toolsを与えるということが重要です。たとえば、テストをさせたい場合には、テストをするためのコマンドを以下のように与える必要があります。

          allowed_tools: |
            Bash(python src/some_script.py)

ルンバのための道をつくる、みたいな話がちょいちょいありますが、Claude Code Actionにも十分な手段を提供してやる必要があります。

祝わせる

今週のリリースを祝わせることにしました。

PRを閲覧するtoolsを使わせる必要があるため、以下を許可しました。

          allowed_tools: |
            mcp__github__get_pull_request,
            mcp__github__list_pull_requests,
            mcp__github__get_pull_request_files,
            mcp__github__get_pull_request_status,
            mcp__github__get_pull_request_comments,
            mcp__github__get_issue,
            mcp__github__get_issue_comments,
            mcp__github__list_issues,
            mcp__github__search_issues,

可能性の片鱗はすごく感じるので、どんどん積極的に使って遊んでいきたいですね!

脚注
  1. ちなみに、Claude Codeを(GitHub Actionを使わずに)Bedrockで動作させる方法については AI コーディングアシスタント Claude Code を Amazon Bedrock で試してみた という記事に記載があります。ただし、GitHub Actionの環境を構築するうえでは、ここに書かれている設定をする必要は一切ありません。 ↩︎

  2. 実際にはGitHubの操作をするために必要なトークンの作成などもやっていますが、省略しています。なお、5/25 7:00時点のREADMEではOIDCの説明においてカスタムアプリの設定も書いてありますが、カスタムアプリの設定は必要ありません。 ↩︎

  3. なお、これは私が意図した通りのことはできたものの、なんと問題になっていた修正は私の想定箇所ではなかったので、結局本質的には直っていないという...つらい ↩︎

Discussion