<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mohamed Sorour</title>
    <description>The latest articles on Forem by Mohamed Sorour (@sorour).</description>
    <link>https://forem.com/sorour</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2966313%2F3c7b0a8f-b43b-421a-8203-3bfcfc420899.jpeg</url>
      <title>Forem: Mohamed Sorour</title>
      <link>https://forem.com/sorour</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/sorour"/>
    <language>en</language>
    <item>
      <title>How an AWS Agent Helped Me Optimize Resources Effortlessly</title>
      <dc:creator>Mohamed Sorour</dc:creator>
      <pubDate>Tue, 30 Sep 2025 05:18:21 +0000</pubDate>
      <link>https://forem.com/aws-builders/how-an-aws-agent-helped-me-optimize-resources-effortlessly-59hi</link>
      <guid>https://forem.com/aws-builders/how-an-aws-agent-helped-me-optimize-resources-effortlessly-59hi</guid>
      <description>&lt;h1&gt;
  
  
  AWS Resource Optimizer Agent
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/mohamedsorour1998/AWS-Resource-Optimizer-Agent" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built a production-ready &lt;strong&gt;AWS Resource Optimizer Agent&lt;/strong&gt; with &lt;strong&gt;Amazon Bedrock AgentCore Gateway&lt;/strong&gt;, &lt;strong&gt;Claude Sonnet 4.5&lt;/strong&gt;, and the &lt;strong&gt;Strands Agents SDK&lt;/strong&gt;, and it completely transformed how I manage my cloud environment. Instead of digging through CloudWatch dashboards or juggling CLI commands, I can now just ask questions like &lt;em&gt;“Which EC2 instances are underutilized?”&lt;/em&gt; or &lt;em&gt;“Show me Lambda errors from the last 24 hours”&lt;/em&gt;—and the agent instantly pulls the right metrics, logs, or EBS data from over &lt;strong&gt;137 AWS tools&lt;/strong&gt;. I can run it locally for testing or deploy it to &lt;strong&gt;AgentCore Runtime&lt;/strong&gt; for secure, scalable use, with built-in &lt;strong&gt;OAuth, memory, and semantic search&lt;/strong&gt; that make it simple and powerful. Setup took only a few steps—create an IAM role, load the Smithy specs for CloudWatch, Logs, and EBS, and the agent was live. It saves me hours of manual work and gives me confidence my infrastructure is running efficiently—I can’t imagine going back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc880c782kpiwgn6wpdu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc880c782kpiwgn6wpdu.png" alt=" " width="800" height="894"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  📋 Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;
Deployment Options

&lt;ul&gt;
&lt;li&gt;Option 1: Local Development&lt;/li&gt;
&lt;li&gt;Option 2: AgentCore Runtime&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;API Targets &amp;amp; Capabilities&lt;/li&gt;

&lt;li&gt;Setup Guide&lt;/li&gt;

&lt;li&gt;Configuration Reference&lt;/li&gt;

&lt;li&gt;Troubleshooting&lt;/li&gt;

&lt;li&gt;Project Structure&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What It Does
&lt;/h3&gt;

&lt;p&gt;AI-powered agent that monitors and optimizes AWS resources through natural language conversations using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CloudWatch Metrics API&lt;/strong&gt;: Monitor EC2, RDS, Lambda, S3, EBS performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudWatch Logs API&lt;/strong&gt;: Analyze application and infrastructure logs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EBS API&lt;/strong&gt;: Manage volumes and snapshots&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;137 AWS Tools Access&lt;/strong&gt;:  in AgentCore GatewayCloudWatch, Logs, and EBS APIs via AgentCore Gateway
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ews3vw0stnzvodpkhlw.png" alt=" " width="800" height="355"&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Semantic Search&lt;/strong&gt;: Intelligent tool discovery via AgentCore Gateway
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffb7yc3uy6y46201mbder.png" alt=" " width="800" height="336"&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Persistent Memory&lt;/strong&gt;: Cross-session conversation continuity
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lrhg7y3h18dyt7h9zcj.png" alt=" " width="800" height="356"&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Ready&lt;/strong&gt;: Ready local CLI and in progress to be Deployable to AgentCore Runtime
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1bghpfjwuec9478eo4g.png" alt=" " width="800" height="356"&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;OAuth Secured&lt;/strong&gt;: Cognito-based authentication
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpvgxy5sta61pt75pmaqi.png" alt=" " width="800" height="354"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Identify idle or underutilized resources&lt;/li&gt;
&lt;li&gt;Analyze Lambda function errors&lt;/li&gt;
&lt;li&gt;Monitor RDS database performance&lt;/li&gt;
&lt;li&gt;Search CloudWatch logs for issues&lt;/li&gt;
&lt;li&gt;Optimize EBS storage usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66p6l2uaoa0ndefxajqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66p6l2uaoa0ndefxajqz.png" alt=" " width="800" height="511"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xmvuxrdbjhv5w07mtzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xmvuxrdbjhv5w07mtzn.png" alt=" " width="720" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AgentCore Gateway&lt;/strong&gt;: MCP protocol server exposing AWS APIs as tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Sonnet 4.5&lt;/strong&gt;: LLM for natural language understanding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strands Agents&lt;/strong&gt;: Agent orchestration framework&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AgentCore Memory&lt;/strong&gt;: Persistent conversation storage&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognito&lt;/strong&gt;: OAuth 2.0 authentication&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Deployment Options
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Option 1: Local Development (CLI)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Development, testing, rapid iteration&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;li&gt;AWS credentials configured&lt;/li&gt;
&lt;li&gt;Smithy API specs in S3 (&lt;code&gt;cost-explorer-smithy-api&lt;/code&gt; bucket)&lt;/li&gt;
&lt;li&gt;IAM permissions for bedrock-agentcore, IAM, Cognito&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Setup Steps
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Install dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# 2. Create infrastructure&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;setup
python3 01-create-iam-role.py
python3 02-create-gateway.py
python3 03-create-smithy-targets.py

