Exclusive Content:

Haiper steps out of stealth mode, secures $13.8 million seed funding for video-generative AI

Haiper Emerges from Stealth Mode with $13.8 Million Seed...

Running Your ML Notebook on Databricks: A Step-by-Step Guide

A Step-by-Step Guide to Hosting Machine Learning Notebooks in...

“Revealing Weak Infosec Practices that Open the Door for Cyber Criminals in Your Organization” • The Register

Warning: Stolen ChatGPT Credentials a Hot Commodity on the...

Configuring Custom Domain Names for Amazon Bedrock AgentCore Runtime Agents

Creating Custom Domain Names for Amazon Bedrock AgentCore Runtime

Introduction

When deploying AI agents to Amazon Bedrock AgentCore Runtime (currently in preview), customers often want to use custom domain names to create a professional and seamless experience.

Benefits of Amazon Bedrock AgentCore Runtime

If you’re building AI agents, you have probably wrestled with hosting challenges: managing infrastructure, handling authentication, scaling, and maintaining security.

Benefits of Custom Domains

When using Amazon Bedrock AgentCore Runtime with Open Authorization (OAuth) authentication, custom domains offer several advantages.

Solution Overview

In this solution, we use CloudFront as a reverse proxy to transform requests from your custom domain into Amazon Bedrock AgentCore Runtime API calls.

Prerequisites

To follow this walkthrough, you must have the following in place.

Create an Agent with Inbound Authentication

If you already have an agent deployed with OAuth authentication, you can skip to the next section to set up the custom domain.

Set Up the Custom Domain Solution

Now let’s implement the custom domain solution using the AWS CDK.

Deploy Your Custom Domain

Now you can deploy the solution and verify it works with both custom and default domains.

Test Your Endpoint

After you deploy the custom domain, you can test your endpoints using either the custom domain or the CloudFront default domain.

Considerations

As you implement this solution in production, there are some important considerations to keep in mind.

Clean Up

To avoid ongoing costs, delete the resources when you no longer need them.

Conclusion

In this post, we showed you how to create custom domain names for your Amazon Bedrock AgentCore Runtime agent endpoints using CloudFront as a reverse proxy.

About the Authors

Rahmat Fedayizada and Paras Bhuva share their expertise in solutions architecture and AI initiatives.

Creating Custom Domains for Amazon Bedrock AgentCore Runtime with CloudFront

When deploying AI agents to the Amazon Bedrock AgentCore Runtime (currently in preview), it’s often important to present a professional and user-friendly interface. By default, AgentCore Runtime agents utilize endpoints that look like this: https://bedrock-agentcore.{region}.amazonaws.com/runtimes/{EncodedAgentARN}/invocations. To enhance the user experience, we aim to transform these endpoints into custom domains, such as https://agent.yourcompany.com.

In this post, we will explore how to achieve this using Amazon CloudFront as a reverse proxy, alongside Amazon Route 53 and AWS Certificate Manager (ACM). This potent combination offers a secure and scalable solution that seamlessly integrates into your existing agent architecture.

Benefits of Amazon Bedrock AgentCore Runtime

If you’re venturing into the world of AI agents, you’re likely aware of the various hosting challenges, such as:

  • Infrastructure management
  • Authentication handling
  • Scaling solutions
  • Security maintenance

Amazon Bedrock AgentCore Runtime simplifies these concerns significantly:

  • Framework Agnostic: Compatible with LangGraph, CrewAI, Strands Agents, or any custom-built agents.
  • Extended Execution Times: Supports up to 8 hours for complex reasoning tasks that traditional serverless functions may struggle with.
  • Isolated MicroVMs: Ensures each user session runs in its own microVM for enhanced security, vital for enterprise applications.
  • Consumption-based Pricing: Pay for what you use instead of provisioning excess resources.
  • Built-in Authentication & Observability: Integrated features streamline the process of developing AI agents.

Benefits of Custom Domains

Utilizing custom domains with Amazon Bedrock AgentCore Runtime offers several advantages beyond basic functionality:

  • Custom Branding: Brand recognition is essential. Client-side applications can display your unique domain instead of AWS infrastructure details.
  • Better Developer Experience: Simplifies endpoint usage by letting developers work with memorable, branded URLs instead of lengthy AWS endpoints.
  • Simplified Maintenance: Manage numerous agents and configurations with ease, especially when deploying across different environments.

