Skip to content

Connect your AWS Bedrock environment to Capsule Security for complete visibility into your AI agents, flows, knowledge bases, guardrails, and runtime activity.

Overview

This integration uses an IAM role to sync into your Bedrock resources and capture runtime telemetry:

CategoryWhat Gets Captured
AgentsBedrock Agents and AgentCore agents with configuration and metadata
Action GroupsLambda functions and OpenAPI schemas attached to agents
Knowledge BasesVector stores, data sources, and chunking configurations
GuardrailsContent filters, denied topics, and PII handling policies
FlowsPrompt flows with node configurations and connections
Runtime ActivityAgent invocations, traces, tool calls, and session history

To block tool calls, model requests, and agent invocations at runtime, add AgentCore Gateway Prevention after the integration is connected.

Prerequisites

Before you begin, ensure you have:

  • An AWS account with Bedrock Agents or AgentCore deployed
  • IAM permissions to deploy CloudFormation stacks (or AdministratorAccess)
  • CloudTrail enabled in your account (for runtime activity capture)
  • Access to the Capsule Security portal

Step 1: Launch the CloudFormation Stack

Deploy the Capsule IAM role using the provided CloudFormation template.

Steps

  1. Log in to the Capsule Security portal
  2. Click Integrations in the left sidebar
  3. Find the AWS Bedrock card and click Set up Integration
  4. Click Open CloudFormation
Capsule Portal integration card of AWS Bedrock installation
  1. You'll be redirected to the AWS CloudFormation console
  2. Review the stack details:
    • Stack name: CapsuleSecurityBedrockIntegration (or customize)
    • Capabilities: Acknowledge IAM resource creation
  3. Click Create stack

What gets deployed

ResourcePurpose
IAM RoleCross-account role assumed by Capsule for read-only access
IAM PolicyPermissions scoped to Bedrock, CloudTrail, and CloudWatch
Trust PolicyRestricts assumption to Capsule's AWS account with external ID

Step 2: Copy the Role ARN

Once the stack completes, retrieve the IAM role ARN from the Outputs tab.

Steps

  1. Wait for the stack status to show CREATE_COMPLETE
  2. Click the Outputs tab
  3. Copy the value for RoleArn
CloudFormation post install ARN selection location

Step 3: Complete the Integration in Capsule

Provide the Role ARN to Capsule to establish the connection.

Steps

  1. Return to the Capsule Security portal
  2. Paste the Role ARN into the input field
  3. Click Save
  4. Capsule validates the role and its ability to communite with your AWS Account

After setup

  • First sync may take several minutes
  • View synced agents in Inventory → Agents
  • View runtime activity in Observability

What Gets Captured

Bedrock Agents

Entity TypeCategoryDescription
AgentsModel AgentAgent configuration, foundation model, instructions
Agent AliasesVersionDeployed versions and routing configuration
Action GroupsToolLambda functions and API schemas
Knowledge BasesData SourceVector stores with embedding models and data sources
GuardrailsGuardrailContent filters, word blocklists, PII policies
FlowsFlowPrompt flow definitions with node graphs
PromptsPromptManaged prompts with versions

Bedrock AgentCore

Entity TypeCategoryDescription
AgentCore RuntimesModel AgentAgent runtime configurations
ToolsToolRegistered tools and function definitions
MemoryMemorySession and long-term memory configurations
IdentityIdentityWorkload identity configurations

Runtime Activity

When CloudTrail and model invocation logging are enabled:

  • Agent invocations - Input prompts and final responses
  • Tool invocations - Action group calls with inputs and outputs
  • Session history - Multi-turn conversation threads

Enabling Runtime Observability

For full runtime visibility, ensure model invocation logging is enabled.

Steps

  1. Open the Amazon Bedrock console
  2. Navigate to Settings → Model invocation logging
  3. Enable logging and configure your destination (S3 or CloudWatch)
  4. For AgentCore, ensure OpenTelemetry export is configured

Updating the CloudFormation Stack

