Skip to main content
Feature available with the Enterprise Plan Workload federation lets an external workload exchange the OIDC token issued by its own identity provider for a short-lived Orq.ai API key. No Orq.ai secret is stored in the workload. The key is scoped to one project, carries only the granted permissions, and expires automatically. The name describes what is federated: the identity of a workload (a process that runs without a person), not the identity of the workspace. Orq.ai is the side that trusts the external issuer here. Related pages:
  • Single Sign-On covers member login with OIDC or SAML and SCIM provisioning. Workload federation is for machine identities, not for people signing in.
  • Session identity tokens covers the reverse direction, where Orq.ai issues OIDC tokens that AWS, Google Cloud, Vault, and other relying parties verify.

Use cases

A workload is any process that calls Orq.ai with no person driving it, authenticating with an identity its own platform already issues. It is not an Orq.ai API key, and it is not a person signed in to the dashboard. A CI/CD job, a scheduled batch job, a backend service, a long-running application, or a deploy pipeline all qualify.
The issuer’s discovery document must be reachable from the public internet, so an in-cluster Kubernetes issuer works only when it is published that way.
If the process would otherwise need an Orq.ai credential stored and rotated, it is a candidate for federation. If a person signs in, use Single Sign-On. Each case below needs one trust configuration: an issuer, claim rules that narrow who may exchange, and the permissions the job uses.
  • Run evaluations from CI. A GitHub Actions workflow on one repository’s main branch, bound to repository_id and ref.
  • Sync Prompts from a pipeline. A GitLab CI pipeline bound to project_id and ref.
  • Call the AI Gateway from a service. A backend service behind Keycloak, Okta, Auth0, or Microsoft Entra ID, bound to its azp or appid.
  • Reach the production Deployment only from a protected environment. A pipeline bound to repository_id and environment.
  • Export usage on a schedule. A Read only trust that cannot create or change anything.
Set up GitHub Actions step by step walks the first case end to end, and every granted exchange is recorded under Settings > Organization > Audit logs.

How it works

  1. The workload asks its identity provider for an OIDC token with a specific aud (audience) value.
  2. The workload sends that token to the Orq.ai token exchange endpoint.
  3. Orq.ai finds the trust configuration matching the token’s issuer and audience, verifies the signature against the issuer’s published keys, and checks the token’s claims against the configured rules.
  4. Orq.ai returns a short-lived API key limited to the permissions and project on the trust configuration.
  5. The workload uses the key as a normal Bearer token until it expires.
The only values the two sides have to agree on are public: the issuer URL and the audience. The subject token itself stays the credential and is sent only to the exchange endpoint.

Prerequisites

  • A workspace on the Enterprise plan. Configuring SSO first is not required.
  • Workspace admin rights to manage trust configurations.
  • An identity provider that issues OIDC JWTs and publishes its signing keys through OpenID discovery. The discovery document and signing keys must be reachable from the public internet.
  • Workload federation is tested with GitHub Actions (including GitHub Enterprise Server) and Keycloak. Other providers such as GitLab CI, Okta, Auth0, and Microsoft Entra ID work when their tokens meet the requirements under Exchange a token.

Create a trust configuration

Go to Settings > Organization > Workload federation and click Add trust configuration. An existing configuration can be disabled from its edit view to stop exchanges without deleting it.
An issuer and audience pair can belong to only one enabled trust configuration across all of Orq.ai. If a pair is already in use, the configuration is refused; keep the generated audience to avoid this.
Any change to a trust configuration, including renaming it, changing its lifetime, or turning it off, revokes every key it has already minted. Deleting a trust configuration revokes all of its keys. Workloads obtain a new key on their next exchange.

Set up GitHub Actions step by step

