Arrange {custom} domains for Amazon Bedrock AgentCore Runtime brokers


When deploying AI agents to Amazon Bedrock AgentCore Runtime (at present in preview), clients typically need to use {custom} domains to create knowledgeable and seamless expertise.

By default, AgentCore Runtime brokers use endpoints like https://bedrock-agentcore.{area}.amazonaws.com/runtimes/{EncodedAgentARN}/invocations.

On this submit, we talk about easy methods to remodel these endpoints into user-friendly {custom} domains (like https://agent.yourcompany.com) utilizing Amazon CloudFront as a reverse proxy. The answer combines CloudFront, Amazon Route 53, and AWS Certificate Manager (ACM) to create a safe, scalable {custom} area setup that works seamlessly along with your current brokers.

Advantages of Amazon Bedrock AgentCore Runtime

If you happen to’re constructing AI brokers, you’ve gotten most likely wrestled with internet hosting challenges: managing infrastructure, dealing with authentication, scaling, and sustaining safety. Amazon Bedrock AgentCore Runtime helps handle these issues.

Amazon Bedrock AgentCore Runtime is framework agnostic; you need to use it with LangGraph, CrewAI, Strands Agents, or {custom} brokers you’ve gotten constructed from scratch. It helps prolonged execution instances as much as 8 hours, good for complicated reasoning duties that conventional serverless capabilities can’t deal with. Every person session runs in its personal remoted microVM, offering safety that’s essential for enterprise purposes.

The consumption-based pricing mannequin means you solely pay for what you utilize, not what you provision. And in contrast to different internet hosting options, Amazon Bedrock AgentCore Runtime contains built-in authentication and specialised observability for AI brokers out of the field.

Advantages of {custom} domains

When utilizing Amazon Bedrock AgentCore Runtime with Open Authorization (OAuth) authentication, your purposes make direct HTTPS requests to the service endpoint. Though this works, {custom} domains provide a number of advantages:

  • Customized branding – Consumer-side purposes (internet browsers, cell apps) show your branded area as a substitute of AWS infrastructure particulars in community requests
  • Higher developer expertise – Improvement groups can use memorable, branded endpoints as a substitute of copying and pasting lengthy AWS endpoints throughout code bases and configurations
  • Simplified upkeep – Customized domains make it easy to handle endpoints when deploying a number of brokers or updating configurations throughout environments

Resolution overview

On this resolution, we use CloudFront as a reverse proxy to rework requests out of your {custom} area into Amazon Bedrock AgentCore Runtime API calls. As a substitute of utilizing the default endpoint, your purposes could make requests to a user-friendly URL like https://agent.yourcompany.com/.

The next diagram illustrates the answer structure.

AgentCore-Diagram

The workflow consists of the next steps:

  1. A consumer software authenticates with Amazon Cognito and receives a bearer token.
  2. The consumer makes an HTTPS request to your {custom} area.
  3. Route 53 resolves the DNS request to CloudFront.
  4. CloudFront forwards the authenticated request to the Amazon Bedrock Runtime agent.
  5. The agent processes the request and returns the response by means of the identical path.

You need to use the identical CloudFront distribution to serve each your frontend software and backend agent endpoints, avoiding cross-origin resource sharing (CORS) points as a result of every thing originates from the identical area.

Stipulations

To comply with this walkthrough, you have to have the next in place:

Though Amazon Bedrock AgentCore Runtime might be in different supported AWS Regions, CloudFront requires SSL certificates to be within the us-east-1 Area.

You may select from the next area choices:

  • Use an current area – Add a subdomain like agent.yourcompany.com
  • Register a brand new area – Use Route 53 to register a site should you don’t have one
  • Use the default URL from CloudFront – No area registration or configuration required

Select the third possibility if you wish to take a look at the answer shortly earlier than organising a {custom} area.

Create an agent with inbound authentication

If you have already got an agent deployed with OAuth authentication, you possibly can skip to the subsequent part to arrange the {custom} area. In any other case, comply with these steps to create a brand new agent utilizing Amazon Cognito as your OAuth supplier:

  1. Create a brand new listing on your agent with the next construction:
your_project_directory/
├── agent_example.py # Your predominant agent code
├── necessities.txt # Dependencies on your agent
└── __init__.py # Makes the listing a Python bundle

  1. Create the primary agent code in agent_example.py:
# agent_example.py
from strands import Agent
from bedrock_agentcore.runtime import BedrockAgentCoreApp

agent = Agent()
app = BedrockAgentCoreApp()
@app.entrypoint
def invoke(payload):
    """Course of person enter and return a response"""
    user_message = payload.get("immediate", "Hiya")
    response = agent(user_message)
    return str(response) # response ought to be json serializable
if __name__ == "__main__":
    app.run()

  1. Add dependencies to necessities.txt:
# necessities.txt
strands-agents
bedrock-agentcore

  1. Run the next instructions to create an Amazon Cognito person pool and take a look at person:
# Create Consumer Pool and seize Pool ID
export POOL_ID=$(aws cognito-idp create-user-pool 
  --pool-name "MyUserPool" 
  --policies '{"PasswordPolicy":{"MinimumLength":8}}' 
  --region us-east-1 | jq -r '.UserPool.Id')

# Create App Consumer and seize Consumer ID
export CLIENT_ID=$(aws cognito-idp create-user-pool-client 
  --user-pool-id $POOL_ID 
  --client-name "MyClient" 
  --no-generate-secret 
  --explicit-auth-flows "ALLOW_USER_PASSWORD_AUTH" "ALLOW_REFRESH_TOKEN_AUTH" 
  --region us-east-1 | jq -r '.UserPoolClient.ClientId')

# Create and configure a take a look at person
aws cognito-idp admin-create-user 
  --user-pool-id $POOL_ID 
  --username "testuser" 
  --temporary-password "Temp1234" 
  --region us-east-1 
  --message-action SUPPRESS

aws cognito-idp admin-set-user-password 
  --user-pool-id $POOL_ID 
  --username "testuser" 
  --password "MyPassword123" 
  --region us-east-1 
  --permanent

echo "Pool ID: $POOL_ID"
echo "Discovery URL: https://cognito-idp.us-east-1.amazonaws.com/$POOL_ID/.well-known/openid-configuration"
echo "Consumer ID: $CLIENT_ID"

  1. Deploy the agent utilizing the Amazon Bedrock AgentCore command line interface (CLI) supplied by the starter toolkit:
pip set up bedrock-agentcore-starter-toolkit #set up the starter toolkit

agentcore configure --entrypoint agent_example.py 
--name my_agent 
--execution-role your-execution-role-arn 
--requirements-file necessities.txt 
--authorizer-config "{"customJWTAuthorizer":{"discoveryUrl":"https://cognito-idp.us-east-1.amazonaws.com/$POOL_ID/.well-known/openid-configuration","allowedClients":["$CLIENT_ID"]}}"

agentcore launch

Make word of your agent runtime Amazon Useful resource Title (ARN) after deployment. You’ll need this for the {custom} area configuration.

For extra examples and particulars, see Authenticate and authorize with Inbound Auth and Outbound Auth.

Arrange the {custom} area resolution

Now let’s implement the {custom} area resolution utilizing the AWS CDK. This part exhibits you easy methods to create the CloudFront distribution that proxies your {custom} area requests to Amazon Bedrock AgentCore Runtime endpoints.

  1. Create a brand new listing and initialize an AWS CDK mission:
mkdir agentcore-custom-domain
cd agentcore-custom-domain
cdk init app --language python
supply .venv/bin/activate
pip set up aws-cdk-lib constructs

  1. Encode the agent ARN and put together the CloudFront origin configuration:
# agentcore_custom_domain_stack.py 
import urllib.parse

agent_runtime_arn = "arn:aws:bedrock-agentcore:us-east-1:accountId:runtime/my_agent-xbcDkz4FR9"
encoded_arn = urllib.parse.quote(agent_runtime_arn, secure="") # URL-encode the ARN
area = agent_runtime_arn.cut up(':')[3]  # Extract area from ARN

In case your frontend software runs on a unique area than your agent endpoint, you have to configure CORS headers. That is widespread in case your frontend is hosted on a unique area (for instance, https://app.yourcompany.com calling https://agent.yourcompany.com), or should you’re creating domestically (for instance, http://localhost:3000 calling your manufacturing agent endpoint).

  1. To deal with CORS necessities, create a CloudFront response headers policy:
# agentcore_custom_domain_stack.py 
from aws_cdk.aws_cloudfront import ResponseHeadersPolicy, ResponseHeadersCorsBehavior

# Create CORS response headers coverage
cors_policy = ResponseHeadersPolicy(self, 'CorsPolicy',
    cors_behavior=ResponseHeadersCorsBehavior(
        access_control_allow_origins=['*'], # Or specify your frontend domains
        access_control_allow_headers=[
            'Authorization',
            'Content-Type', 
            'X-Amzn-*',
            'X-Requested-With'
        ],
        access_control_allow_methods=['GET', 'POST', 'OPTIONS'],
        access_control_allow_credentials=False,
        access_control_expose_headers=['*'],
        origin_override=True # Overrides CORS headers from origin
    )
)

  1. Create a CloudFront distribution to behave as a reverse proxy on your agent endpoints:
# agentcore_custom_domain_stack.py
 from aws_cdk.aws_cloudfront import (
    Distribution, BehaviorOptions, CachePolicy, 
    AllowedMethods, ViewerProtocolPolicy,
    OriginProtocolPolicy, OriginRequestPolicy
)
from aws_cdk.aws_cloudfront_origins import HttpOrigin

bedrock_agentcore_hostname = f"bedrock-agentcore.{area}.amazonaws.com"
origin_path = f"/runtimes/{encoded_arn}/invocations"

distribution = Distribution(self, 'Distribution',
    default_behavior=BehaviorOptions(
        origin=HttpOrigin(
            bedrock_agentcore_hostname,
            origin_path=origin_path, 
            protocol_policy=OriginProtocolPolicy.HTTPS_ONLY,
            read_timeout=Period.seconds(120) # Non-compulsory: for responses >30s, modify as wanted
        ),
        viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        cache_policy=CachePolicy.CACHING_DISABLED,  # Important for dynamic APIs
        allowed_methods=AllowedMethods.ALLOW_ALL,
        response_headers_policy=cors_policy,  # Add CORS coverage if created
        origin_request_policy=OriginRequestPolicy.ALL_VIEWER,  # Ahead headers for MCP
    ),
    # Add area configuration if utilizing {custom} domains
    domain_names=[domain_name] if domain_name else None,
    certificates=certificates if domain_name else None,
)

Set cache_policy=CachePolicy.CACHING_DISABLED to ensure your agent responses stay dynamic and aren’t cached by CloudFront.

  1. If you happen to’re utilizing a {custom} area, add an SSL certificates and DNS configuration to your stack:
# agentcore_custom_domain_stack.py 
from aws_cdk.aws_certificatemanager import Certificates, CertificateValidation
from aws_cdk.aws_route53 import HostedZone, ARecord, RecordTarget
from aws_cdk.aws_route53_targets import CloudFrontTarget

# For current domains
hosted_zone = HostedZone.from_lookup(self, 'HostedZone',
    domain_name="yourcompany.com"
)
# SSL certificates with automated DNS validation
certificates = Certificates(self, 'Certificates',
    domain_name="my-agent.yourcompany.com",
    validation=CertificateValidation.from_dns(hosted_zone),
)
# DNS document pointing to CloudFront
ARecord(self, 'AliasRecord',
    zone=hosted_zone,
    record_name="my-agent.yourcompany.com",
    goal=RecordTarget.from_alias(CloudFrontTarget(distribution)),
)

The next code is the whole AWS CDK stack that mixes all of the elements:

# agentcore_custom_domain_stack.py
import urllib.parse
from aws_cdk import Stack, CfnOutput, Period
from aws_cdk.aws_cloudfront import (
    Distribution, BehaviorOptions,
    CachePolicy, AllowedMethods,
    ViewerProtocolPolicy, OriginProtocolPolicy,
    ResponseHeadersPolicy, ResponseHeadersCorsBehavior,
    OriginRequestPolicy
)
from aws_cdk.aws_cloudfront_origins import HttpOrigin
from aws_cdk.aws_certificatemanager import Certificates, CertificateValidation
from aws_cdk.aws_route53 import HostedZone, ARecord, RecordTarget
from aws_cdk.aws_route53_targets import CloudFrontTarget
from constructs import Assemble

class AgentcoreCustomDomainStack(Stack):
    def __init__(self, scope: Assemble, construct_id: str, **kwargs) -> None:
        tremendous().__init__(scope, construct_id, **kwargs)

        # Configuration - Replace these on your setup
        agent_runtime_arn = "arn:aws:bedrock-agentcore:us-east-1:accountId:runtime/my_agent-xbcDkz4FR9"
        area = agent_runtime_arn.cut up(':')[3]  # Extract area from ARN
        domain_name = "agent.yourcompany.com"  # Utilizing your hosted zone
        hosted_zone_id = "Z1234567890ABC"  # Your hosted zone ID
        enable_cors = True  # Set to False if serving frontend and backend from identical area

        # Encode the agent ARN for the origin path
        encoded_arn = urllib.parse.quote(agent_runtime_arn, secure="")
        bedrock_agentcore_hostname = f"bedrock-agentcore.{area}.amazonaws.com"
        origin_path = f"/runtimes/{encoded_arn}/invocations"

        # Create CORS response headers coverage if wanted
        cors_policy = None
        if enable_cors:
            cors_policy = ResponseHeadersPolicy(self, 'CorsPolicy',
                cors_behavior=ResponseHeadersCorsBehavior(
                    access_control_allow_origins=['*'],  # Or specify your frontend domains
                    access_control_allow_headers=[
                        'Authorization',
                        'Content-Type', 
                        'X-Amzn-*',
                        'X-Requested-With'
                    ],
                    access_control_allow_methods=['GET', 'POST', 'OPTIONS'],
                    access_control_expose_headers=['*'],
                    access_control_allow_credentials=False,
                    origin_override=True  # Overrides CORS headers from origin
                )
            )

        # Base distribution configuration
        distribution_props = {
            "default_behavior": BehaviorOptions(
                origin=HttpOrigin(
                    bedrock_agentcore_hostname,
                    origin_path=origin_path,  # Direct path to agent endpoint
                    protocol_policy=OriginProtocolPolicy.HTTPS_ONLY,
                    read_timeout=Period.seconds(120) # Non-compulsory: for responses >30s, modify as wanted
                ),
                viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
                cache_policy=CachePolicy.CACHING_DISABLED,
                allowed_methods=AllowedMethods.ALLOW_ALL,
                response_headers_policy=cors_policy,  # Add CORS coverage if enabled
                origin_request_policy=OriginRequestPolicy.ALL_VIEWER,  # Ahead headers for MCP
            )
        }

        # Non-compulsory: Add {custom} area
        if domain_name:
            # Use from_hosted_zone_attributes for particular zone
            hosted_zone = HostedZone.from_hosted_zone_attributes(self, 'HostedZone',
                                                                 zone_name="yourcompany.com",  # Your root area
                                                                 hosted_zone_id=hosted_zone_id
                                                                 )

            certificates = Certificates(self, 'Certificates',
                                      domain_name=domain_name,
                                      validation=CertificateValidation.from_dns(
                                          hosted_zone),
                                      )

            # Add {custom} area to distribution
            distribution_props["domain_names"] = [domain_name]
            distribution_props["certificate"] = certificates

        distribution = Distribution(self, 'Distribution', **distribution_props)

        # Create DNS document if utilizing {custom} area
        if domain_name:
            ARecord(self, 'AliasRecord',
                    zone=hosted_zone,
                    record_name=domain_name,
                    goal=RecordTarget.from_alias(
                        CloudFrontTarget(distribution)),
                    )

        # Outputs
        if domain_name:
            domain_url = f"https://{domain_name}/"
            CfnOutput(self, "AgentEndpoint",
                      worth=domain_url,
                      description="Your {custom} area endpoint"
                      )

        CfnOutput(self, "CloudFrontDistribution",
                  worth=f"https://{distribution.distribution_domain_name}/",
                  description="CloudFront default area (works with out {custom} area)"
                  )

  1. Configure the AWS CDK app entry level:
# app.py
#!/usr/bin/env python3
import aws_cdk as cdk
from agentcore_custom_domain.agentcore_custom_domain_stack import AgentCoreCustomDomainStack

app = cdk.App()
AgentcoreCustomDomainStack(app, "AgentCoreCustomDomainStack",
    # CloudFront requires certificates in us-east-1
    env=cdk.Atmosphere(area='us-east-1'),
)
app.synth()

Deploy your {custom} area

Now you possibly can deploy the answer and confirm it really works with each {custom} and default domains. Full the next steps:

  1. Replace the next values in agentcore_custom_domain_stack.py:
    • Your Amazon Bedrock AgentCore Runtime ARN
    • Your area identify (if utilizing a {custom} area)
    • Your hosted zone ID (if utilizing a {custom} area)
  2. Deploy utilizing the AWS CDK:

Check your endpoint

After you deploy the {custom} area, you possibly can take a look at your endpoints utilizing both the {custom} area or the CloudFront default area.First, get a JWT token from Amazon Cognito:

export TOKEN=$(aws cognito-idp initiate-auth 
  --client-id "your-client-id" 
  --auth-flow USER_PASSWORD_AUTH 
  --auth-parameters USERNAME='testuser',PASSWORD='MyPassword123' 
  --region us-east-1 | jq -r '.AuthenticationResult.AccessToken')

Use the next code to check along with your {custom} area:

curl -X POST "https://my-agent.yourcompany.com/" 
  -H "Authorization: Bearer $TOKEN" 
  -H "Content material-Sort: software/json" 
  -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: session-12345678901234567890123456789012345" 
  -d '{"immediate": "Hiya, how will you assist me at present?"}'

Alternatively, use the next code to check with the CloudFront default area:

curl -X POST "https://d1234567890123.cloudfront.web/" 
  -H "Authorization: Bearer $TOKEN" 
  -H "Content material-Sort: software/json" 
  -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: session-12345678901234567890123456789012345" 
  -d '{"immediate": "Hiya, how will you assist me at present?"}'

If every thing works appropriately, you’ll obtain a response out of your agent by means of both endpoint. You’ve efficiently created a {custom} area on your Amazon Bedrock AgentCore Runtime agent!

Concerns

As you implement this resolution in manufacturing, the next are some necessary concerns:

  • Value implications – CloudFront provides prices for information switch and requests. Assessment Amazon CloudFront pricing to know the influence on your utilization patterns.
  • Safety enhancements – Think about implementing the next safety measures:
    • AWS WAF guidelines to assist defend towards widespread internet exploits.
    • Fee limiting to assist forestall abuse.
    • Geo-restrictions in case your agent ought to solely be accessible from particular Areas.
  • Monitoring – Allow CloudFront access logs and arrange Amazon CloudWatch alarms to watch error charges, latency, and request quantity.

Clear up

To keep away from ongoing prices, delete the sources once you not want them:

You would possibly must manually delete the Route 53 hosted zones and ACM certificates from their respective service consoles.

Conclusion

On this submit, we confirmed you easy methods to create {custom} domains on your Amazon Bedrock AgentCore Runtime agent endpoints utilizing CloudFront as a reverse proxy. This resolution gives a number of key advantages: simplified integration for improvement groups, {custom} domains that align along with your group, cleaner infrastructure abstraction, and easy upkeep when endpoints want updates. Through the use of CloudFront as a reverse proxy, you too can serve each your frontend software and backend agent endpoints from the identical area, avoiding widespread CORS challenges.

We encourage you to discover this resolution additional by adapting it to your particular wants. You would possibly need to improve it with extra safety features, arrange monitoring, or combine it along with your current infrastructure.

To be taught extra about constructing and deploying AI brokers, see the Amazon Bedrock AgentCore Developer Guide. For superior configurations and finest practices with CloudFront, discuss with the Amazon CloudFront documentation. Yow will discover detailed details about SSL certificates within the AWS Certificate Manager documentation, and area administration within the Amazon Route 53 documentation.

Amazon Bedrock AgentCore is at present in preview and topic to vary. Normal AWS pricing applies to extra companies used, similar to CloudFront, Route 53, and Certificates Supervisor.


In regards to the authors

Rahmat Fedayizada is a Senior Options Architect with the AWS Power and Utilities crew. He works with power corporations to design and implement scalable, safe, and extremely obtainable architectures. Rahmat is keen about translating complicated technical necessities into sensible options that drive enterprise worth.

Paras Bhuva is a Senior Supervisor of Options Structure at AWS, the place he leads a crew of resolution architects serving to power clients innovate and speed up their transformation. Having began as a Resolution Architect in 2012, Paras is keen about architecting scalable options and constructing organizations centered on software modernization and AI initiatives.

Leave a Reply

Your email address will not be published. Required fields are marked *