To update the CloudFormation Stack, following these steps:

  1. Head over to CloudFormation / Stacks in your AWS Account
  2. Select our integration stack (named CapsuleSecurityBedrockIntegration by default)
  3. Click Update stack → Create a change set
  4. Select Standard change set → Replace existing template
  5. Provide the CloudFormation Template URL (default: https://capsule-security-us-east-1-public-demo.s3.us-east-1.amazonaws.com/cf-capsule-security-bedrock-integration.yaml)
  6. Click upcoming Nexts, review the terms and agree to them
  7. This will create a ChangeSet, review the changes and click Execute change set

AgentCore Gateway Prevention

Block tool calls, model requests, and agent invocations that violate your prevention policies before they reach their target. An AgentCore gateway fronts MCP tools, model providers (inference targets), and agents or HTTP services (AgentCore Runtime and passthrough targets). A second CloudFormation stack registers a Capsule interceptor Lambda on the gateway. Before the gateway forwards a request, the interceptor asks Capsule for a decision:

Agent ──► AgentCore gateway ──► Capsule interceptor (Lambda)
  MCP tools/call                    │
  model request (/inference)        │ tool call, prompt, or agent input, plus the caller
  agent invocation (/<target>)      ▼
                                Capsule ── allow ──► gateway forwards the request to the target
                                        └─ deny  ──► gateway answers the caller without calling the target
  • Only a Capsule deny blocks. If Capsule is unreachable, slow, or answers with an error, the request goes through as if the stack were not installed
  • Capsule identifies the calling AgentCore Runtime by its execution role (gateways with AWS_IAM inbound auth) or by the caller token's sub and client ID (gateways with CUSTOM_JWT inbound auth). Requests from a runtime Capsule has not discovered yet go through unevaluated
  • Bedrock Agents (non-AgentCore) and model or agent calls that never pass through an AgentCore gateway are not covered. See Routing model and agent traffic through the gateway

What Capsule evaluates

Target typeEvaluated before the target is calledPasses through untouched
MCP targets (Lambda, OpenAPI, Smithy, MCP server)tools/call: tool name and argumentsinitialize, tools/list, other MCP methods
Inference targetsThe prompt in /inference/v1/chat/completions, /inference/v1/responses, /inference/v1/messages, /inference/model/<model>/invoke, and /inference/model/<model>/invoke-with-response-stream requests, streaming or notGET /inference/v1/models
AgentCore Runtime targetsThe payload of POST /<target>/invocationsOther requests
Passthrough targets (MCP, A2A, INFERENCE)MCP tools/call, A2A message/send and message/stream, and inference requests in the formats aboveOther requests
Passthrough targets (CUSTOM)NothingEvery request

Capsule checks requests only. Tool results, model output, and agent responses are not evaluated, so response streaming works as it does without the stack.

Deploy one stack per gateway, in the gateway's region. A stack stays bound to the gateway it was created for. AgentCore Runtime and passthrough targets can only be added to gateways created without the MCP protocol type, so they usually sit on a different gateway from your MCP targets and need a stack of their own.

What gets deployed

ResourcePurpose
Secrets Manager secretHolds the Capsule token. The token never appears in Lambda configuration or stack events
Interceptor Lambdacapsule-agentcore-interceptor-<suffix>. Called by the gateway on every request; sends the requests above to Capsule
Interceptor IAM roleWrites its own logs and reads the token secret, nothing else
Lambda permissionLets the gateway's service role invoke the interceptor
Registration Lambdacapsule-agentcore-register-<suffix>. Runs on stack create, update, and delete to add or remove the interceptor on the gateway
Registration IAM roleGetGateway and UpdateGateway on this gateway only, and iam:PassRole on the gateway's existing service role

<suffix> is the first 8 characters of the stack ID, so stacks for several gateways coexist in one account. The registration role needs iam:PassRole because UpdateGateway replaces the whole gateway definition; the stack passes back the role the gateway already has and never changes it.

Before you start

  • Connect the AWS account with the integration stack above, and wait until the AgentCore Runtimes that call the gateway appear in Capsule. The two stacks can be deployed in either order, but enforcement starts once the runtime is in Capsule
  • Create at least one policy in Prevention mode. Without one, every request is allowed
  • Note the gateway's ID (for example acme-tools-abcdef1234, not the ARN), name, and service role ARN from AgentCore console → Gateways → your gateway
  • Confirm the gateway has no other REQUEST interceptor. AWS allows one per gateway, and the stack never replaces an existing one
  • Make sure the gateway's service role allows lambda:InvokeFunction on the interceptor (see below)
  • Route the model and agent traffic you want covered through the gateway (see below)

Routing model and agent traffic through the gateway

Capsule sees only requests that reach the gateway. Point model clients at the gateway's /inference path:

ClientSetting
OpenAI SDKbase_url="https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/inference/v1"
Anthropic SDKbase_url="https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/inference"
AWS SDK bedrock-runtime (InvokeModel)AWS_ENDPOINT_URL_BEDROCK_RUNTIME=https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/inference

From the Bedrock Runtime API, inference targets serve InvokeModel and InvokeModelWithResponseStream. Agents that call Converse or ConverseStream need to switch to one of the clients above. For common agent frameworks:

FrameworkModel classThrough the gateway
Strands AgentsBedrockModel (default)Not supported, it calls ConverseStream. Use AnthropicModel or OpenAIModel
Strands AgentsAnthropicModel, OpenAIModelSet base_url in client_args
LangChain / LangGraphChatBedrockConverseNot supported, it calls Converse. Use ChatBedrock or ChatAnthropic
LangChain / LangGraphChatBedrockSet endpoint_url
LangChain / LangGraphChatAnthropic, ChatOpenAISet base_url
LiteLLM, CrewAIOpenAI or Anthropic providerSet base_url (CrewAI passes it to LiteLLM)
OpenAI Agents SDKOpenAIResponsesModel (default)Set base_url. Needs a target that serves the OpenAI Responses API

Claude models on Bedrock stay reachable from Anthropic and OpenAI clients: the gateway translates those requests to InvokeModel for a Bedrock Runtime target. On a gateway with CUSTOM_JWT inbound auth, pass the caller's token as the SDK's API key. On a gateway with AWS_IAM inbound auth, requests must be SigV4-signed for the bedrock-agentcore service, so add a signing hook to the OpenAI or Anthropic SDK's HTTP client.

Invoke agents behind AgentCore Runtime targets at https://<gateway-id>.gateway.bedrock-agentcore.<region>.amazonaws.com/<target-name>/invocations, and passthrough targets at /<target-name>/<path> on the same host. Callers of an AWS_IAM gateway need bedrock-agentcore:InvokeGateway on it.

To keep agents from bypassing the gateway, let inference targets hold the provider credentials (GATEWAY_IAM_ROLE for Bedrock, an API key in the AgentCore token vault for OpenAI and Anthropic) and remove direct model access from the agents' roles. For AgentCore Runtime targets, restrict the runtime to gateway traffic.

Gateway service role

The gateway invokes the interceptor with its own service role. The stack grants the Lambda side, but cannot edit your role. If the role does not already allow it, add:

{
  "Effect": "Allow",
  "Action": "lambda:InvokeFunction",
  "Resource": "arn:aws:lambda:us-east-1:123456789012:function:capsule-agentcore-interceptor-*"
}

Replace us-east-1 with the gateway's region and 123456789012 with your account ID. The prefix is needed only because the function name is not known before the stack exists. After CREATE_COMPLETE, replace it with the exact InterceptorFunctionArn stack output.

Deployer permissions

The IAM user or role deploying the stack needs:

cloudformation:CreateStack, cloudformation:UpdateStack, cloudformation:DeleteStack, cloudformation:DescribeStacks,
cloudformation:CreateChangeSet, cloudformation:DescribeChangeSet, cloudformation:ExecuteChangeSet,
iam:CreateRole, iam:GetRole, iam:PutRolePolicy, iam:DeleteRolePolicy, iam:DeleteRole, iam:PassRole,
lambda:CreateFunction, lambda:UpdateFunctionConfiguration, lambda:UpdateFunctionCode, lambda:DeleteFunction,
lambda:AddPermission, lambda:RemovePermission, lambda:InvokeFunction, lambda:TagResource, lambda:GetFunction,
secretsmanager:CreateSecret, secretsmanager:UpdateSecret, secretsmanager:DeleteSecret, secretsmanager:TagResource
  1. In Capsule, open Integrations, select your AWS Bedrock integration, and find AgentCore gateway prevention. It lists the gateways Capsule reads from your AWS account. The list can be up to five minutes old
  2. Click Set up on the gateway
  3. Click Create token and copy the token. Capsule does not store it and shows it only once. One token serves every gateway in the same AWS account and region. Treat it as a secret: never put it in a URL, a ticket, or shell history
  4. Click Open CloudFormation. The quick-create page opens in the gateway's region with GatewayIdentifier, GatewayName, GatewayRoleArn, and CapsuleEndpoint filled in. The token is never part of the link

The dialog shows the endpoint the link fills in. Check that it matches your Capsule portal, and use it for the CLI:

Capsule portal URLEndpoint
https://portal.us-east1.capsulesecurity.iohttps://agentsecurity.us-east1.capsulesecurity.io/v1/aws-bedrock-agentcore/hooks/events/pre
https://portal.us-west4.capsulesecurity.iohttps://agentsecurity.us-west4.capsulesecurity.io/v1/aws-bedrock-agentcore/hooks/events/pre
https://portal.eu-west4.capsulesecurity.iohttps://agentsecurity.eu-west4.capsulesecurity.io/v1/aws-bedrock-agentcore/hooks/events/pre

The interceptor sends the token and every evaluated request (tool arguments, prompts, agent input) to this URL, so the template accepts only Capsule-operated hosts.

Step 2: Deploy the stack

The template is published at:

https://capsule-security-us-east-1-public-demo.s3.us-east-1.amazonaws.com/cf-capsule-bedrock-prevention/versions/latest.yaml

Option A: AWS console

The Open CloudFormation link from Step 1 opens a quick-create page with every parameter except CapsuleToken filled in. Paste the token, check I acknowledge that AWS CloudFormation might create IAM resources, and click Create stack. Without the link:

  1. Open CloudFormation in the gateway's region
  2. Click Create stack → With new resources (standard)
  3. Select Amazon S3 URL, paste the template URL above, and click Next
  4. Name the stack, for example CapsuleAgentCorePrevention-abcdef1234 (the last 10 characters of the gateway ID)
  5. Fill in the parameters (see the table below)
  6. Click Next through the remaining pages, check I acknowledge that AWS CloudFormation might create IAM resources, and click Submit

Option B: AWS CLI

Download latest.yaml from the URL above, then:

aws cloudformation deploy \
  --stack-name CapsuleAgentCorePrevention-abcdef1234 \
  --template-file latest.yaml \
  --capabilities CAPABILITY_IAM \
  --region us-east-1 \
  --parameter-overrides \
    GatewayIdentifier=acme-tools-abcdef1234 \
    GatewayName=acme-tools \
    GatewayRoleArn=arn:aws:iam::123456789012:role/AcmeAgentCoreGatewayRole \
    CapsuleEndpoint=https://agentsecurity.us-east1.capsulesecurity.io/v1/aws-bedrock-agentcore/hooks/events/pre \
    CapsuleToken="$CAPSULE_TOKEN"

Pass the token from an environment variable or a secrets tool.

Parameters

ParameterValueNotes
GatewayIdentifierGateway ID, e.g. acme-tools-abcdef1234Not the ARN. Fixed for the life of the stack; create another stack for another gateway
GatewayNameGateway name, e.g. acme-toolsCapsule policies match it as the MCP server name. The stack fails if it does not match the gateway
GatewayRoleArnThe gateway's service role ARNAgentCore console → Gateways → your gateway → Service role
CapsuleEndpointEndpoint from Step 1Only agentsecurity.<region>.capsulesecurity.io hosts are accepted
CapsuleTokenToken from Step 1Stored in Secrets Manager, never echoed

Stack creation takes 1-3 minutes, most of it waiting for the gateway to return to READY after the interceptor is attached. Wait for CREATE_COMPLETE.

If the stack fails because the gateway already has a REQUEST interceptor, nothing was changed. Delete the failed stack, remove the other interceptor from the gateway or pick another gateway, and deploy again. If it fails with GatewayName does not match the gateway's name, delete the failed stack and deploy again with the name shown in the message.

Step 3: Verify

  1. In Capsule, click Verify on the gateway. Capsule reads the gateway from AWS through the integration's role and shows its state:
StateMeaning
InstalledThe Capsule interceptor is on the gateway and receives request headers
Needs updateThe Capsule interceptor is on the gateway without passRequestHeaders, so Capsule cannot identify the calling runtime. Update the stack from the latest template
ConflictAnother REQUEST interceptor is on the gateway. The dialog shows its ARN
Not installedNo Capsule interceptor on the gateway. Check that the stack reached CREATE_COMPLETE

The gateway list can be up to five minutes old. Verify reads the gateway's current state from AWS.

  1. Send a tool call, model request, or agent invocation through the gateway. The log group /aws/lambda/capsule-agentcore-interceptor-<suffix> shows one invocation per request, and the request appears in Capsule Observability under the runtime that made it.

What the caller sees on a deny

The target is not called. On MCP targets and MCP passthrough targets, the gateway returns the deny to the agent as a normal MCP tool result with isError: true, and the agent can act on the reason like any other tool error:

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "isError": true,
    "content": [
      {
        "type": "text",
        "text": "Capsule Policy Enforcement -\nblock-acme-exfiltration - Sensitive data sent to an external tool"
      }
    ]
  }
}