Solution Overview

In our proposed solution, we leverage CloudFront as a reverse proxy. This setup transforms requests from your custom domain into Amazon Bedrock AgentCore Runtime API calls. Rather than using the default endpoint, your applications can interact with user-friendly URLs, like https://agent.yourcompany.com/.

Here’s the workflow:

  1. A client application authenticates through Amazon Cognito and obtains a bearer token.
  2. The client sends an HTTPS request to your custom domain.
  3. Route 53 resolves the DNS query to CloudFront.
  4. CloudFront forwards the authenticated request to the Amazon Bedrock Runtime agent.
  5. The agent processes the request and returns the response through the same route.

This architecture allows the same CloudFront distribution to serve both your frontend application and backend agent endpoints, minimizing cross-origin resource sharing (CORS) issues.

Prerequisites

Before diving into implementation, ensure you have the following components:

  • Amazon Bedrock AgentCore Runtime set up in a supported AWS Region (note that CloudFront requires SSL certificates to be in the us-east-1 Region).
  • Domain Options: Choose between an existing domain (like agent.yourcompany.com), registering a new domain through Route 53, or using a default URL from CloudFront for quick testing.

Create an Agent with Inbound Authentication

To proceed with setting up your agent with OAuth authentication using Amazon Cognito, follow these steps:

  1. Directory Structure:

    your_project_directory/
    ├── agent_example.py  # Main agent code
    ├── requirements.txt  # Dependencies
    └── __init__.py       # Python package marker
  2. Agent Code in agent_example.py:

    from strands import Agent
    from bedrock_agentcore.runtime import BedrockAgentCoreApp
    
    agent = Agent()
    app = BedrockAgentCoreApp()
    
    @app.entrypoint
    def invoke(payload):
       user_message = payload.get("prompt", "Hello")
       response = agent(user_message)
       return str(response)
    
    if __name__ == "__main__":
       app.run()
  3. Dependencies in requirements.txt:

    strands-agents
    bedrock-agentcore
  4. Creating Amazon Cognito User Pool and Test User:

    # Create User Pool and capture 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 Client and capture Client 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 test user
    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 "Client ID: $CLIENT_ID"
  5. Deploy the Agent:

    Using the Amazon Bedrock AgentCore command-line interface:

    pip install bedrock-agentcore-starter-toolkit
    agentcore configure --entrypoint agent_example.py --name my_agent --execution-role your-execution-role-arn --requirements-file requirements.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 note of your agent’s runtime Amazon Resource Name (ARN) for future configuration.

Set Up the Custom Domain Solution

