AnthropicWorkloadIdentity unstable
The AnthropicWorkloadIdentity module authenticates AnthropicClient with
Workload Identity Federation.
Constructors
Creates an HttpClient transform that authenticates Anthropic requests with
Workload Identity Federation.
When to use
Use as the transformClient option of AnthropicClient instead of an API key.
Details
The first request runs identityToken and exchanges the result at
${apiUrl}/v1/oauth/token with the jwt-bearer grant. The access token is
cached and sent as Authorization: Bearer with the oauth-2025-04-20 beta
until shortly before it expires. Concurrent requests share one exchange.
identityToken runs again on every exchange, so a token read from a file is
picked up after it rotates. Surrounding whitespace is trimmed.
Exchanges use the HttpClient captured by make, not the transformed client.
Failures are HttpClientErrors, mapped to AiError by AnthropicClient.
A failing or empty identityToken produces an EncodeError. Source failures
are preserved as causes and must not contain secrets. Exchange errors redact
the literal identity token, including JSON-escaped occurrences.
Gotchas
- No background refresh: the next request after expiry waits for an exchange.
- A 401 invalidates only the token used by that request, without replay.
- The exchange client must not follow redirects or log request bodies.
FetchHttpClientredirects are disabled; redirect responses fail the exchange. - Anthropic accepts an identity token with a
jticlaim once, so the exchange is never retried andidentityTokenmust yield a new token for each exchange. - The token URL must use
https, orhttponlocalhost,127.0.0.1or::1. Any other URL is a defect. - Leave the
apiKeyoption ofAnthropicClientunset.
See
- layer for providing the transformed
HttpClientas a layer
Signature
declare function make<E = never, R = never>(options: Options<E, R>): Effect<(client: HttpClient) => HttpClient, never, HttpClient | R>Example Reading a projected Kubernetes token
import { AnthropicClient, AnthropicWorkloadIdentity } from "@effect/ai-anthropic"import { Effect, FileSystem, Layer, Redacted } from "effect"
// Provide an `HttpClient` and a `FileSystem` to this layer.const AnthropicLayer = Layer.unwrap(Effect.gen(function*() { const fs = yield* FileSystem.FileSystem const transformClient = yield* AnthropicWorkloadIdentity.make({ identityToken: Effect.map( fs.readFileString("/var/run/secrets/anthropic.com/token"), Redacted.make ), federationRuleId: "fdrl_...", organizationId: "00000000-0000-0000-0000-000000000000", serviceAccountId: "svac_..." }) return AnthropicClient.layer({ transformClient })}))Layers
Provides the current HttpClient authenticated with workload identity federation.
When to use
Use with Layer.provide to authenticate AnthropicClient without
setting its transformClient option.
Details
Applies make to the current client, which also performs token exchanges.
The layer requires the services needed by identityToken.
Gotchas
- Every request carries the access token regardless of URL. Provide this
layer only to
AnthropicClient, not the whole application. - The gotchas of
makeapply.
See
- make for the client transform this layer applies
Signature
declare function layer<E = never, R = never>(options: Options<E, R>): Layer<HttpClient, never, HttpClient | R>Example
import { AnthropicClient, AnthropicWorkloadIdentity } from "@effect/ai-anthropic"import { Effect, FileSystem, Layer, Redacted } from "effect"
const WorkloadIdentity = AnthropicWorkloadIdentity.layer({ identityToken: Effect.gen(function*() { const fs = yield* FileSystem.FileSystem return Redacted.make(yield* fs.readFileString("/var/run/secrets/anthropic.com/token")) }), federationRuleId: "fdrl_...", organizationId: "00000000-0000-0000-0000-000000000000", serviceAccountId: "svac_..."})
// Requires an `HttpClient` and a `FileSystem`.const AnthropicLayer = AnthropicClient.layer({}).pipe( Layer.provide(WorkloadIdentity))Options
Options for authenticating Anthropic requests with Workload Identity Federation.
See
Signature
type Options<E = never, R = never> = { readonly apiUrl?: string; readonly federationRuleId: string; readonly identityToken: Effect.Effect<Redacted.Redacted<string>, E, R>; readonly organizationId: string; readonly serviceAccountId?: string; readonly workspaceId?: string;}