On inference, AgentCore Runtime, and A2A targets, the gateway returns 403 with the same reason in the caller's API error format. Model SDKs raise their usual permission error (PermissionDeniedError in the OpenAI and Anthropic SDKs, AccessDeniedException in the AWS SDK) and do not retry it. A streaming request gets the error before any event is sent. For example, an Anthropic SDK client receives:

{
  "type": "error",
  "error": {
    "type": "permission_error",
    "message": "Capsule Policy Enforcement -\nblock-acme-exfiltration - Sensitive data sent to an external model"
  }
}

Blocked calls in the agent's conversation

Capsule shows a blocked request in the same session as the agent's conversation when the calling runtime has AgentCore observability (ADOT) enabled and CloudWatch Transaction Search is on in the account. The runtime then carries its session ID on gateway calls, as long as the agent serves invocations through an ADOT-instrumented server (the AgentCore SDK app, Starlette, or FastAPI) and calls the gateway through an MCP client or httpx (which the OpenAI and Anthropic Python SDKs use) while handling the invocation. Calls made with requests or urllib3 need opentelemetry.propagate.inject(headers), because ADOT leaves those libraries uninstrumented for agents.

Without this, prevention works the same and the blocked request appears in a session of its own.

Latency and failure behavior

  • Every evaluated request adds one HTTPS round trip from the gateway's region to Capsule plus Capsule's evaluation time, typically a few seconds. A Lambda cold start adds a few hundred milliseconds. For streaming model requests this delays the first token, not the stream
  • The interceptor waits at most 25 seconds for Capsule, then lets the request through. Set your MCP, model, and agent client timeouts above 25 seconds so a slow evaluation passes the request through instead of timing out the caller
  • The token is cached in the Lambda for 5 minutes. A 401 or 403 from Capsule drops the cached token so the next call re-reads the secret
  • The interceptor lets the request through instead of failing when Capsule gives no usable answer, so a slow or unreachable Capsule never causes a gateway retry. AWS can still retry an interceptor invocation, and Capsule evaluates every invocation it receives, so a retried request can be evaluated more than once

