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

# Amazon Bedrock with an IAM role

> Let xpander call Amazon Bedrock in your AWS account by assuming an IAM role, with no stored keys.

xpander assumes a role in your AWS account and calls Bedrock with short-lived credentials. No access key is stored, you revoke access by editing the role, and calls show in your CloudTrail under the session `xpander-<your organization ID>`. Calls on your own Bedrock are never charged credits. You need an organization admin in xpander and permission to create IAM roles in the Bedrock account.

![Diagram](https://docs.xpander.ai/images/diagrams/run-integrations-bedrock-iam-role-e267f7a6.svg)

**xpander cloud**

**1. Copy the trust policy from xpander**

In **Platform > AI governance > Models**, choose **Add provider**, set **Provider** to **Amazon Bedrock** and **Credential** to **IAM role**. The dialog shows the xpander AWS role to trust, your **external ID** (your organization ID), and a trust policy and permissions policy to copy.

xpander always sends your external ID and you cannot change it, so another organization cannot use your role even if it knows the ARN.

**2. Create the role in AWS**

Create a role with the trust policy you copied. It has this shape:

```json theme={"dark"}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "<xpander role ARN shown in the dialog>" },
      "Action": "sts:AssumeRole",
      "Condition": { "StringEquals": { "sts:ExternalId": "<your organization ID>" } }
    }
  ]
}
```

```text AWS console theme={"dark"}
1. IAM > Roles > Create role.
2. Trusted entity type: Custom trust policy. Paste the trust policy from xpander.
3. Skip permissions for now and name the role, for example xpander-bedrock.
4. Create the role.
```

```bash AWS CLI theme={"dark"}
# trust.json is the trust policy copied from xpander
aws iam create-role \
  --role-name xpander-bedrock \
  --assume-role-policy-document file://trust.json
```

```hcl Terraform theme={"dark"}
resource "aws_iam_role" "xpander_bedrock" {
  name = "xpander-bedrock"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { AWS = var.xpander_principal_arn }      # shown in the dialog
      Action    = "sts:AssumeRole"
      Condition = { StringEquals = { "sts:ExternalId" = var.xpander_external_id } }  # your organization ID
    }]
  })
}
```

**3. Attach the permissions policy**

```json theme={"dark"}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "InvokeBedrockModels",
      "Effect": "Allow",
      "Action": [
        "bedrock:InvokeModel",
        "bedrock:InvokeModelWithResponseStream",
        "bedrock:CountTokens"
      ],
      "Resource": [
        "arn:aws:bedrock:*::foundation-model/*",
        "arn:aws:bedrock:*:*:inference-profile/*",
        "arn:aws:bedrock:*:*:application-inference-profile/*"
      ]
    }
  ]
}
```

```bash AWS CLI theme={"dark"}
# permissions.json is the permissions policy copied from xpander
aws iam put-role-policy \
  --role-name xpander-bedrock \
  --policy-name invoke-bedrock \
  --policy-document file://permissions.json
```

```hcl Terraform theme={"dark"}
resource "aws_iam_role_policy" "xpander_bedrock_invoke" {
  name = "invoke-bedrock"
  role = aws_iam_role.xpander_bedrock.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Sid    = "InvokeBedrockModels"
      Effect = "Allow"
      Action = ["bedrock:InvokeModel", "bedrock:InvokeModelWithResponseStream", "bedrock:CountTokens"]
      Resource = [
        "arn:aws:bedrock:*::foundation-model/*",
        "arn:aws:bedrock:*:*:inference-profile/*",
        "arn:aws:bedrock:*:*:application-inference-profile/*",
      ]
    }]
  })
}
```

You can narrow `Resource` to your models and regions. Keep the inference-profile entries for cross-region profiles such as `us.anthropic.claude-sonnet-4-5-20250929-v1:0`.

**4. Connect and test**

Paste the role ARN (for example `arn:aws:iam::123456789012:role/xpander-bedrock`), pick the region, and choose **Test connection**. A pass means xpander assumed the role and Bedrock accepted the call. Choose **Add role**.

**Hybrid and Air-Gapped**

The role your install runs as (IRSA or EKS Pod Identity) assumes the Bedrock role. The account is yours, so no external ID is required, though you can add one.

**1. Find your install's role**

In **Platform > AI governance > Models**, open the **Amazon Bedrock** row's menu and choose **Use your own key…** (or **Add key** under **Keys and models…**), then set **Credential** to **IAM role**. The dialog shows your install's role when it can read it. Otherwise use the IAM role on xpander's service account (IRSA or EKS Pod Identity).

**2. Create the Bedrock role**

```json theme={"dark"}
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::<your-account-id>:role/<role-your-xpander-install-runs-as>" },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

Also allow `sts:AssumeRole` on this role in your install role's own permissions.

**3. Attach the permissions policy**

The same policy as on xpander cloud: `bedrock:InvokeModel`, `bedrock:InvokeModelWithResponseStream` and `bedrock:CountTokens` on `foundation-model/*`, `inference-profile/*` and `application-inference-profile/*`.

**4. Connect and test**

On Air-Gapped, paste the role ARN, pick the region and choose **Test connection**. On Hybrid, the role is used from your cluster, so confirm by running an agent on Amazon Bedrock.

Or skip the extra role: give your install's own role the Bedrock permissions and leave the organization's Bedrock key empty. See [AI vendors](https://docs.xpander.ai/run/integrations/ai-vendors.md).

## Troubleshooting

| Message | What to check |
| - | - |
| xpander could not assume this role | The trust policy's `Principal` must be the exact role in the dialog, and on xpander cloud the `sts:ExternalId` must be your organization ID. Changes take a few seconds. Test again. |
| The role was assumed, but it cannot call Bedrock models in `<region>` | Attach the permissions policy. If you narrowed `Resource`, include your model or inference profile in that region. |
| Bedrock in `<region>` answered an error | Use a region where your models are available. Cross-region profiles (`us.`, `eu.`, `apac.`, `global.`) need every region they can reach allowed. |
| This role is in an xpander AWS account | Create the role in your own AWS account. |
| Enter the role's full ARN | Paste the ARN, not the role name. |

Fable- and Mythos-class Anthropic models also need the data-retention opt-in per region. See [AI vendors](https://docs.xpander.ai/run/integrations/ai-vendors.md).

## Next steps

> **[Set install-level Bedrock settings](https://docs.xpander.ai/run/integrations/ai-vendors.md)**
>
> Auth methods and the opt-in.

> **[Route calls through the AI gateway](https://docs.xpander.ai/run/integrations/ai-gateway.md)**
>
> How model calls reach the provider.


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