AWS Bedrock
Discover AWS Bedrock Agents and Flows, with the IAM policies to provision on your side.
Airia discovers AWS Bedrock Agents and Flows in your AWS account and can additionally secure those agents by routing their AI requests through the Airia Gateway.
There are two setup tiers. Choose based on what you want:
| Goal | What to provision |
|---|---|
| Discovery only (inventory and governance of Bedrock agents) | An IAM user with the small read-only policy in "Tier 1" below |
| Discovery + securing agents through the Airia Gateway | The full integration setup in "Tier 2": two customer-managed policies plus an IAM user |
Start with Tier 1 if you are evaluating. You can add the Tier 2 policies later without recreating the connection.
What Airia discovers
Bedrock Agents (with status, version, foundation model, and action groups) and Bedrock Flows in the connected account and region. Each discovered agent becomes an inventory entry with its metadata available for governance, classification, and risk scoring.
Discovery covers only Bedrock Agents and Flows. Plain model invocation, Knowledge Bases, and AgentCore runtimes are not discovered by this connector. For AgentCore, see AWS AgentCore.
Authentication model
An IAM user access key (access key ID + secret access key) and a region. A session token is optional. Discovery does not assume a role.
Temporary STS credentials (with a session token) expire. When they do, the next sync fails ("The security token included in the request is expired") until you update the connection with fresh credentials. Use long-lived IAM user keys for scheduled discovery.
One connection covers one AWS account and one region. Agents and flows in other regions are not discovered; create one connection per region (and per account).
Tier 1: Discovery-only IAM policy
Create an IAM user (for example airia-discovery), attach a policy with exactly these
actions, and create an access key for it. All actions are read-only.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"bedrock:ListAgents", "bedrock:GetAgent",
"bedrock:ListAgentActionGroups",
"bedrock:ListFlows", "bedrock:GetFlow",
"bedrock:GetPrompt",
"sts:GetCallerIdentity"
],
"Resource": "*"
}]
}No write scopes are needed for discovery. sts:GetCallerIdentity is used by Test Connection.
Then skip to "Configure the connection in Airia" below.
Discovery is all-or-nothing
A sync lists agents, then flows, then reads the details of each one. If AWS denies
bedrock:ListAgents, bedrock:ListFlows, bedrock:GetAgent, or bedrock:GetFlow, the whole
run fails and nothing is added or removed. For example, granting ListAgents without
ListFlows discovers nothing, not just no flows. Grant the required actions together.
bedrock:ListAgentActionGroups and bedrock:GetPrompt are best-effort: if they are denied, the
sync still succeeds, but an agent's tools (action groups) or a flow prompt's model are left
uncaptured. Include them for complete inventory.
Test Connection can pass while a sync would fail. If Test Connection shows a warning that
bedrock:ListAgents or bedrock:ListFlows is missing, discovery syncs will fail. Fix the
policy before saving.
Tier 2: Full integration (secure agents through the Airia Gateway)
When you secure a Bedrock Agent, Airia provisions a custom orchestration Lambda in your account that routes the agent's model requests through the Airia Gateway. This requires two customer-managed IAM policies:
- Permissions Boundary Policy (
AiriaLambdaBoundary): limits what the Lambda execution roles can do and prevents privilege escalation. - Integration Policy (
AiriaBedrockIntegrationPolicy): grants the integration user permission to create and manage the Bedrock and Lambda resources.
Both are created as customer-managed policies (not inline) to avoid the AWS Console's 2048-character inline policy limit.
Architecture:
Bedrock Agent → Custom Lambda Orchestrator → Airia Gateway → AI Model
↓
Parameter Store (API keys)
↓
CloudWatch LogsPrerequisites
- AWS account with Bedrock service access
- IAM permissions to create policies and users
- Your Airia Gateway URL and API key
- AWS CLI (optional; everything below can be done in the console)
Step 1: Prepare the two policy files
Get your 12-digit AWS account ID (console: click your username, top right; CLI:
aws sts get-caller-identity --query Account --output text).
Policy A: AiriaLambdaBoundary (account-agnostic, use as-is):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaBasicExecution",
"Effect": "Allow",
"Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/airia-orchestrator-*:*"
},
{
"Sid": "ParameterStoreReadOnly",
"Effect": "Allow",
"Action": ["ssm:GetParameter", "ssm:GetParameters"],
"Resource": "arn:aws:ssm:*:*:parameter/airia/bedrock/gateway-api-key/*"
},
{
"Sid": "KMSDecryptOnly",
"Effect": "Allow",
"Action": "kms:Decrypt",
"Resource": "arn:aws:kms:*:*:key/*",
"Condition": { "StringLike": { "kms:ViaService": "ssm.*.amazonaws.com" } }
},
{
"Sid": "BedrockAgentRuntimeAccess",
"Effect": "Allow",
"Action": ["bedrock:Retrieve", "bedrock:RetrieveAndGenerate"],
"Resource": "arn:aws:bedrock:*:*:knowledge-base/*"
},
{
"Sid": "BedrockRuntimeAccess",
"Effect": "Allow",
"Action": ["bedrock:InvokeModel"],
"Resource": "arn:aws:bedrock:*::foundation-model/*"
},
{
"Sid": "CloudWatchMetricsAccess",
"Effect": "Allow",
"Action": ["cloudwatch:PutMetricData"],
"Resource": "*",
"Condition": { "StringEquals": { "cloudwatch:namespace": "Airia/BedrockOrchestrator" } }
},
{
"Sid": "DenyDangerousActions",
"Effect": "Deny",
"Action": ["iam:*", "organizations:*", "account:*"],
"Resource": "*"
}
]
}Policy B: AiriaBedrockIntegrationPolicy (replace <ACCOUNT_ID> with your account ID in
every ARN):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BedrockAgentManagement",
"Effect": "Allow",
"Action": ["bedrock:GetAgent", "bedrock:UpdateAgent", "bedrock:ListAgents", "bedrock:UpdateAgentActionGroup"],
"Resource": "arn:aws:bedrock:*:<ACCOUNT_ID>:agent/*"
},
{
"Sid": "LambdaFunctionManagement",
"Effect": "Allow",
"Action": ["lambda:GetFunction", "lambda:CreateFunction", "lambda:UpdateFunctionCode", "lambda:UpdateFunctionConfiguration", "lambda:GetPolicy", "lambda:AddPermission"],
"Resource": "arn:aws:lambda:*:<ACCOUNT_ID>:function:airia-orchestrator-*"
},
{
"Sid": "LambdaLayerAccess",
"Effect": "Allow",
"Action": ["lambda:GetLayerVersion"],
"Resource": "arn:aws:lambda:*:*:layer:AWS-Parameters-and-Secrets-Lambda-Extension:*"
},
{
"Sid": "IAMRoleCreationWithBoundary",
"Effect": "Allow",
"Action": ["iam:CreateRole"],
"Resource": "arn:aws:iam::<ACCOUNT_ID>:role/airia-lambda-*",
"Condition": {
"StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::<ACCOUNT_ID>:policy/AiriaLambdaBoundary" }
}
},
{
"Sid": "IAMRoleManagement",
"Effect": "Allow",
"Action": ["iam:GetRole", "iam:GetPolicy", "iam:AttachRolePolicy", "iam:PutRolePolicy"],
"Resource": [
"arn:aws:iam::<ACCOUNT_ID>:role/airia-lambda-*",
"arn:aws:iam::<ACCOUNT_ID>:policy/AiriaLambdaBoundary"
]
},
{
"Sid": "IAMPassRoleToLambda",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::<ACCOUNT_ID>:role/airia-lambda-*",
"Condition": { "StringEquals": { "iam:PassedToService": "lambda.amazonaws.com" } }
},
{
"Sid": "IAMPassRoleToBedrock",
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"arn:aws:iam::<ACCOUNT_ID>:role/service-role/AmazonBedrockExecutionRoleForAgents_*",
"arn:aws:iam::<ACCOUNT_ID>:role/AmazonBedrockExecutionRoleForAgents_*"
],
"Condition": { "StringEquals": { "iam:PassedToService": "bedrock.amazonaws.com" } }
},
{
"Sid": "GetAWSAccountIdentity",
"Effect": "Allow",
"Action": "sts:GetCallerIdentity",
"Resource": "*"
},
{
"Sid": "ParameterStoreManagement",
"Effect": "Allow",
"Action": ["ssm:PutParameter", "ssm:GetParameter"],
"Resource": "arn:aws:ssm:*:<ACCOUNT_ID>:parameter/airia/bedrock/gateway-api-key/*"
},
{
"Sid": "KMSForParameterStore",
"Effect": "Allow",
"Action": ["kms:Decrypt", "kms:Encrypt", "kms:GenerateDataKey"],
"Resource": "arn:aws:kms:*:<ACCOUNT_ID>:key/*",
"Condition": { "StringLike": { "kms:ViaService": ["ssm.*.amazonaws.com"] } }
}
]
}Security note: the KMS key wildcard is required because AWS-managed SSM keys have different
key IDs per region; the kms:ViaService condition restricts KMS use to Parameter Store only.
Step 2: Create the policies in the AWS Console
- IAM → Policies → Create policy → JSON tab. Paste Policy A. Name it
AiriaLambdaBoundary, description "Permissions boundary for Airia Lambda execution roles to prevent privilege escalation". Create. - Repeat for Policy B. Name it
AiriaBedrockIntegrationPolicy, description "Permissions for managing AWS Bedrock Agents with Airia Gateway integration". Create.
Step 3: Create the integration user and key
- IAM → Users → Create user. Name:
ai-gateway-integration. Console access optional. Skip the permissions step and create the user. - Open the user → Permissions → Add permissions → Attach policies directly → attach
AiriaBedrockIntegrationPolicy. - Discovery also needs the read-only actions from the Tier 1 policy above (
ListFlows,GetFlow, and the others), whichAiriaBedrockIntegrationPolicydoes not include. Attach a Tier 1 policy to this user as well, or use a separate discovery user for the connection. - Open the user → Security credentials → Create access key → use case "Application running outside AWS". Copy both the access key ID and the secret access key (the secret is only shown once).
Step 4: Verify (optional, CLI)
aws configure --profile airia-integration # enter the new key + region
aws sts get-caller-identity --profile airia-integration
aws bedrock-agent list-agents --region us-east-1 --profile airia-integration --max-results 5Expected: STS returns your account, and list-agents returns a list (empty is fine).
What gets created when you secure an agent
| Resource | Name pattern | Purpose |
|---|---|---|
| Lambda function | airia-orchestrator-{agent-name} | Orchestration logic routing requests through the Airia Gateway (Python, 30 s timeout, 256 MB) |
| IAM role | airia-lambda-{agent-id} | Lambda execution role, constrained by the AiriaLambdaBoundary permissions boundary |
| Parameter Store entry | /airia/bedrock/gateway-api-key/{function-name} | SecureString holding the Airia Gateway API key |
| CloudWatch logs | /aws/lambda/airia-orchestrator-{agent-name} | Function logs; custom metrics publish to the Airia/BedrockOrchestrator namespace |
Supported regions
The integration uses the AWS Parameters and Secrets Lambda Extension, available in all standard commercial regions (US, Canada, Europe, Asia Pacific, Middle East, South America, Africa). Bedrock itself is available in fewer regions; check AWS regional availability for Bedrock in your target region.
Configure the connection in Airia
- In Airia, go to Discover → Connect → AWS Bedrock.
- Enter:
| Field | Required | Notes |
|---|---|---|
| AWS Region | Yes | For example us-east-1 |
| AWS Access Key ID | Yes | From the IAM user above |
| AWS Secret Access Key | Yes | Stored encrypted, masked on edit |
| Session Token | No | Only when using temporary STS credentials |
- Click Test Connection, then save. The first discovery scan starts on save.
Multiple environments
Multiple AWS Bedrock connections per Airia tenant are supported: typically one per AWS account and region pair. Name each connection accordingly ("Prod us-east-1", "Sandbox eu-west-1").
Relationship to the AI Gateway provider
AWS Bedrock appears both as a discovery connector (this page) and as an AI Gateway model provider (for routing Bedrock-hosted models). The two are configured separately and credentials are not shared between them, even when they use the same AWS account. Plan to provision credentials for each independently.
Troubleshooting
A failed discovery run is recorded as Failed with the AWS error text. A successful run that finds no changes is not recorded, so an empty sync-runs list can mean the sync succeeded and found 0 agents (check that the connection's region and account are the ones that host your agents).
| Symptom | Cause | Fix |
|---|---|---|
| Sync run Failed with "…is not authorized to perform: bedrock:<Action>…" | The IAM user lacks a required read action; any denied call fails the whole run | Compare the policy with the Tier 1 JSON above |
| Sync run Failed with "The security token included in the request is expired" | Temporary credentials with a session token expired | Update the connection with fresh credentials, or use IAM user access keys |
| No agents discovered and no sync runs listed | Wrong region or account, or the account has no Agents or Flows (Knowledge Bases and plain model use are not discovered) | Confirm the region on the connection matches where your agents live; add one connection per region |
iam:PutRolePolicy permission denied | Integration policy missing the IAMRoleManagement statement | Re-check Policy B against the JSON above |
iam:PermissionsBoundary condition not satisfied | AiriaLambdaBoundary policy does not exist | Create Policy A (Step 2) |
| Lambda cannot assume role right after creation | IAM eventual consistency | Wait 15 to 30 seconds and retry |
| Parameter Store access denied | Lambda role missing SSM permissions or wrong parameter path | Verify the role's inline policy |
| "Security token included in the request is invalid" | Credentials from a different account, or region mismatch | aws sts get-caller-identity with the profile and confirm the account ID |
| Region not supported | Lambda extension layer unavailable in that region | Use a supported region |
Credential hygiene
- Rotate the access key on your normal rotation schedule (90 days is a common baseline).
- Use separate AWS accounts for development and production connections.
- Enable CloudTrail on the account for an audit trail of the integration user's actions.