GitHub Actions with cloud providers
Route claude-code-action through Amazon Bedrock, Google Cloud's Agent Platform or Microsoft Foundry using OIDC, with no long-lived cloud keys in the repo.
Out of the box, Claude Code GitHub Actions calls the Claude API with an API key or subscription token. If your organisation buys Claude through a cloud provider, you can send inference there instead. The workflow proves who it is with GitHub's OpenID Connect (OIDC) token, your cloud swaps that for short-lived credentials, and nothing long-lived sits in your repository secrets.
This page assumes you already understand the basic workflow and only covers what changes.
Pick the provider
Use whichever cloud already has Claude model access for your organisation. One input on the action selects it:
| Provider | Input |
|---|---|
| Amazon Bedrock | use_bedrock: "true" |
| Google Cloud's Agent Platform | use_vertex: "true" |
| Microsoft Foundry | use_foundry: "true" |
What you need first
- Repository admin, to install an app and add secrets.
- Rights to create identity resources in the cloud: IAM roles and OIDC providers on AWS; Workload Identity Federation resources and service accounts on Google Cloud; Entra applications on Azure.
- Claude model access:
- Bedrock: access granted to the Claude models. Cross-region inference profiles (the
us.style IDs) need access in every region of the group. See Amazon Bedrock. - Agent Platform: a project with the Agent Platform API enabled and Claude access. See Google Cloud's Agent Platform.
- Foundry: a resource with a Claude deployment. See Microsoft Foundry.
- Bedrock: access granted to the Claude models. Cross-region inference profiles (the
Step 1: choose how the action talks to GitHub
The action needs a GitHub identity to push commits and comment. With a cloud provider you pick it yourself:
| Option | Trade-off |
|---|---|
| Official Claude GitHub App | Easiest; install it on the repo. Comes with its full shared permission set |
| Your own GitHub App | Least privilege: only Contents, Issues and Pull requests (read and write). More setup |
The built-in GITHUB_TOKEN | Nothing to install, but GitHub will not trigger CI on commits it makes |
To create your own app, register a new GitHub App with webhooks disabled (they are not used), grant the three permissions above, generate a private key (keep the .pem), note the App ID, and install it on the repository.
Step 2: make your cloud trust GitHub
All three providers trust the issuer https://token.actions.githubusercontent.com. Lock trust down to your repository in every case.
Amazon Bedrock
Following AWS's guide to OIDC identity providers:
- Add a GitHub OIDC provider: URL
https://token.actions.githubusercontent.com, audiencests.amazonaws.com. - Create an IAM role trusted by it as a web identity. Attach a scoped policy granting
bedrock:InvokeModel,bedrock:InvokeModelWithResponseStream,bedrock:ListInferenceProfilesandbedrock:GetInferenceProfile, plus the twoaws-marketplacesubscription actions described in the Bedrock IAM section. - In the trust policy, restrict the subject, e.g.
repo:northwind/api:*. GitHub's OIDC hardening guide explains the claim format.
Record the role ARN.
Google Cloud's Agent Platform
Following Google's Workload Identity Federation docs:
- Enable IAM Credentials, Security Token Service and the Agent Platform API (
aiplatform.googleapis.com). - Create a Workload Identity Pool with a GitHub OIDC provider (issuer as above) and an attribute condition limiting it to your repository.
- Create a dedicated service account with only
roles/aiplatform.user(Vertex AI User) and let the pool impersonate it.
Record the provider's full resource name and the service account email.
Microsoft Foundry
Following Microsoft's guide to authenticating from GitHub Actions:
- Register an Entra application (or use a user-assigned managed identity) and add a federated identity credential trusting your repository's tokens.
- Give it the Azure AI User role on the Foundry resource, or a narrower custom role (see Foundry RBAC).
Record the client ID, tenant ID and subscription ID.
Step 3: add secrets
| Secret | For | Holds |
|---|---|---|
AWS_ROLE_TO_ASSUME | Bedrock | IAM role ARN |
GCP_WORKLOAD_IDENTITY_PROVIDER | Agent Platform | Provider resource name |
GCP_SERVICE_ACCOUNT | Agent Platform | Service account email |
AZURE_CLIENT_ID | Foundry | Application client ID |
AZURE_TENANT_ID | Foundry | Entra tenant ID |
AZURE_SUBSCRIPTION_ID | Foundry | Subscription ID |
APP_ID | Custom GitHub App | App ID |
APP_PRIVATE_KEY | Custom GitHub App | Contents of the .pem |
None of these is a long-lived cloud credential; they are identifiers. The private key belongs to your GitHub App, not your cloud.
Step 4: write the workflow
Every variant shares the same shape: trigger on @claude, check the commenter, get a GitHub token, sign in to the cloud with OIDC, run the action. The job must have id-token: write, or GitHub will not issue the OIDC token.
Warning: On a public repository, anyone can post a comment containing
@claude. The action checks write access, but only after earlier steps have minted an app token and signed in to your cloud, leaving audit log entries and burning minutes. Put a permission check first, as below.
Here is the Bedrock version in full:
name: claude-bedrock
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened]
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
jobs:
claude:
if: >
contains(github.event.comment.body || '', '@claude') ||
contains(github.event.issue.body || '', '@claude') ||
contains(github.event.issue.title || '', '@claude')
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Require write access
env:
GH_TOKEN: ${{ github.token }}
ACTOR: ${{ github.actor }}
run: |
perm=$(gh api "repos/${{ github.repository }}/collaborators/$ACTOR/permission" --jq .permission)
case "$perm" in admin|maintain|write) ;; *) echo "No write access for $ACTOR"; exit 1;; esac
- uses: actions/checkout@v6
- name: 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 }}
- name: AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: eu-west-1
- uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.app-token.outputs.token }}
use_bedrock: "true"
claude_args: "--model eu.anthropic.claude-sonnet-4-6 --max-turns 15"
The credentials step exports AWS_REGION for the rest of the job. Bedrock model IDs carry a cross-region prefix (us., eu. and so on); use the one for the region group where you have access.
Swapping the cloud step for Agent Platform
Replace the AWS step and the action step with:
- name: Google Cloud auth
id: auth
uses: google-github-actions/auth@v2
with:
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
- uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.app-token.outputs.token }}
use_vertex: "true"
claude_args: "--model claude-sonnet-5 --max-turns 15"
env:
ANTHROPIC_VERTEX_PROJECT_ID: ${{ steps.auth.outputs.project_id }}
CLOUD_ML_REGION: europe-west1
The project ID comes from the auth step's output, so you do not hard-code it. Set CLOUD_ML_REGION to your region.
Swapping the cloud step for Foundry
- name: Azure login
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- uses: anthropics/claude-code-action@v1
with:
github_token: ${{ steps.app-token.outputs.token }}
use_foundry: "true"
claude_args: "--model claude-sonnet-5 --max-turns 15"
env:
ANTHROPIC_FOUNDRY_RESOURCE: northwind-ai-uks
ANTHROPIC_FOUNDRY_RESOURCE is your Foundry resource name; Claude Code builds the endpoint from it. The azure/login step signs in with OIDC, and Claude Code picks the credentials up through Azure's default credential chain. Use a model ID that matches a deployment in that resource.
If you chose a different GitHub identity
- Official Claude GitHub App: delete the app token step and the
github_tokenline. - Built-in token: delete the app token step and set
github_token: ${{ secrets.GITHUB_TOKEN }}.
In every variant, --max-turns in claude_args keeps runs and spend bounded. See GitHub Actions cost tips.
Step 5: test
Comment @claude on an issue or PR and watch the run under the repository's Actions tab. Claude replies on the same thread.
Troubleshooting
Authentication failures are nearly always OIDC configuration:
- Is
id-token: writepresent? - Does the trust condition match the repository exactly (owner and name, case included)?
- Do the secret names in the workflow match the ones you created?
Triggers or CI misbehaving work the same as with the Claude API; see the GitHub Actions troubleshooting.