> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abundly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Workload identity

> Give agents keyless access to your Google Cloud

Every agent has its own **workload identity**: a short-lived, signed token that says which workspace, team and agent is calling. Instead of handing the platform a long-lived service account key, you configure your cloud to trust that identity and grant it exactly the access it needs. No key is stored anywhere.

This uses standard OpenID Connect, so it works with Google Cloud [Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation). Today it can be used by the [Google Drive](/integrations/google-drive) and [BigQuery](/integrations/bigquery) capabilities.

<Note>
  Workload identity is an enterprise feature. Contact [support@abundly.ai](mailto:support@abundly.ai) to enable it for your workspace.
</Note>

## The agent's identity

Workspace admins find the values your cloud needs under **Workspace → Workload identity**:

* **Issuer URL** — the URL your cloud trusts, for example `https://app.abundly.ai/oidc`. It's the same for every agent in your deployment.
* **Workspace ID** — used to restrict the trust to your workspace.

Each agent's **subject** — its unique identity — is `workspace:<workspace id>:team:<team id>:agent:<agent id>` (agents without a team have `team:none`). When a capability is set to workload identity, its settings show the exact principals to grant for that agent, its team and the whole workspace.

Each token also carries these claims. Every claim is always present, empty when it doesn't apply:

| Claim | Contains |
| - | - |
| `workspace_id`, `team_id`, `agent_id` | Stable IDs (`team_id` is `none` without a team). Grant access with these. |
| `workspace_name`, `team_name`, `agent_name` | Display names, for readable bindings and logs. Names can be edited, so never grant access by name. |
| `trigger` | How the run started, for example `chat`, `scheduler`, `email`, `sms`, `webhook`, `http`, `voice` or `agentCommunication` |
| `chat_id` | The chat, for runs in a chat |
| `run_id` | The activity log entry, for triggered runs outside a chat |
| `user_id` | The signed-in user the agent acts for, in chats in the web app. Empty when there's no verified user, for example scheduled runs, inbound email, or Slack. |

Tokens are minted per run, so a token issued for one user or run is never reused for another.

For example, the decoded token of an agent in a team, working in a chat started by a signed-in user, used for Google Cloud:

```json theme={null}
{
  "iss": "https://app.abundly.ai/oidc",
  "aud": "//iam.googleapis.com/projects/123456789/locations/global/workloadIdentityPools/abundly/providers/abundly",
  "sub": "workspace:64f1a2b3c4d5e6f708192a3b:team:69a1c2e4b7d93f0a12c4e8b1:agent:65a0b1c2d3e4f5061728394a",
  "iat": 1791212400,
  "nbf": 1791212400,
  "exp": 1791212700,
  "jti": "3f6c2a9e-8b41-4d7a-9c55-0e2f7b1d4a90",
  "workspace_id": "64f1a2b3c4d5e6f708192a3b",
  "workspace_name": "Acme Logistics",
  "team_id": "69a1c2e4b7d93f0a12c4e8b1",
  "team_name": "Data platform",
  "agent_id": "65a0b1c2d3e4f5061728394a",
  "agent_name": "Data analyst",
  "trigger": "chat",
  "chat_id": "6b02d7e1a4c95f3e8d71b260",
  "run_id": "",
  "user_id": "68f4b0c2d9e17a5b3c6f0d94"
}
```

The same agent on a schedule has `"trigger": "scheduler"`, a `run_id`, and empty `chat_id` and `user_id`.

<Warning>
  Always restrict the trust to **your** workspace ID (step 2 below). Without that condition, agents in other workspaces on the same platform could use your pool.
</Warning>

## Set up Google Cloud

<Steps>
  <Step title="Enable the APIs">
    In your Google Cloud project, enable the **IAM Service Account Credentials API** and the **Security Token Service API**, plus the APIs the capability uses (Drive, Docs and Sheets for Google Drive; BigQuery for BigQuery).
  </Step>

  <Step title="Create a workload identity pool that trusts Abundly">
    Replace the issuer URL and `YOUR_WORKSPACE_ID` with the values from **Workspace → Workload identity**.

    ```bash theme={null}
    gcloud iam workload-identity-pools create abundly \
      --location=global --display-name="Abundly agents"

    gcloud iam workload-identity-pools providers create-oidc abundly \
      --location=global --workload-identity-pool=abundly \
      --issuer-uri="https://app.abundly.ai/oidc" \
      --attribute-mapping="google.subject=assertion.sub,attribute.workspace_id=assertion.workspace_id,attribute.team_id=assertion.team_id,attribute.agent_id=assertion.agent_id" \
      --attribute-condition="assertion.workspace_id == 'YOUR_WORKSPACE_ID'"
    ```

    In Google Cloud, a pool trusts an external issuer through what Google calls a *provider*. Open it under **IAM & Admin → Workload Identity Federation** and copy its **Default audience** (`https://iam.googleapis.com/projects/<project number>/locations/global/workloadIdentityPools/abundly/providers/abundly`). That's the value you paste into Abundly.
  </Step>

  <Step title="Grant access">
    Choose who gets access with the `--member` value:

    | Who | Member |
    | - | - |
    | One agent | `principal://iam.googleapis.com/projects/<project number>/locations/global/workloadIdentityPools/abundly/subject/<subject>` |
    | A team | `principalSet://iam.googleapis.com/projects/<project number>/locations/global/workloadIdentityPools/abundly/attribute.team_id/<team id>` |
    | All agents in the workspace | `principalSet://iam.googleapis.com/projects/<project number>/locations/global/workloadIdentityPools/abundly/*` |

    **Google Drive** needs a service account, because Drive files are shared with an email address. Create one, let the agent act as it, then share files or folders with the service account's email:

    ```bash theme={null}
    gcloud iam service-accounts add-iam-policy-binding drive-agent@your-project.iam.gserviceaccount.com \
      --role=roles/iam.workloadIdentityUser \
      --member="<member from the table>"
    ```

    **BigQuery** can grant roles to the agent directly, without a service account:

    ```bash theme={null}
    gcloud projects add-iam-policy-binding your-project \
      --role=roles/bigquery.jobUser --member="<member from the table>"
    ```

    Add `roles/bigquery.dataViewer` and `roles/bigquery.metadataViewer` the same way, on the project or on specific datasets. Queries run, and are billed, in a project where the agent has **BigQuery Job User**.
  </Step>

  <Step title="Connect your workspace">
    In **Workspace → Workload identity**, add the Default audience under **Audiences**, with a label such as "Google Cloud". Each relying party that trusts your agents gets its own audience in this list, so tokens meant for one can't be used at another.
  </Step>

  <Step title="Configure the capability">
    * **BigQuery:** set **Authentication** to **Workload identity** and save. If the workspace has more than one Google Cloud audience, pick which one to use. There's no project to configure: the agent works in the projects you granted it access to. To point agents at the right projects and datasets, add a note to the capability in the workspace or team settings, or keep a data guide as a workspace document.
    * **Google Drive:** choose **Workload identity** mode, pick the audience if there are several, enter the service account email, save, then click **Test connection**.
  </Step>
</Steps>

## Good to know

* An agent's subject includes its team, so moving an agent to another team changes its identity. Team-based grants follow the agent automatically; grants on the old subject stop working.
* Tokens are valid for five minutes and are only used by the platform to obtain Google credentials. They are never shown to the agent's model.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.