OpenRouterWorkloadIdentity unstable
The OpenRouterWorkloadIdentity module authenticates OpenRouterClient with
workload identity federation.
Constructors
Creates an HttpClient transform that authenticates OpenRouter requests with
workload identity federation.
When to use
Use as the transformClient option of OpenRouterClient instead of an API
key.
Details
The first request runs identityToken and exchanges the result at
{apiUrl}/oauth/token with the RFC 8693 token-exchange grant and the
inference scope. 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 OpenRouterClient.
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
- The identity token must be a JWT. OIDC ID tokens are JWTs.
- The federation policy must grant the
inferencescope. A policy that acts as a management key is rejected. - 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. - The exchange is never retried.
- The token URL must use
https, orhttponlocalhost,127.0.0.1or::1. Any other URL is a defect. - Leave the
apiKeyoption ofOpenRouterClientunset. The access token replaces it.
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 { OpenRouterClient, OpenRouterWorkloadIdentity } from "@effect/ai-openrouter"import { Effect, FileSystem, Layer, Redacted } from "effect"
// Provide an `HttpClient` and a `FileSystem` to this layer.const OpenRouterLayer = Layer.unwrap(Effect.gen(function*() { const fs = yield* FileSystem.FileSystem const transformClient = yield* OpenRouterWorkloadIdentity.make({ identityToken: Effect.map( fs.readFileString("/var/run/secrets/openrouter.ai/token"), Redacted.make ), federationPolicyId: "..." }) return OpenRouterClient.layer({ transformClient })}))Layers
Provides the current HttpClient authenticated with workload identity federation.
When to use
Use with Layer.provide to authenticate OpenRouterClient 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
OpenRouterClient, not the whole application. - An
apiKeyoption ofOpenRouterClientreplaces the access token here, so leave it unset. - The other 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 { OpenRouterClient, OpenRouterWorkloadIdentity } from "@effect/ai-openrouter"import { Effect, FileSystem, Layer, Redacted } from "effect"
const WorkloadIdentity = OpenRouterWorkloadIdentity.layer({ identityToken: Effect.gen(function*() { const fs = yield* FileSystem.FileSystem return Redacted.make(yield* fs.readFileString("/var/run/secrets/openrouter.ai/token")) }), federationPolicyId: "..."})
// Requires an `HttpClient` and a `FileSystem`.const OpenRouterLayer = OpenRouterClient.layer({}).pipe( Layer.provide(WorkloadIdentity))Options
Options for authenticating OpenRouter requests with workload identity federation.
See
Signature
type Options<E = never, R = never> = { readonly apiUrl?: string; readonly federationPolicyId: string; readonly identityToken: Effect.Effect<Redacted.Redacted<string>, E, R>;}