&lt;span class="c"&gt;# Wait 60 seconds for tools to sync&lt;/span&gt;

&lt;span class="c"&gt;# 3. Run agent locally&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..
python3 agent.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Usage&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 agent.py
👤 You: List my CloudWatch metrics
🤖 Agent: &lt;span class="o"&gt;[&lt;/span&gt;Shows available metrics...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Option 2: AgentCore Runtime (Production)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Best for&lt;/strong&gt;: Production deployment, managed hosting, team environments&lt;/p&gt;

&lt;h4&gt;
  
  
  Prerequisites
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;AWS Account with bedrock-agentcore permissions&lt;/li&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;li&gt;Boto3 installed&lt;/li&gt;
&lt;li&gt;Model access: Anthropic Claude Sonnet 4.5 enabled in Bedrock console&lt;/li&gt;
&lt;li&gt;Infrastructure from Option 1 setup (Gateway, Targets, IAM Role)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Deployment Steps
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Configure environment variables&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Copy template&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.template .env

&lt;span class="c"&gt;# Edit .env with your values from config.json&lt;/span&gt;
&lt;span class="nv"&gt;GATEWAY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://resource-optimizer-gateway-xxx.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp
&lt;span class="nv"&gt;COGNITO_CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_client_id
&lt;span class="nv"&gt;COGNITO_CLIENT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_secret
&lt;span class="nv"&gt;COGNITO_TOKEN_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/token
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Deploy to AgentCore Runtime&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Option A: Use deploy script&lt;/span&gt;
./deploy.sh

&lt;span class="c"&gt;# Option B: Manual deployment&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;bedrock-agentcore-starter-toolkit
agentcore configure &lt;span class="nt"&gt;-e&lt;/span&gt; runtime_agent.py
agentcore launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Test deployment&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Quick test&lt;/span&gt;
agentcore invoke &lt;span class="s1"&gt;'{"prompt": "List my Lambda functions"}'&lt;/span&gt;

&lt;span class="c"&gt;# Get agent ARN (from output or bedrock_agentcore.yaml)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Invoke from application&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bedrock-agentcore&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invoke_agent_runtime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agentRuntimeArn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;arn:aws:bedrock-agentcore:us-east-1:ACCOUNT:agent/AGENT_ID&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Show me idle EC2 instances&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Process streaming response
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Runtime Management
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;View logs&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check CloudWatch Logs (location shown in deploy output)&lt;/span&gt;
aws logs &lt;span class="nb"&gt;tail&lt;/span&gt; /aws/bedrock-agentcore/agent/YOUR_AGENT_ID &lt;span class="nt"&gt;--follow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update agent&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Make code changes, then redeploy&lt;/span&gt;
agentcore launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Delete runtime&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Via CLI&lt;/span&gt;
aws bedrock-agentcore delete-agent-runtime &lt;span class="nt"&gt;--agent-runtime-arn&lt;/span&gt; YOUR_ARN

&lt;span class="c"&gt;# Or use AWS Console&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  API Targets &amp;amp; Capabilities
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CloudWatch Metrics (40 tools)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Monitor AWS resource performance&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ListMetrics&lt;/code&gt;: Discover available metrics&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetMetricStatistics&lt;/code&gt;: Retrieve metric data points&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetMetricData&lt;/code&gt;: Query multiple metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Queries&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Show me EC2 CPU utilization"&lt;/li&gt;
&lt;li&gt;"List Lambda invocation metrics"&lt;/li&gt;
&lt;li&gt;"Get RDS database read latency"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CloudWatch Logs (91 tools)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Search and analyze logs&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DescribeLogGroups&lt;/code&gt;: List log groups&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FilterLogEvents&lt;/code&gt;: Search logs with patterns&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetLogEvents&lt;/code&gt;: Retrieve log entries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Queries&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Search Lambda logs for errors"&lt;/li&gt;
&lt;li&gt;"Show recent log events for my application"&lt;/li&gt;
&lt;li&gt;"Find API Gateway 5xx errors"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  EBS (6 tools)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;: Manage EBS volumes and snapshots&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Operations&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ListSnapshotBlocks&lt;/code&gt;: List snapshot blocks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GetSnapshotBlock&lt;/code&gt;: Retrieve block data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Queries&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"List my EBS volumes"&lt;/li&gt;
&lt;li&gt;"Show snapshot details"&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setup Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Create IAM Role
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Script&lt;/strong&gt;: &lt;code&gt;setup/01-create-iam-role.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it creates&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Role name: &lt;code&gt;ResourceOptimizerGatewayRole&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Trust policy: Allows bedrock-agentcore.amazonaws.com&lt;/li&gt;
&lt;li&gt;Permissions: CloudWatch, Logs, EBS, S3 access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Permissions granted&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"CloudWatch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GetMetricStatistics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ListMetrics"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GetMetricData"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Logs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"DescribeLogGroups"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FilterLogEvents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GetLogEvents"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"EBS"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ListSnapshotBlocks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GetSnapshotBlock"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"S3"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ListBucket"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;For&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Smithy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;specs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 setup/01-create-iam-role.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create AgentCore Gateway
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Script&lt;/strong&gt;: &lt;code&gt;setup/02-create-gateway.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it creates&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gateway with MCP protocol&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Semantic Search enabled&lt;/strong&gt; (intelligent tool selection)&lt;/li&gt;
&lt;li&gt;Debug mode for detailed errors&lt;/li&gt;
&lt;li&gt;Cognito OAuth authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Features&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;protocolConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;searchType&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SEMANTIC&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Critical&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="mi"&gt;137&lt;/span&gt; &lt;span class="n"&gt;tools&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 setup/02-create-gateway.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;: Gateway URL stored in &lt;code&gt;config.json&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Create Smithy Targets
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Script&lt;/strong&gt;: &lt;code&gt;setup/03-create-smithy-targets.py&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it creates&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CloudWatchTarget&lt;/strong&gt; (371KB Smithy spec)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudWatchLogsTarget&lt;/strong&gt; (645KB Smithy spec)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EBSTarget&lt;/strong&gt; (92KB Smithy spec)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Smithy Specs Required&lt;/strong&gt;:&lt;br&gt;
Upload to S3 bucket &lt;code&gt;cost-explorer-smithy-api&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;cloudwatch-2010-08-01.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cloudwatch-logs-2014-03-28.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ebs-2019-11-02.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Run&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 setup/03-create-smithy-targets.py
&lt;span class="c"&gt;# Wait 60 seconds for tools to sync&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output&lt;/strong&gt;: Target IDs stored in &lt;code&gt;config.json&lt;/code&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Configuration Reference
&lt;/h2&gt;

&lt;h3&gt;
  
  
  config.json Structure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"aws"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"account_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"339712964409"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"gateway_role_arn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::ACCOUNT:role/ResourceOptimizerGatewayRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"region"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cognito"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user_pool_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1_xxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"client_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"client_secret"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"discovery_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://cognito-idp.us-east-1.amazonaws.com/..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"token_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.auth.us-east-1.amazoncognito.com/oauth2/token"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gateway"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resource-optimizer-gateway-xxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://resource-optimizer-gateway-xxx.gateway.bedrock-agentcore.us-east-1.amazonaws.com/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"resource-optimizer-gateway"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"smithy_targets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XXXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CloudWatchTarget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3://cost-explorer-smithy-api/cloudwatch-2010-08-01.json"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XXXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CloudWatchLogsTarget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3://cost-explorer-smithy-api/cloudwatch-logs-2014-03-28.json"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"XXXXX"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"EBSTarget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3://cost-explorer-smithy-api/ebs-2019-11-02.json"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"memory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ResourceOptimizerMemory-xxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ResourceOptimizerMemory"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Environment Variables (AgentCore Runtime)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Required&lt;/span&gt;
&lt;span class="nv"&gt;GATEWAY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://your-gateway.gateway.bedrock-agentcore.REGION.amazonaws.com/mcp
&lt;span class="nv"&gt;COGNITO_CLIENT_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_client_id
&lt;span class="nv"&gt;COGNITO_CLIENT_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_client_secret
&lt;span class="nv"&gt;COGNITO_TOKEN_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://your-domain.auth.REGION.amazoncognito.com/oauth2/token

&lt;span class="c"&gt;# Optional&lt;/span&gt;
&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1  &lt;span class="c"&gt;# Defaults to us-east-1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local Development Issues
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Agent shows 0 tools
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;: Targets not synced yet&lt;br&gt;
&lt;strong&gt;Fix&lt;/strong&gt;: Wait 60 seconds after running &lt;code&gt;03-create-smithy-targets.py&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Permission denied errors
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;: Missing IAM permissions&lt;br&gt;
&lt;strong&gt;Fix&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Add AgentCore permissions to your IAM user&lt;/span&gt;
aws iam put-user-policy &lt;span class="nt"&gt;--user-name&lt;/span&gt; YOUR_USER &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-name&lt;/span&gt; AgentCoreAdmin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--policy-document&lt;/span&gt; &lt;span class="s1"&gt;'{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": "bedrock-agentcore:*",
      "Resource": "*"
    }]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Smithy spec too large error
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Cause&lt;/strong&gt;: Spec exceeds 2MB limit&lt;br&gt;
&lt;strong&gt;Fix&lt;/strong&gt;: We use specs under 2MB (CloudWatch 371KB, Logs 645KB, EBS 92KB)&lt;/p&gt;