Now let’s implement the custom domain solution using the AWS Cloud Development Kit (CDK).

  1. Create a New Directory and Initialize the Project:

    mkdir agentcore-custom-domain
    cd agentcore-custom-domain
    cdk init app --language python
    source .venv/bin/activate
    pip install aws-cdk-lib constructs
  2. Configure the CloudFront Origin:

    Here’s how to encode the agent ARN and prepare the configuration:

    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, safe="")
    region = agent_runtime_arn.split(':')[3]
  3. Handle CORS Requirements:

    If your frontend application runs on a different domain, configure CORS headers:

    from aws_cdk.aws_cloudfront import ResponseHeadersPolicy, ResponseHeadersCorsBehavior
    
    cors_policy = ResponseHeadersPolicy(self, 'CorsPolicy',
       cors_behavior=ResponseHeadersCorsBehavior(
           access_control_allow_origins=['*'],
           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
       )
    )
  4. Create the CloudFront Distribution:

    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.{region}.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=Duration.seconds(120)
           ),
           viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
           cache_policy=CachePolicy.CACHING_DISABLED,
           allowed_methods=AllowedMethods.ALLOW_ALL,
           response_headers_policy=cors_policy,
           origin_request_policy=OriginRequestPolicy.ALL_VIEWER,
       ),
       domain_names=[domain_name] if domain_name else None,
       certificate=certificate if domain_name else None,
    )
  5. Configure SSL Certificates and DNS Records:

    from aws_cdk.aws_certificatemanager import Certificate, CertificateValidation
    from aws_cdk.aws_route53 import HostedZone, ARecord, RecordTarget
    from aws_cdk.aws_route53_targets import CloudFrontTarget
    
    hosted_zone = HostedZone.from_lookup(self, 'HostedZone',
       domain_name="yourcompany.com"
    )
    certificate = Certificate(self, 'Certificate',
       domain_name="my-agent.yourcompany.com",
       validation=CertificateValidation.from_dns(hosted_zone),
    )
    ARecord(self, 'AliasRecord',
       zone=hosted_zone,
       record_name="my-agent.yourcompany.com",
       target=RecordTarget.from_alias(CloudFrontTarget(distribution)),
    )
  6. Complete CDK Stack Configuration:

    Here’s the complete AWS CDK stack combining all parts:

    import urllib.parse
    from aws_cdk import Stack, CfnOutput, Duration
    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 Certificate, CertificateValidation
    from aws_cdk.aws_route53 import HostedZone, ARecord, RecordTarget
    from aws_cdk.aws_route53_targets import CloudFrontTarget
    from constructs import Construct
    
    class AgentcoreCustomDomainStack(Stack):
       def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
           super().__init__(scope, construct_id, **kwargs)
    
           agent_runtime_arn = "arn:aws:bedrock-agentcore:us-east-1:accountId:runtime/my_agent-xbcDkz4FR9"
           region = agent_runtime_arn.split(':')[3]
           domain_name = "agent.yourcompany.com"
           hosted_zone_id = "Z1234567890ABC"
           enable_cors = True
    
           encoded_arn = urllib.parse.quote(agent_runtime_arn, safe="")
           bedrock_agentcore_hostname = f"bedrock-agentcore.{region}.amazonaws.com"
           origin_path = f"/runtimes/{encoded_arn}/invocations"
    
           cors_policy = None
           if enable_cors:
               cors_policy = ResponseHeadersPolicy(self, 'CorsPolicy',
                   cors_behavior=ResponseHeadersCorsBehavior(
                       access_control_allow_origins=['*'],
                       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
                   )
               )
    
           distribution_props = {
               "default_behavior": BehaviorOptions(
                   origin=HttpOrigin(
                       bedrock_agentcore_hostname,
                       origin_path=origin_path,
                       protocol_policy=OriginProtocolPolicy.HTTPS_ONLY,
                       read_timeout=Duration.seconds(120)
                   ),
                   viewer_protocol_policy=ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
                   cache_policy=CachePolicy.CACHING_DISABLED,
                   allowed_methods=AllowedMethods.ALLOW_ALL,
                   response_headers_policy=cors_policy,
                   origin_request_policy=OriginRequestPolicy.ALL_VIEWER,
               )
           }
    
           if domain_name:
               hosted_zone = HostedZone.from_hosted_zone_attributes(self, 'HostedZone',
                                                                    zone_name="yourcompany.com",
                                                                    hosted_zone_id=hosted_zone_id
                                                                    )
               certificate = Certificate(self, 'Certificate',
                                         domain_name=domain_name,
                                         validation=CertificateValidation.from_dns(hosted_zone),
                                         )
    
               distribution_props["domain_names"] = [domain_name]
               distribution_props["certificate"] = certificate
    
           distribution = Distribution(self, 'Distribution', **distribution_props)
    
           if domain_name:
               ARecord(self, 'AliasRecord',
                       zone=hosted_zone,
                       record_name=domain_name,
                       target=RecordTarget.from_alias(
                           CloudFrontTarget(distribution)),
                       )
    
           if domain_name:
               domain_url = f"https://{domain_name}/"
               CfnOutput(self, "AgentEndpoint",
                         value=domain_url,
                         description="Your custom domain endpoint"
                         )
    
           CfnOutput(self, "CloudFrontDistribution",
                     value=f"https://{distribution.distribution_domain_name}/",
                     description="CloudFront default domain (works without custom domain)"
                     ) 
  7. Configure the AWS CDK App Entry Point:

    # app.py
    import aws_cdk as cdk
    from agentcore_custom_domain.agentcore_custom_domain_stack import AgentcoreCustomDomainStack
    
    app = cdk.App()
    AgentcoreCustomDomainStack(app, "AgentCoreCustomDomainStack",
       env=cdk.Environment(region='us-east-1'),
    )
    app.synth()

Deploy Your Custom Domain

To deploy the solution, update the following values in agentcore_custom_domain_stack.py:

  • Your Amazon Bedrock AgentCore Runtime ARN
  • Your domain name (if using a custom domain)
  • Your hosted zone ID (if using a custom domain)