Updating to a new template version

Capsule publishes new versions at the same latest.yaml URL. Updating is safe while agents are running: the interceptor keeps its function ARN, and new requests run the new code as soon as the update applies. Every update also re-attaches the interceptor if someone removed it from the gateway.

Stacks on template version 1.0 evaluate MCP tool calls only. Update to 1.1 or later to evaluate inference, AgentCore Runtime, and passthrough targets.

Console: CloudFormation → your stack → Update stack → Replace existing template, set Amazon S3 URL to the latest.yaml URL, keep every parameter as it is (CapsuleToken shows as Use existing value), check the IAM acknowledgement, and submit.

CLI:

aws cloudformation update-stack \
  --stack-name CapsuleAgentCorePrevention-abcdef1234 \
  --template-url https://capsule-security-us-east-1-public-demo.s3.us-east-1.amazonaws.com/cf-capsule-bedrock-prevention/versions/latest.yaml \
  --capabilities CAPABILITY_IAM \
  --region us-east-1 \
  --parameters \
    ParameterKey=GatewayIdentifier,UsePreviousValue=true \
    ParameterKey=GatewayName,UsePreviousValue=true \
    ParameterKey=GatewayRoleArn,UsePreviousValue=true \
    ParameterKey=CapsuleEndpoint,UsePreviousValue=true \
    ParameterKey=CapsuleToken,UsePreviousValue=true