&lt;h3&gt;
  
  
  AgentCore Runtime Issues
&lt;/h3&gt;

&lt;h4&gt;
  
  
  CodeBuild build error
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Check&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;View CodeBuild logs in AWS Console&lt;/li&gt;
&lt;li&gt;Verify IAM permissions include CodeBuild access&lt;/li&gt;
&lt;li&gt;Check requirements.txt is valid&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Model access denied
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enable Anthropic Claude Sonnet 4.5 in Bedrock console&lt;/li&gt;
&lt;li&gt;Verify region matches (default: us-west-2 for runtime, us-east-1 for gateway)&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Docker not found warning
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Info&lt;/strong&gt;: Can be ignored - CodeBuild doesn't need Docker unless using &lt;code&gt;--local&lt;/code&gt; flag&lt;/p&gt;

&lt;h3&gt;
  
  
  Gateway Issues
&lt;/h3&gt;

&lt;h4&gt;
  
  
  list_gateway_targets returns 0 targets
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This API has known issues. Use &lt;code&gt;get_gateway_target(targetId=X)&lt;/code&gt; instead&lt;/p&gt;

&lt;h4&gt;
  
  
  Tools not loading after target creation
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Fix&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wait 60 seconds for synchronization&lt;/li&gt;
&lt;li&gt;Verify S3 bucket contains Smithy specs: &lt;code&gt;aws s3 ls s3://cost-explorer-smithy-api/&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws-cost-optimization-agent/
├── agent.py                    # Local CLI agent
├── runtime_agent.py            # AgentCore Runtime agent
├── requirements.txt            # Python dependencies
├── config.json                 # Auto-generated configuration
├── .env.template               # Environment template
├── deploy.sh                   # Runtime deployment script
├── README.md                   # This file
├── COMPLETION-SUMMARY.md       # Project history
└── setup/
    ├── 01-create-iam-role.py       # IAM role creation
    ├── 02-create-gateway.py        # Gateway with semantic search
    └── 03-create-smithy-targets.py # All 3 API targets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;agent.py&lt;/strong&gt;: Interactive CLI agent for local development&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;runtime_agent.py&lt;/strong&gt;: Deployable agent for AgentCore Runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;config.json&lt;/strong&gt;: Auto-generated by setup scripts (not in git)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.env&lt;/strong&gt;: Environment variables for runtime (not in git)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Technical Specifications
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Startup&lt;/strong&gt;: ~3 seconds (local), ~1 second (runtime)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Loading&lt;/strong&gt;: 137 tools (40 CloudWatch + 91 Logs + 6 EBS)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Time&lt;/strong&gt;: 2-4 seconds for typical queries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt;: Last 5 conversation turns (local), stateless (runtime)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Limits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Smithy Spec Size&lt;/strong&gt;: 2MB maximum per target&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool Name Length&lt;/strong&gt;: 64 characters (Bedrock limitation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Window&lt;/strong&gt;: 200K tokens (Claude Sonnet 4.5)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate Limits&lt;/strong&gt;: CloudWatch 400+ req/sec (high)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Technologies
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;Claude Sonnet 4.5&lt;/td&gt;
&lt;td&gt;20250929&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent Framework&lt;/td&gt;
&lt;td&gt;Strands Agents&lt;/td&gt;
&lt;td&gt;Latest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway&lt;/td&gt;
&lt;td&gt;AgentCore Gateway&lt;/td&gt;
&lt;td&gt;MCP Protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory&lt;/td&gt;
&lt;td&gt;AgentCore Memory&lt;/td&gt;
&lt;td&gt;Short-term (30 days)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Amazon Cognito&lt;/td&gt;
&lt;td&gt;OAuth 2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;AgentCore Runtime&lt;/td&gt;
&lt;td&gt;Container-based&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Authentication Flow
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Agent requests OAuth token from Cognito&lt;/li&gt;
&lt;li&gt;Token passed in Authorization header to Gateway&lt;/li&gt;
&lt;li&gt;Gateway assumes IAM role for AWS API calls&lt;/li&gt;
&lt;li&gt;All communication over TLS&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Use least-privilege IAM policies&lt;/li&gt;
&lt;li&gt;✅ Rotate Cognito client secrets regularly&lt;/li&gt;
&lt;li&gt;✅ Enable CloudWatch logging for audit trail&lt;/li&gt;
&lt;li&gt;✅ Use VPC endpoints for private access (optional)&lt;/li&gt;
&lt;li&gt;✅ Review IAM role permissions quarterly&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/" rel="noopener noreferrer"&gt;AgentCore Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/userguide/runtime.html" rel="noopener noreferrer"&gt;AgentCore Runtime Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://strandsagents.com/" rel="noopener noreferrer"&gt;Strands Agents SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.org/" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/cloudwatch/" rel="noopener noreferrer"&gt;AWS CloudWatch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Support
&lt;/h2&gt;

&lt;p&gt;For issues:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check troubleshooting section above&lt;/li&gt;
&lt;li&gt;Review CloudWatch Logs&lt;/li&gt;
&lt;li&gt;Verify configuration in &lt;code&gt;config.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check AWS service quotas&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;strong&gt;Status&lt;/strong&gt;: ✅ Production Not Ready yet (Still facing some issues in runtime, once i solve it i will update the code and the post)&lt;br&gt;
&lt;strong&gt;Last Updated&lt;/strong&gt;: September 30, 2025&lt;br&gt;
&lt;strong&gt;Total Tools&lt;/strong&gt;: 137 across 3 API targets&lt;/p&gt;

</description>
      <category>python</category>
      <category>ai</category>
      <category>aws</category>
    </item>
    <item>
      <title>Building Smart Learning Assistants with Amazon Nova: Why Hinting Is Better Than Answering</title>
      <dc:creator>Mohamed Sorour</dc:creator>
      <pubDate>Fri, 16 May 2025 04:51:14 +0000</pubDate>
      <link>https://forem.com/sorour/building-smart-learning-assistants-with-amazon-nova-why-hinting-is-better-than-answering-59pg</link>
      <guid>https://forem.com/sorour/building-smart-learning-assistants-with-amazon-nova-why-hinting-is-better-than-answering-59pg</guid>
      <description>&lt;p&gt;Have you ever had a teacher who simply provided you with the solutions to your homework? Yes,that was satisfying at the time, but did you really gain any knowledge? Most likely not.&lt;/p&gt;

&lt;p&gt;That was the main obstacle we had to overcome in order to create an AI helper for RosettaCloud's interactive Labs. Our platform teaches shell programming and DevOps, and we wanted to develop an AI assistant that would do more than just solve problems for students—it should help them learn.&lt;/p&gt;

&lt;p&gt;In this post, I'll describe how we used LangChain, Amazon Bedrock's Nova LLM, and RAG (Retrieval-Augmented Generation) system to create a hint-first instructional chatbot that have a knowledge base and a memory, Instead of depriving pupils of educational chances, our method guarantees that the assistant leads them toward discoveries.&lt;/p&gt;

&lt;p&gt;The "Don't Just Tell Me" Philosophy&lt;br&gt;
When learning technical skills like DevOps, Shell Scripting or Kubernetes, students need to develop troubleshooting abilities and pattern recognition. If an AI simply answers questions directly, it short-circuits the learning process.&lt;/p&gt;

&lt;p&gt;Here is how our interactive-lab will look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dvpfn551g0sjxbx41rq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9dvpfn551g0sjxbx41rq.png" alt="Image description" width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now lets focus on AI our AI assistant:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnez10c13kyo0xqvucoka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnez10c13kyo0xqvucoka.png" alt="Image description" width="512" height="1050"&gt;&lt;/a&gt;&lt;br&gt;
Here's our educational philosophy baked into our AI assistant:&lt;/p&gt;

&lt;p&gt;First interaction: Provide a hint that guides the student toward the solution&lt;br&gt;
Follow-up questions: Provide more direct assistance if the student is still stuck&lt;br&gt;
Context-aware memory: Remember the conversation to provide increasingly targeted help&lt;br&gt;
Nova's strength in context understanding and its ability to follow complex instructions made it perfect for this approach. Let's dive into how we built it.&lt;/p&gt;

&lt;p&gt;Architecture Overview: The RosettaCloud Chatbot Flow&lt;/p&gt;

&lt;p&gt;Our system follows a 7-step flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecbb41klyg1tv9d4wlyn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fecbb41klyg1tv9d4wlyn.png" alt="Image description" width="329" height="843"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;1- User asks a question in the Angular frontend&lt;br&gt;
2- Question is sent via WebSockets to API Gateway&lt;br&gt;
3- The AI Chatbot Lambda processes the request&lt;br&gt;
4- Two parallel operations:&lt;br&gt;
 A- Fetch chat history from DynamoDB&lt;br&gt;
 B- Search for relevant documents in our LanceDB vector database&lt;br&gt;
5- Amazon Bedrock's Nova processes everything&lt;br&gt;
6- Response is streamed back to the client&lt;br&gt;
7- Frontend renders the response with helpful references&lt;/p&gt;

&lt;p&gt;This architecture gives us real-time interactions with context awareness, making the student experience feel like working with a patient tutor.&lt;/p&gt;

&lt;p&gt;The Core Components&lt;/p&gt;
&lt;h3&gt;
  
  
  Angular Client side app
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgk6kvvduu26mi168war3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgk6kvvduu26mi168war3.png" alt="Image description" width="800" height="898"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  WebSocket Communication for Real-Time Responses
&lt;/h3&gt;

&lt;p&gt;Students expect real-time help. We use WebSockets to create a streaming experience:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ubk7f2fd2r8smz3xdzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ubk7f2fd2r8smz3xdzg.png" alt="Image description" width="800" height="831"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typescript
// Angular service for WebSocket communication
@Injectable({
  providedIn: 'root'
})
export class ChatbotService {
  private socket: WebSocket;
  private messageSubject = new Subject&amp;lt;ChatMessage&amp;gt;();

  constructor() {
    this.connectWebSocket();
  }

  private connectWebSocket() {
    // Connect to our API Gateway WebSocket endpoint
    this.socket = new WebSocket(environment.chatbotWebsocketUrl);

    this.socket.onmessage = (event) =&amp;gt; {
      const data = JSON.parse(event.data);
      this.messageSubject.next(data);
    };
  }

  sendQuestion(question: string) {
    const payload = {
      prompt: question,
      session_id: this.getSessionId(),
      bedrock_model_id: 'amazon.nova-lite-v1:0',
      model_kwargs: {
        temperature: 0.7, 
        top_p: 0.9,
        max_tokens_to_sample: 512
      }
    };

    this.socket.send(JSON.stringify(payload));
  }

  getMessages(): Observable&amp;lt;ChatMessage&amp;gt; {
    return this.messageSubject.asObservable();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Lambda Backend: AI Chatbot with RAG
&lt;/h3&gt;

&lt;p&gt;The heart of our system is the AI Chatbot Lambda which handles:&lt;/p&gt;

&lt;p&gt;Processing the user's question&lt;br&gt;
Retrieving relevant context from our knowledge base&lt;br&gt;
Building a conversational RAG workflow&lt;br&gt;
Streaming responses back to the client&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nh36bvxk4qbrpgpjv7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1nh36bvxk4qbrpgpjv7b.png" alt="Image description" width="800" height="543"&gt;&lt;/a&gt;&lt;br&gt;
Here's a simplified version of our ai_chatbot.py Lambda function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def handle_message(event, context):
    connection_id = event.get('requestContext', {}).get('connectionId', '')
    api_endpoint = get_api_endpoint_from_event(event)

    body = json.loads(event.get("body", "{}"))
    prompt = body["prompt"]
    bedrock_model_id = body["bedrock_model_id"]
    model_kwargs = body["model_kwargs"]
    session_id = body["session_id"]

    try:
        # Initialize our streaming wrapper for Bedrock
        streamer = BedrockStreamer(connection_id, session_id, api_endpoint)

        # Create the RAG chain with LangChain
        conversation = streamer.create_rag_chain(
            LANCEDB_S3_URI, 
            KNOWLEDGE_BASE_ID, 
            bedrock_model_id, 
            model_kwargs
        )

        # Stream the response
        for response in streamer.stream_response(conversation, prompt):
            streamer.params["Data"] = response
            streamer.api_client.post_to_connection(**streamer.params)

        return {"statusCode": 200, "body": json.dumps("Success")}

    except Exception as e:
        print(f"Error: {str(e)}")
        # Error handling...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The BedrockStreamer class is where the magic happens:
&lt;/h3&gt;

&lt;p&gt;Our chatbot system's foundation is the BedrockStreamer class, which manages the intricate interaction between human inquiries and AI answers.  It establishes connections to Amazon Bedrock for AI processing and API Gateway for WebSocket communication.  Fundamentally, this class builds the RAG (Retrieval Augmented Generation) pipeline by setting up the conversational components of LangChain, initializing vector retrievers from LanceDB, defining the "hint-first" instructional prompt method, and controlling the streaming response system.  It manages important activities including using heartbeat messages to sustain WebSocket connections, adding instructional metadata to answers, and using DynamoDB to ensure session persistence.  Instead of functioning as a unified teaching aid, the many elements would remain disjointed fragments in the absence of this overarching orchestration layer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
class BedrockStreamer:
    def __init__(self, connectionId, session_id, api_endpoint):
        self.api_client = boto3.client("apigatewaymanagementapi", 
                                       endpoint_url=api_endpoint)
        self.bedrock_client = boto3.client(service_name='bedrock-runtime', 
                                          region_name=BEDROCK_REGION)
        self.session_id = session_id
        self.doc_sources = []
        self.params = {
            "Data": "",
            "ConnectionId": connectionId
        }
        self.heartbeat_active = False

    def set_prompt(self, response_style="balanced"):
        # The key to our hint-first approach is in the system prompt
        system_prompt = (
            "You are an assistant specializing in DevOps. "
            f"Use a {response_style} style - be direct, clear and efficient. "
            "Use the following pieces of retrieved context to answer "
            "But do not include the context in your answer. "
            "You should not answer the question directly, but rather hint the user "
            "to the answer. if the user asked again, then you can answer. "
            "You should not answer any question not related to DevOps or SWE. "
            "If the user asks about something else, say that you are not able to "
            "answer that. If the user asks about DevOps, answer it. "
            "the question about DevOps. If you don't know the answer, "
            "say that you don't know. When showing code examples, "
            "format them properly with markdown syntax."
            "\n\n"
            "{context}"
        )

        # Conversation prompt for chat history context
        qa_prompt = ChatPromptTemplate.from_messages([
            ("system", system_prompt),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{input}"),
        ])

        return qa_prompt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Nova LLM: The Brain That Gets Educational Context
&lt;/h3&gt;

&lt;p&gt;Amazon Bedrock's Nova model is particularly good at understanding the nuance between "give a hint" and "provide the answer." We configure it to provide educational guidance:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54328y4pw73gt10vv6tj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54328y4pw73gt10vv6tj.png" alt="Image description" width="800" height="848"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def create_rag_chain(self, lancedb_uri, knowledge_base_id, bedrock_model_id, model_kwargs):
    # Get our educational prompt template
    qa_prompt = self.set_prompt("educational")

    # Initialize vector retriever for our shell script knowledge base
    retriever = self.init_retriever(lancedb_uri, knowledge_base_id)

    # Initialize Bedrock LLM with Nova
    llm = BedrockChat(
        model_id=bedrock_model_id,
        model_kwargs=model_kwargs,
        streaming=True,
        client=self.bedrock_client
    )

    # Create chain components using LangChain
    history_aware_retriever = create_history_aware_retriever(llm, retriever)
    question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)
    rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)

    # Make it conversational with DynamoDB chat history
    conversational_rag_chain = RunnableWithMessageHistory(
        rag_chain,
        lambda session_id: DynamoDBChatMessageHistory(
            table_name=DYNAMO_TABLE,
            session_id=self.session_id
        ),
        input_messages_key="input",
        history_messages_key="chat_history",
    )

    return conversational_rag_chain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stream response back via web sockets:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi5tf8j311pdd7qng52d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwi5tf8j311pdd7qng52d.png" alt="Image description" width="589" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular show it to user:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futirep4gmnyqznkbxcnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futirep4gmnyqznkbxcnz.png" alt="Image description" width="436" height="852"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Knowledge Base Indexing: Document Indexer Lambda
&lt;/h2&gt;

&lt;p&gt;For our assistant to be effective, it needs access to high-quality learning materials. We built a document indexing system that processes shell scripts and extracts educational metadata.&lt;br&gt;
Our chatbot system's knowledge base is created and maintained via the crucial background operation known as Document Indexing Flow. &lt;/p&gt;

&lt;p&gt;The Document Indexer Lambda is automatically activated by an EventBridge trigger when shell scripts are uploaded to S3. The Lambda meticulously examines each script to collect educational metadata such as the question text, difficulty level, correct answers, and verification logic.  The improved script representations are then converted into vector embeddings that capture semantic meaning using this Lambda using Amazon Bedrock's Titan Embeddings model.  The contextual understanding of the chatbot is powered by a searchable knowledge base created by storing these vectors in LanceDB.  Without human involvement, this automated pipeline guarantees that our chatbot always has access to up-to-date, correctly indexed instructional information, enabling the system to grow naturally as more learning resources are added.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8tqond7cjv2bludc4g5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8tqond7cjv2bludc4g5.png" alt="Image description" width="800" height="118"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def process_shell_script(text, filename):
    # Extract educational metadata from shell script comments
    lab_info = {
        'exercise_name': '',
        'difficulty': '',
        'learning_objectives': [],
        'question_number': '',
        'question': '',
        'question_type': '',
        'possible_answers': [],
        'correct_answer': '',
        'question_flag': '',
        'check_flag': ''
    }

    # Parse the shell script to extract question info
    # from comments and code blocks
    # ...

    # Create an enhanced representation that includes
    # educational context
    enhanced_text = f"""
SCRIPT NAME: {filename}

ORIGINAL CONTENT:
{text}

SUMMARY OF COMMENTS:
{chr(10).join(comments)}

MAIN COMMAND BLOCKS:
{chr(10) + chr(10).join([f"Block {i+1}:{chr(10)}{block}" for i, block in enumerate(command_blocks)])}

LAB QUESTION INFORMATION:
{formatted_lab_metadata}
"""

    return enhanced_text, lab_info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Hint-First Approach in Action&lt;br&gt;
Let's see how this actually works in practice. Here's a sample interaction:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwfrzs1aet5tmcqukt4e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwfrzs1aet5tmcqukt4e.png" alt="Image description" width="432" height="845"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyxgdevhuyimnsv9f637.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyxgdevhuyimnsv9f637.png" alt="Image description" width="440" height="849"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4st1x8wumkybis1i1frc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4st1x8wumkybis1i1frc.png" alt="Image description" width="438" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned from Building with Nova
&lt;/h2&gt;

&lt;p&gt;After implementing this system, we've learned several valuable lessons:&lt;/p&gt;

&lt;p&gt;Nova does a remarkable job of adhering to subtle instructions and maintaining the "hint first" strategy. Streaming is crucial. Compared to waiting for full answers, the WebSocket method feels considerably more interactive.&lt;/p&gt;

&lt;p&gt;We went through numerous iterations to find the ideal balance between being too helpful and being helpful. Careful prompt engineering matters. Context is king: The assistant is genuinely helpful when it combines conversation history and document retrieval.&lt;/p&gt;

&lt;p&gt;Finding a balance between user delight and instructional value was the most challenging aspect. Students would become irritated if the helper was very restricted. They wouldn't learn if they were too helpful. We were able to achieve that balance because of Nova's adaptability.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Significance of This for Education
&lt;/h2&gt;

&lt;p&gt;There are two main types of traditional approaches to educational chatbots:&lt;/p&gt;

&lt;p&gt;Basic Q&amp;amp;A bots that offer straightforward responses without any direction&lt;br&gt;
Systems that are too tight and irritate kids&lt;/p&gt;

&lt;p&gt;With Nova, our hint-first strategy establishes a compromise—a system that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Promotes critical thinking&lt;/li&gt;
&lt;li&gt;Offers scaffolded assistance&lt;/li&gt;
&lt;li&gt;Increases directness gradually in accordance with student needs&lt;/li&gt;
&lt;li&gt;Keeps in mind the context of the conversation to offer tailored assistance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This reflects the real job of effective teachers. They point students in the direction of answers rather than solving their difficulties.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: AI in Education's Future
&lt;/h2&gt;

&lt;p&gt;Developing educational AI differs greatly from developing a general-purpose helper. A well-designed RAG system and Amazon Nova's adaptability enabled us to develop something that genuinely improves learning rather than hinders it.&lt;/p&gt;

&lt;p&gt;As we keep improving our system, we're investigating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More advanced methods for knowledge retrieval &lt;/li&gt;
&lt;li&gt;Progress monitoring to automatically modify hint levels&lt;/li&gt;
&lt;li&gt;Integration with practical laboratory settings for instantaneous feedback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI in education is not about substituting answer machines for instructors. The goal is to build assistants that, like the best human teachers, know when to guide, when to instruct, and when to hint.&lt;br&gt;
Have you developed AI systems for education? Which strategies have you found work best for striking a balance between learning support and assistance? Leave a comment with your ideas!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>bedrock</category>
      <category>ai</category>
      <category>cb</category>
    </item>
  </channel>
</rss>