Then deploy using the AWS CDK:

cdk deploy

Test Your Endpoint

After deployment, verify your endpoints with either the custom or default domain. First, retrieve 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')

Testing with the Custom Domain

curl -X POST "https://my-agent.yourcompany.com/" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: session-12345678901234567890123456789012345" \
  -d '{"prompt": "Hello, how can you help me today?"}'

Testing with the Default CloudFront Domain

curl -X POST "https://d1234567890123.cloudfront.net/" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Amzn-Bedrock-AgentCore-Runtime-Session-Id: session-12345678901234567890123456789012345" \
  -d '{"prompt": "Hello, how can you help me today?"}'

With everything correctly set up, you should receive a response from your agent through either endpoint!

Considerations

As you implement this solution, keep the following considerations in mind:

  1. Cost Implications: CloudFront adds costs for data transfer and requests. Review the pricing model beforehand.
  2. Security Enhancements: Consider implementing AWS WAF rules for protection, rate limiting to prevent abuse, and geo-restrictions for access.
  3. Monitoring: Enable CloudFront access logs and configure Amazon CloudWatch alarms to monitor performance and error rates.

Clean Up

To prevent ongoing costs, ensure to delete Resources you no longer require. You may need to manually remove Route 53 hosted zones and ACM certificates from their respective consoles.

Conclusion

In this post, we demonstrated how to craft custom domain names for your Amazon Bedrock AgentCore Runtime endpoints using CloudFront as a reverse proxy. This approach not only streamlines integration for development teams but also fortifies your branding efforts and simplifies maintenance.

We encourage you to adapt this solution to meet your specific needs and explore advanced features for enhanced security and monitoring.

For further information, check the Amazon Bedrock AgentCore Developer Guide. Explore the Amazon CloudFront documentation for best practices and AWS Certificate Manager documentation for SSL certificates.

Amazon Bedrock AgentCore is currently in preview and subject to changes. Standard AWS pricing applies for additional services utilized.

About the Authors

Rahmat Fedayizada is a Senior Solutions Architect at AWS, working with energy firms to design scalable, secure architectures.

Paras Bhuva leads a team of Solutions Architects at AWS, helping customers accelerate their transformations in application modernization and AI.


Feel free to explore and customize these solutions according to your organization’s specific requirements!

Latest

Creating a Personal Productivity Assistant Using GLM-5

From Idea to Reality: Building a Personal Productivity Agent...

Lawsuits Claim ChatGPT Contributed to Suicide and Psychosis

The Dark Side of AI: ChatGPT's Alleged Role in...

Japan’s Robotics Sector Hits Record Orders Amid Growing Global Labor Shortages

Japan's Robotics Boom: Navigating Labor Shortages and Global Competition Add...

Analysis of Major Market Segments Fueling the Digital Language Sector

Exploring the Rapid Growth of the Digital Language Learning...

Don't miss

Haiper steps out of stealth mode, secures $13.8 million seed funding for video-generative AI

Haiper Emerges from Stealth Mode with $13.8 Million Seed...

Running Your ML Notebook on Databricks: A Step-by-Step Guide

A Step-by-Step Guide to Hosting Machine Learning Notebooks in...

VOXI UK Launches First AI Chatbot to Support Customers

VOXI Launches AI Chatbot to Revolutionize Customer Services in...

Investing in digital infrastructure key to realizing generative AI’s potential for driving economic growth | articles

Challenges Hindering the Widescale Deployment of Generative AI: Legal,...

Creating a Personal Productivity Assistant Using GLM-5

From Idea to Reality: Building a Personal Productivity Agent in Just Five Minutes with GLM-5 AI A Revolutionary Approach to Application Development This headline captures the...

Creating Smart Event Agents with Amazon Bedrock AgentCore and Knowledge Bases

Deploying a Production-Ready Event Assistant Using Amazon Bedrock AgentCore Transforming Conference Navigation with AI Introduction to Event Assistance Challenges Building an Intelligent Companion with Amazon Bedrock AgentCore Solution...

A Comprehensive Guide to Machine Learning for Time Series Analysis

Mastering Feature Engineering for Time Series: A Comprehensive Guide Understanding Feature Engineering in Time Series Data The Essential Role of Lag Features in Time Series Analysis Unpacking...