The TemplateVersion stack output shows the version you run.

Rotating the token

In Capsule, click Verify on the gateway, then Create token under Rotate the token. Update the stack with the new CapsuleToken value and every other parameter unchanged (console: Update stack → Use current template). The interceptor picks up the new value within 5 minutes. Earlier tokens stay valid, so the stack keeps working until you update it. If a token leaks, contact Capsule support.

Removing prevention

Delete the stack. The registration Lambda removes the Capsule interceptor from the gateway before the Lambda functions are deleted, so the gateway keeps working without it.

aws cloudformation delete-stack --stack-name CapsuleAgentCorePrevention-abcdef1234 --region us-east-1

The gateway, its targets, its service role, and any RESPONSE interceptor are not affected. The token secret stays recoverable in Secrets Manager for 30 days.

If deletion fails with Could not remove the Capsule REQUEST interceptor, remove it in AgentCore console → Gateways → your gateway → Interceptors, then delete the stack again. Do not delete the stack with resources retained while the entry is still on the gateway: the gateway would call a Lambda that no longer exists and every tool call would fail. Do not clear it with a bare aws bedrock-agentcore-control update-gateway either. UpdateGateway replaces the whole gateway definition, so every optional setting you do not re-supply (KMS key, WAF, policy engine, authorizer configuration, description) is cleared.