This walkthrough lets the main branch of the acme/evals repository call the AI Gateway.
  1. Find the repository’s numeric ID using any of these:
    • Browser (public repositories): open https://api.github.com/repos/acme/evals and copy the top-level "id" value.
    • GitHub CLI (public or private): gh api repos/acme/evals --jq .id
    • From a workflow run: add a step with echo "${{ github.repository_id }}". Use github.repository_owner_id for the organization ID.
    Example result: 812345678. Replace acme/evals with the target repository.
  2. In Orq.ai, go to Settings > Organization > Workload federation, click Add trust configuration, and fill in:
  3. In the GitHub repository, go to Settings > Secrets and variables > Actions > Variables and add a repository variable ORQ_AUDIENCE with the copied audience. The audience is not a secret, so a variable is enough.
  4. Add the workflow from GitHub Actions to .github/workflows/.
  5. Push to main. The job exchanges its GitHub token for an Orq.ai API key and calls the AI Gateway. The exchange appears in Settings > Organization > Audit logs as federation.exchange.granted, with the token subject.
If the exchange step fails with invalid_target, see Troubleshooting.

Claim rules

A rule is a list of conditions. A token is accepted when every condition of any single rule matches. Rules are combined with OR, conditions within a rule with AND. Each condition names a claim and lists its allowed values:
  • A value without * must match the claim exactly.
  • A value containing * is a glob anchored at both ends. * matches any characters except :, so repo:acme/*:ref:refs/heads/main cannot be widened by a token whose sub contains extra : segments.
  • A missing claim, or a claim that is not a string, fails the condition.
A trust configuration holds up to 20 rules, each with up to 20 conditions, each with up to 50 values. Rules decide which tokens are accepted. The issuer and audience only prove that the token came from the right provider; the rules narrow it down to a specific repository, branch, environment, user, or application.
A rule that is too broad hands out keys to everything that provider signs tokens for. Start narrow and widen only when needed.

Which claims to use

Every OIDC provider puts different claims in its tokens. The ones that identify a workload or a person: To see the exact claims and values a provider sends, decode one of its tokens before writing rules:
A live subject token is the credential itself, so decode it locally. An already-expired token is safe to paste into an online decoder such as jwt.io, and nothing needs decoding on the Orq.ai side: the exchange endpoint verifies the signature itself.
Claim names are case-sensitive, and a rule on a claim the provider does not send never matches.

Common rules

Conditions in the same rule are ANDed, so each row above accepts only tokens that satisfy every condition in it.
  • To allow alternatives, add a rule per alternative. To accept two repositories, create two rules, each binding its own repository_id; a token from either repository matches one of them and is accepted.
  • To allow several values in one condition, list them. ref with refs/heads/main and refs/heads/release accepts a token from either branch.

GitHub Actions rules

GitHub Actions tokens have two additional requirements. Bind a numeric ID. Every rule must bind repository_id or repository_owner_id to a value without *. Repository and organization names can be renamed or transferred; the numeric IDs cannot. To find them:
  • Open https://api.github.com/repos/<owner>/<repo> for a public repository, or run gh api repos/<owner>/<repo> --jq .id. The organization ID is .owner.id in the same response.
  • Inside a workflow, ${{ github.repository_id }} and ${{ github.repository_owner_id }} print the exact values the token carries.
Restrict the events. These events are accepted:
  • push, workflow_dispatch, schedule, release, create, deployment, deployment_status.
Any other event, such as pull_request from a fork or a merge queue, is rejected unless every rule has an event_name condition with exact values. A value containing * does not count.
To accept pull request workflows on purpose, add an event_name condition to each rule and list every accepted event, for example push and pull_request. A rule with only event_name = pull_request rejects tokens from pushes.

Exchange a token

The exchange endpoint implements OAuth 2.0 Token Exchange (RFC 8693).
No Orq.ai credential is sent. The subject token is the credential. A successful response returns the key:
expires_in is the lifetime configured on the trust configuration, independent of the subject token’s own expiry. The subject token must:
  • Be signed by the issuer’s current keys, with iss equal to the trust configuration’s issuer URL.
  • Contain the trust configuration’s audience in aud.
  • Have been issued (iat) within the last 10 minutes.
  • Carry a jti claim. Each token can be exchanged once.

Errors

Use the key

The minted key is a standard Orq.ai API key.
  • Send it as Authorization: Bearer <key> to the platform API, the AI Gateway, and an MCP Gateway.
  • Scope: the granted permissions and the pinned project only.
  • Lifetime: it stops working when it expires.
  • Audit: each grant is recorded as federation.exchange.granted, with the trust configuration, the token subject, the key ID, and its expiry.

Examples

GitHub Actions

The exchange step exports the minted key as ORQ_API_KEY, so every later step uses it exactly as it would a stored API key.
  • The CLI reads ORQ_API_KEY directly. ORQ_NO_INPUT=1 makes it fail instead of prompting, so a misconfigured job errors out rather than hanging.
  • The SDKs read the same variable. The step can just as well be a script using the Node SDK (@orq-ai/node) or the Python SDK (orq-ai-sdk).
  • id-token: write is required. Without it, GitHub does not issue an OIDC token to the job.
ORQ_AUDIENCE is the repository variable from Set up GitHub Actions step by step.
The trust configuration for this workflow uses issuer https://token.actions.githubusercontent.com, one rule with repository_id set to the repository’s numeric ID and ref set to refs/heads/main, and grants the Chat completions permission.

Keycloak

Orq.ai reads the audience from the ID token, not the access token.
  1. In Keycloak, open the client the workload uses, then make the ID token carry the audience:
    • Simplest: create the trust configuration with the client ID as its audience, because Keycloak already puts the client ID in the ID token’s aud.
    • Explicit: add an Audience mapper to the client with Included Custom Audience set to the trust configuration’s audience and Add to ID token turned on.
  2. Create a trust configuration with issuer https://<keycloak-host>/realms/<realm> and a rule that limits who may exchange, for example azp = <client-id> for one application or email = jane@example.com for one user.
  3. Request tokens with scope=openid so Keycloak returns an ID token, then exchange it:

Other OIDC providers

Request an ID token from the provider with the trust configuration’s audience in aud, then send it to the exchange endpoint as shown above. Add a rule on a claim such as preferred_username, email, or sub to limit which principals may exchange tokens.

Troubleshooting

Every token rejection returns the same invalid_target error. Open Settings > Organization > Audit logs and look for federation.exchange.denied on the trust configuration. The reason names what to fix: If no denied entry appears, Orq.ai could not link the token to a trust configuration, could not verify it, or the per-trust denial-audit budget was exhausted. Check that:
  • The token’s iss exactly matches the Issuer URL, including the scheme and without a trailing slash.
  • The token’s aud contains the trust configuration’s audience, and the same audience is sent in the audience parameter.
  • The issuer’s discovery document and signing keys are reachable from the public internet, and the token is signed with one of those keys.
  • The trust configuration is enabled.
  • The workspace is on the Enterprise plan.

Security

  • Token rejections return the same generic error, so a caller cannot discover which issuers or audiences are configured.
  • Each subject token can be exchanged once. Replays are rejected.
  • Subject tokens older than 10 minutes are rejected regardless of their own expiry.
  • Exchanges are limited to 60 per minute per trust configuration.
  • Granted exchanges, and denials of correctly signed tokens meant for a trust configuration, are recorded in the workspace audit log. Denials are capped at 20 per minute per trust configuration.
  • Keys minted from a configuration created in the dashboard are pinned to its project, and no minted key can hold workspace administration permissions.
  • Issuer discovery and key fetches refuse redirects.

Limitations

  • A workspace holds up to 100 trust configurations.
  • Trust configurations are managed by workspace admins from the dashboard. They cannot be created or edited with an API key.
  • The trust configuration’s audience must appear in the token’s aud. If the identity provider cannot add a custom value, use a value it already sends, such as the client ID, as long as no other trust configuration uses the same issuer and audience.
  • Identity providers on a private network are not supported. Orq.ai must be able to fetch the issuer’s discovery document and signing keys over the public internet.