Skip to content
// EFFECT DAYS 2026

OpenAiWorkloadIdentity unstable

The OpenAiWorkloadIdentity module authenticates OpenAiClient with workload identity federation.

3 exports Since v4.1.3 Source

Constructors

make

unstable
Since v4.1.3

Creates an HttpClient transform that authenticates OpenAI requests with workload identity federation.

When to use

Use as the transformClient option of OpenAiClient instead of an API key.

Details

The first request runs identityToken and exchanges the result at https://auth.openai.com/oauth/token with the token-exchange grant. The access token is cached and sent as Authorization: Bearer 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 OpenAiClient. 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.

In WebSocket mode the access token is resolved each time a socket connects.

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.
  • A WebSocket keeps the token it connected with. A rejected WebSocket handshake does not discard the cached token, because the socket does not report the response status.
  • The exchange client must not follow redirects or log request bodies. FetchHttpClient redirects are disabled; redirect responses fail the exchange.
  • The exchange is never retried.
  • The token URL must use https, or http on localhost, 127.0.0.1 or ::1. Any other URL is a defect.
  • Leave the apiKey option of OpenAiClient unset. The access token replaces it.
  • The access token is not accepted by the Admin API.

See

  • layer for providing the transformed HttpClient as 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 { OpenAiClient, OpenAiWorkloadIdentity } from "@effect/ai-openai"
import { Effect, FileSystem, Layer, Redacted } from "effect"
// Provide an `HttpClient` and a `FileSystem` to this layer.
const OpenAiLayer = Layer.unwrap(Effect.gen(function*() {
const fs = yield* FileSystem.FileSystem
const transformClient = yield* OpenAiWorkloadIdentity.make({
identityToken: Effect.map(
fs.readFileString("/var/run/secrets/openai.com/token"),
Redacted.make
),
identityProviderId: "idp_...",
serviceAccountId: "sa_..."
})
return OpenAiClient.layer({ transformClient })
}))

Layers

layer

unstable
Since v4.1.3

Provides the current HttpClient authenticated with workload identity federation.

When to use

Use with Layer.provide to authenticate OpenAiClient 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 OpenAiClient, not the whole application.
  • An apiKey option of OpenAiClient replaces the access token here, so leave it unset.
  • The other gotchas of make apply.

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 { OpenAiClient, OpenAiWorkloadIdentity } from "@effect/ai-openai"
import { Effect, FileSystem, Layer, Redacted } from "effect"
const WorkloadIdentity = OpenAiWorkloadIdentity.layer({
identityToken: Effect.gen(function*() {
const fs = yield* FileSystem.FileSystem
return Redacted.make(yield* fs.readFileString("/var/run/secrets/openai.com/token"))
}),
identityProviderId: "idp_...",
serviceAccountId: "sa_..."
})
// Requires an `HttpClient` and a `FileSystem`.
const OpenAiLayer = OpenAiClient.layer({}).pipe(
Layer.provide(WorkloadIdentity)
)

Options

Options

type unstable
Since v4.1.3

Options for authenticating OpenAI requests with Workload Identity Federation.

See

  • make for creating a client transform from these options
  • layer for providing a transformed HttpClient from these options

Signature

type Options<E = never, R = never> = {
readonly identityProviderId: string;
readonly identityToken: Effect.Effect<Redacted.Redacted<string>, E, R>;
readonly identityTokenType?: "jwt" | "id_token";
readonly serviceAccountId: string;
readonly tokenUrl?: string;
}