Troubleshooting prevention

SymptomWhere to lookLikely cause
Stack fails at CapsuleGatewayInterceptorRegistrationCloudFormation Events, log group /aws/lambda/capsule-agentcore-register-<suffix>Wrong GatewayIdentifier or GatewayName, GatewayRoleArn does not match the gateway's role, another REQUEST interceptor on the gateway, or the gateway was not READY
Stack update fails with GatewayIdentifier cannot be changedCloudFormation EventsThe update pointed the stack at another gateway. Nothing changed; create a separate stack for the other gateway
Every request through the gateway fails after deploymentGateway status; interceptor log group is emptyThe gateway's service role does not allow lambda:InvokeFunction (see Gateway service role)
Requests go through unevaluatedLog group /aws/lambda/capsule-agentcore-interceptor-<suffix>, capsule unreachable linescapsule 401: wrong, expired, or rotated token, or an endpoint from another Capsule region. Abort: Capsule did not answer within 25 seconds. fetch failed: the endpoint is not reachable from AWS
Requests are never blocked, and nothing is loggedCapsule Inventory → AgentsThe calling runtime is not in Capsule yet, or no policy is in Prevention mode

The interceptor logs one line when it gets no usable answer from Capsule and nothing otherwise. It never logs the caller's Authorization header or request bodies. When contacting support, include the stack name, region, gateway ID, and the x-correlation-id from the interceptor log line. Never send the token.

Troubleshooting

Stack creation failed

  • Check the Events tab for specific error messages
  • Verify you have permissions to create IAM roles
  • Ensure the stack name doesn't already exist

Role validation failed in Capsule

  • Confirm the stack status is CREATE_COMPLETE
  • Verify you copied the full ARN from the Outputs tab
  • Check that the role or its permission hasn't been modified or deleted

No agents appearing

  • Verify Bedrock agents exist in the connected AWS account
  • Check the agent regions match your Capsule environment
  • Allow several minutes for the initial sync to complete

No runtime activity appearing

  • Confirm CloudTrail is enabled in your account
  • Verify model invocation logging is enabled in Bedrock settings
  • Check that agents have been invoked since the integration was connected

Supported Regions

The integration supports all AWS regions where Bedrock is available. Each Capsule environment syncs from a specific AWS region based on your deployment.

Support

For help with this integration, contact support.

For AWS Bedrock issues: