Follow Discord
Sweep 06 Nov 2026 · 01:32Z Build v2.1.319 537 read Stable v2.1.311 Latest v2.1.319 Next v2.1.319 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · api

github-actions changedmanage-claude/wif-providers/github-actions

Nearest release: v2.1.319, published 17 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+39added
Lines−37removed
From line 4 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits16to this page, all time

The whole hunk

from line 4, old and new numbered
/
lines
from line 4
44description: Authenticate GitHub Actions workflows to the Claude API with short-lived identity tokens instead of long-lived API keys.
55---
66 
7Every GitHub Actions workflow run can request a signed identity token from GitHub’s hosted issuer at `https://token.actions.githubusercontent.com`. With Workload Identity Federation, your workflow exchanges that token for a short-lived Anthropic access token, so your CI jobs can call the Claude API without an `ANTHROPIC_API_KEY` secret stored in your repository.
7Every GitHub Actions workflow run can request a signed identity token from GitHub’s hosted issuer at `https://token.actions.githubusercontent.com`. With Workload Identity Federation (WIF), your workflow exchanges that token for a short-lived Anthropic access token. Your CI jobs can then call the Claude API without an `ANTHROPIC_API_KEY` secret stored in your repository.
88 
9The token’s `sub` claim encodes the repository and trigger context. For a push to a branch it has the form `repo:<owner>/<repo>:ref:refs/heads/<branch>`. Pull-request runs use `repo:<owner>/<repo>:pull_request`, and environment-gated deployments use `repo:<owner>/<repo>:environment:<name>`. Your federation rule matches against this claim (and others, such as `repository_owner` and `ref`) to determine which workflow runs are allowed to authenticate.
9The token’s `sub` claim encodes the repository and trigger context. For a push to a branch it has the form `repo:<owner>/<repo>:ref:refs/heads/<branch>`. Pull-request runs use `repo:<owner>/<repo>:pull_request`, and environment-gated deployments use `repo:<owner>/<repo>:environment:<name>`. Your federation rule matches against this claim (and others, such as `repository_owner` and `ref`) to determine which workflow runs can authenticate.
1010 
1111## Prerequisites
1212 
from line 25
2525 contents: read
2626```
2727 
28Inside the job, the runner exposes two environment variables: `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN`. Call the request URL with the request token as a bearer credential and your chosen audience as a query parameter, then write the returned JSON Web Token (JWT) to a file:
28Inside the job, the runner exposes two environment variables: `ACTIONS_ID_TOKEN_REQUEST_URL` and `ACTIONS_ID_TOKEN_REQUEST_TOKEN`. Call the request URL with the request token as a bearer credential and your chosen audience as a query parameter. Then write the returned JSON Web Token (JWT) to a file:
2929 
3030```yaml
3131- name: Fetch GitHub OIDC token
from line 105
105105}
106106```
107107 
108Be as specific as the workload allows. Loosen `subject_prefix` to `repo:your-org/your-repo:*` (paired with a `claims.ref` constraint) only if the rule must match multiple event types from the same repository, because the trailing segment of `sub` varies among `ref:...`, `environment:...`, and `pull_request` events.
108Be as specific as the workload allows. Loosen `subject_prefix` to `repo:your-org/your-repo:*` (paired with a `claims.ref` constraint) only if the rule must match multiple event types from the same repository. The trailing segment of `sub` varies among `ref:...`, `environment:...`, and `pull_request` events.
109109 
110110## Acquire and use a token
111111 
112Set the federation environment variables on the job. In the SDK, `anthropic.Anthropic()` (typescript: `new Anthropic()`; csharp: `new AnthropicClient()`; go: `anthropic.NewClient()`; java: `AnthropicOkHttpClient.fromEnv()`; php: `new Client()`; ruby: `Anthropic::Client.new`) reads `ANTHROPIC_IDENTITY_TOKEN_FILE`, exchanges the JWT on the first request, and refreshes the access token automatically before it expires.
112Set the federation environment variables on the job, and write GitHub’s OIDC token to the file that `ANTHROPIC_IDENTITY_TOKEN_FILE` names:
113113 
114<CodeGroup>
115 ```yaml Workflow
116 name: Call Claude
117 on: push
114```yaml
115name: Call Claude
116on: push
118117 
119 permissions:
120 id-token: write
121 contents: read
118permissions:
119 id-token: write
120 contents: read
122121 
123 jobs:
124 call-claude:
125 runs-on: ubuntu-latest
126 env:
127 ANTHROPIC_FEDERATION_RULE_ID: fdrl_...
128 ANTHROPIC_ORGANIZATION_ID: 00000000-0000-0000-0000-000000000000
129 ANTHROPIC_SERVICE_ACCOUNT_ID: svac_...
130 ANTHROPIC_WORKSPACE_ID: wrkspc_... # required when the rule covers multiple workspaces
131 ANTHROPIC_IDENTITY_TOKEN_FILE: /tmp/gha-jwt
132 steps:
133 - uses: actions/checkout@v5
134 - name: Fetch GitHub OIDC token
135 run: |
136 curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
137 "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://api.anthropic.com" \
138 | jq -r .value > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
139 - name: Run your script
140 run: |
141 pip install anthropic
142 python your_script.py
143 ```
122jobs:
123 call-claude:
124 runs-on: ubuntu-latest
125 env:
126 ANTHROPIC_FEDERATION_RULE_ID: fdrl_...
127 ANTHROPIC_ORGANIZATION_ID: 00000000-0000-0000-0000-000000000000
128 ANTHROPIC_SERVICE_ACCOUNT_ID: svac_...
129 ANTHROPIC_WORKSPACE_ID: wrkspc_... # required when the rule covers multiple workspaces
130 ANTHROPIC_IDENTITY_TOKEN_FILE: /tmp/gha-jwt
131 steps:
132 - uses: actions/checkout@v5
133 - name: Fetch GitHub OIDC token
134 run: |
135 curl -sS -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
136 "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://api.anthropic.com" \
137 | jq -r .value > "$ANTHROPIC_IDENTITY_TOKEN_FILE"
138 - name: Run your script
139 run: |
140 pip install anthropic
141 python your_script.py
142```
144143 
144Then call the Claude API from your script. An SDK client that you create without credentials reads `ANTHROPIC_IDENTITY_TOKEN_FILE`, exchanges the JWT on the first request, and refreshes the access token automatically before it expires.
145 
146<CodeGroup>
145147 ```bash cURL
146148 JWT=$(cat /tmp/gha-jwt)
147149 
from line 315
313315 
314316## Verify the setup
315317 
316A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. A denied exchange returns an opaque `401` `authentication_error` with the fixed message `Authentication failed`, whichever check failed. In most cases the deny reason is recorded on the attempt’s entry in the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console. [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) walks the checks in order. The most common GitHub Actions-side cause is the `sub` claim format not matching (its trailing segment varies among `ref:...`, `environment:...`, and `pull_request` events); the history entry shows reason `match_subject_prefix`.
318A successful exchange returns an `access_token` starting with `sk-ant-oat01-` and an `expires_in` value in seconds. A denied exchange returns an opaque `401` `authentication_error` with the fixed message `Authentication failed`, whichever check failed. In most cases, the attempt’s entry on the [authentication history page](https://platform.claude.com/settings/workload-identity-federation?tab=history) in the Claude Console shows the deny reason. [Troubleshoot a failed exchange](https://platform.claude.com/docs/en/manage-claude/wif-reference#troubleshoot-a-failed-exchange) walks through the checks in order. The most common GitHub Actions-side cause is a `sub` claim format that doesn’t match, because its trailing segment varies among `ref:...`, `environment:...`, and `pull_request` events. The history entry then shows the reason `match_subject_prefix`.
317319 
318320## Restrict which workflows can authenticate
319321 
Feedback