Agentic AI weather assistant built with Amazon Bedrock that plans API calls, fetches real-time weather data, and delivers human-readable forecasts
In the evolving landscape of artificial intelligence, the shift from traditional “smart encyclopedias” to Agentic AI represents a significant leap in capability. While traditional AI systems provide static responses based on training data, agentic systems are designed to think, plan, and act to solve complex problems. This article explores the core building blocks of Agentic AI, using a hands-on weather assistant project built with Amazon Bedrock and Python as a primary example.
Understanding Agentic AI
Agentic AI moves beyond the “Question → Answer” model toward a “Problem → Plan → Action → Result” workflow. According to the sources, true agentic systems are defined by three key characteristics:
- Autonomy: The ability to make independent decisions, such as choosing appropriate tools or interpreting location descriptions without constant human guidance.
- Reactivity: The capacity to respond to environmental changes, handle errors, and adjust strategies based on real-time results.
- Proactivity: Taking the initiative to achieve goals through multi-step planning and anticipating user needs
The Architecture of an AI Agent
A functional AI agent requires a “brain” for reasoning and “hands” to interact with the world. The sources outline a four-step process for a weather-focused agent:
- User Input: The user provides a location in any format (e.g., ZIP code, city name, or coordinates).
- AI Planning: Using a model like Claude 4.5 Sonnet , the agent analyzes the input and determines the necessary coordinates and API endpoints.
- Action (API Calls): The agent executes the plan. For weather data, this involves a two-step process: first calling the NWS Points API to find the correct forecast office, then calling the Forecast API for the actual data.
- AI Summary: The agent processes technical JSON data into a human-friendly, readable summary
Why Amazon Bedrock?
Amazon Bedrock serves as a foundation for these systems by providing access to high-performing models like Claude, which excels at complex reasoning and structured data processing. Bedrock offers managed infrastructure and enterprise-grade security , allowing developers to build agents that are both scalable and cost-effective.
Real-World Impact and Future Steps
The patterns used to build a weather assistant are highly transferable to other industries:
- Travel and Logistics: Agents can check weather, monitor traffic, and automatically adjust itineraries or routes.
- Agriculture: Monitoring environmental conditions to recommend specific farming actions.
- Emergency Management: Tracking severe weather to coordinate rapid responses.
- Business Operations: Automating market analysis, customer support, and risk assessment.
Development and Implementation
Building an agent can be approached through different interfaces depending on the end-user:
- Command-Line Interface (CLI): Ideal for developers and automation, focusing on direct interaction and raw workflow steps.
- Web Application: Using tools like Streamlit, developers can create interactive experiences that visualize the agent’s “thinking” phases, such as planning, execution, and analysis.
The sources emphasize that building from scratch using pure Python and the AWS SDK (boto3) without complex framework abstractions allows developers to truly understand the “aha moment” of how an AI agent functions.
Environment Setup
🏠 Your Own AWS Account
To set up the development environment for the weather agent in your own AWS account , you will need to follow a series of steps to configure your local machine and AWS permissions. This process typically takes about 12 minutes.
Prerequisites
Before starting, ensure you have the following:
- Python 3.7+ installed locally.
- An AWS account with appropriate administrative or developer permissions.
- The AWS CLI installed on your machine.
Step 1: Development Environment and Python
You should use a code editor that supports Python syntax, such as Visual Studio Code or PyCharm. Once your editor is ready, verify your Python installation in the terminal using python --version. On macOS, you may specifically need to use python3 and pip3.
Step 2: AWS Credential Configuration
You must provide your agent with access to AWS services using one of two methods
- AWS CLI (Recommended): Run aws configure In your terminal, enter your Access Key ID, Secret Access Key , and set the default region to us-west-2.
- Environment Variables: Manually export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_DEFAULT_REGION in your terminal session.
Step 3: Enable Claude 4.5 Sonnet in Amazon Bedrock
This is a critical step ; without it, your agent will not function.
- Log into the Amazon Bedrock console.
- Ensure you are in the us-west-2 (Oregon) region.
- Navigate to Model Access and request access for Claude 4.5 Sonnet.
- Ensure your IAM user has the permissions bedrock:InvokeModel, bedrock:Converse, and bedrock:ListFoundationModels
Step 4: Project Setup and Dependencies
Create a dedicated workspace for your agent and set up a virtual environment to manage packages:
- Create a directory: mkdir agentic-ai-workshop && cd agentic-ai-workshop.
- Initialize a Virtual Environment: Run python -m venv .venv and activate it. You should see (.venv) it in your terminal prompt once active.
- Install Packages: Create a requirements.txt file (or install directly) containing the necessary libraries like boto3 , requests , and streamlit
Step 5: Verification
To confirm everything is configured correctly, run aws sts get-caller-identity it in your terminal. This should return your AWS account details without errors. Once verified, you are ready to begin building the agent logic using boto3 to interface with the model python -c "import boto3, streamlit, requests; print('✅ All packages installed')"
Troubleshooting Common Issues
- “AWS credentials not found” : Run aws configure to enter your credentials or set the required environment variables manually.
- “Model access denied” : You must specifically request access for Claude 4.5 Sonnet in the Amazon Bedrock console and ensure you are working in the us-west-2 (Oregon) region.
- “Permission denied” errors : Verify that your IAM user has the minimum required permissions: bedrock:InvokeModel, bedrock:Converse, and bedrock:ListFoundationModels.
- “Python command not found” : Ensure Python is installed and added to your system PATH; on some systems, you may need to use python3 and pip3 instead of python and pip.
- Virtual environment issues : If you encounter execution errors, ensure your virtual environment is active (indicated by (.venv) in your terminal prompt).
- Package installation fails : Try re-running the installation command for your dependencies in the terminal.
- Invalid or international locations : The National Weather Service API used by the agent only covers US locations ; international cities or misspellings may result in failed data retrieval.
- Network and connectivity issues : The agent may encounter timeouts or connection problems, which require robust error handling or retry logic.
- Data processing errors : The agent must be able to handle unexpected, incomplete, or inconsistent JSON data returned from the weather APIs.
Understanding Our Agent Architecture
How the National Weather Service APIs Work
The National Weather Service (NWS) provides free weather data through a mandatory two-step API process because the US is divided into a grid system where different forecast offices cover specific squares.
- Points API : This is the first step (https://api.weather.gov/points/{lat},{lon}). It takes latitude and longitude coordinates as input and identifies which NWS forecast office covers that specific location, along with the necessary grid coordinates. For example, coordinates for Seattle map to the "SEW" office at grid 124,67.
- Forecast API : This is the second step (https://api.weather.gov/gridpoints/{office}/{gridX},{gridY}/forecast). It uses the specific office and grid data obtained from the Points API to retrieve the detailed weather forecast in a technical JSON format.
How Our Weather Agent Works
The weather assistant functions as a reasoning engine that follows a linear path: User Input → AI Planning → API Calls → AI Summary → Response.
Instead of hardcoding every possible location, the agent uses Claude 4.5 Sonnet to dynamically figure out what coordinates and API calls are needed based on what the user types.
Understanding the Flow.
The flow of the agent is designed to bridge the gap between human language and technical data:
- Analyze : The AI (Claude) interprets the user’s location description.
- Determine : It identifies the required coordinates and API endpoints.
- Execute : Two sequential API calls are made — first to get the office info, then the weather data.
- Translate : The AI processes the resulting raw data into a friendly summary for the user.
The 4 Steps in Detail
Step 1: User Input
📝The agent is designed to be highly flexible, accepting various location formats without requiring a specific structure. Users can enter:
- City names (e.g., “Seattle” or “Seattle, WA”).
- ZIP codes (e.g., “90210”).
- Informal descriptions (e.g., “downtown Portland”).
- Coordinates (e.g., “47.6062, -122.3321”).
Step 2: AI Planning
🧠In this phase, Claude 4.5 Sonnet acts as the “brain.” It analyzes the input to create a technical strategy:
- It determines the precise coordinates for the user’s location.
- It identifies the correct NWS API endpoints.
- It plans the sequence of calls (knowing it must hit the Points API before the Forecast API).
Step 3: API Calls
🔗The agent executes the plan by making two distinct requests:
- Points API Call : It sends the coordinates to get the forecast office and grid info.
- Forecast API Call : It uses the URL returned by the first call to fetch the actual, detailed weather data.
Step 4: AI Summary
📊The final step involves converting the raw JSON data (which is complex and technical) into a human-friendly format. Claude filters through the technical details to provide a natural response, such as: “Today: Partly cloudy with a high of 72°F. Wind: West at 5–10 mph”
Building the Command-Line Agent
Constructing a command-line interface (CLI) agent allows you to experience the “aha moment” of agentic AI by building every component from scratch. This approach is ideal for developers because it provides a direct, focused interaction and clearly displays the raw workflow steps
Step 1: Establishing the Amazon Bedrock Connection
The foundation of the agent is its connection to the “brain” Claude 4.5 Sonnet
- Implementation: Create a file named weather_agent_cli.py within your agentic-ai-workshop directory
# Import necessary libraries
import boto3 # AWS SDK for Python - allows us to interact with AWS services
import json # For handling JSON data
import subprocess # For running system commands like curl
import time # For adding delays and timing operations
from datetime import datetime # For timestamps and date operations
def call_claude_sonnet(prompt):
"""
This function sends a prompt to Claude 4.5 Sonnet and gets a response.
This is the "brain" of our agent - where the AI thinking happens.
Args:
prompt (str): The question or instruction we want to send to Claude
Returns:
tuple: (success: bool, response: str) - success status and Claude's response or error message
"""
# Create a connection to Amazon Bedrock service
# Bedrock is AWS's service for accessing AI models like Claude
bedrock = boto3.client(
service_name='bedrock-runtime', # Specify we want the runtime version for making AI calls
region_name='us-west-2' # AWS region - using us-west-2 as specified
)
try:
# Send our prompt to Claude and get a response
response = bedrock.converse(
# Specify which version of Claude we want to use
modelId='us.anthropic.claude-sonnet-4-5-20250929-v1:0', # Claude 4.5 Sonnet
# Format our message - Claude expects messages in a specific structure
messages=[
{
"role": "user", # We are the user asking a question
"content": [{"text": prompt}] # Our actual question/prompt
}
],
# Configure how Claude should respond
inferenceConfig={
"maxTokens": 2000, # Maximum length of response (tokens ≈ words)
"temperature": 0.7 # Creativity level (0=very focused, 1=very creative)
}
)
# Extract the actual text response from Claude's response structure
# The response comes nested in a complex structure, so we dig down to get the text
return True, response['output']['message']['content'][0]['text']
except Exception as e:
# If something goes wrong, return an error message
return False, f"Error calling Claude: {str(e)}"
def execute_curl_command(url):
"""
Execute a curl command to fetch data from an API.
This is how our agent "acts" in the real world - making HTTP requests.
Args:
url (str): The URL to fetch data from
Returns:
tuple: (success: bool, response: str) - success status and API response or error message
"""
try:
# Use curl command to make HTTP request
# curl is a command-line tool for making HTTP requests
result = subprocess.run(
['curl', '-s', url], # -s flag makes curl silent (no progress info)
capture_output=True, # Capture the output so we can process it
text=True, # Return output as text (not bytes)
timeout=30 # Give up after 30 seconds
)
# Check if the command was successful
if result.returncode == 0:
return True, result.stdout
else:
return False, f"Curl command failed: {result.stderr}"
except subprocess.TimeoutExpired:
return False, "Request timed out after 30 seconds"
except Exception as e:
return False, f"Error executing curl: {str(e)}"
def generate_weather_api_calls(location):
"""
Use Claude to intelligently generate National Weather Service API calls for a given location.
This is where the "agentic" magic happens - AI generating the API call URL.
Args:
location (str): The location provided by the user
Returns:
tuple: (success: bool, api_calls: list) - success status and list of API URLs or error message
"""
# Create a detailed prompt that teaches Claude how to generate NWS API calls
prompt = f"""
You are an expert at working with the National Weather Service (NWS) API.
Your task: Generate the NWS API URL to get weather forecast data for "{location}".
Instructions:
1. First, determine the approximate latitude and longitude coordinates for this location
2. Generate the NWS Points API URL: https://api.weather.gov/points/{{lat}},{{lon}}
For the coordinates, use your knowledge to estimate:
- Major cities: Use well-known coordinates
- ZIP codes: Estimate based on the area
- States: Use approximate center coordinates
- In case a location description is provided instead of a location name, please use the most likely city and state name as the location for the coordinates
Example for Seattle:
https://api.weather.gov/points/47.6062,-122.3321
Example for largest city in USA:
Based on your knowledge, you will establish location is New York City
https://api.weather.gov/points/40.7128,-74.0060
Now generate the API call (Points API) for the established location.
Return ONLY the complete Points API URL, nothing else.
Format: https://api.weather.gov/points/LAT,LON
"""
print(f"🧠 AI is analyzing '{location}' and generating weather API calls...")
success, response = call_claude_sonnet(prompt)
if success:
# Clean up the response - sometimes Claude adds extra text
api_url = response.strip()
# Make sure we got a valid URL
if api_url.startswith('https://api.weather.gov/points/'):
return True, [api_url] # Return as list for consistency
else:
return False, f"AI generated invalid URL: {api_url}"
else:
return False, response
def get_forecast_url_from_points_response(points_json):
"""
Extract the forecast URL from the NWS Points API response.
Args:
points_json (str): JSON response from the Points API
Returns:
tuple: (success: bool, forecast_url: str) - success status and forecast URL or error message
"""
try:
data = json.loads(points_json)
forecast_url = data['properties']['forecast']
return True, forecast_url
except (json.JSONDecodeError, KeyError) as e:
return False, f"Error parsing Points API response: {str(e)}"
def process_weather_response(raw_json, location):
"""
Use Claude to convert raw NWS API JSON into a human-readable weather summary.
This is where AI processes complex data into useful information.
Args:
raw_json (str): Raw JSON response from NWS API
location (str): Original location for context
Returns:
tuple: (success: bool, summary: str) - success status and processed summary or error message
"""
prompt = f"""
You are a weather information specialist. I have raw National Weather Service forecast data for "{location}" that needs to be converted into a clear, helpful summary for a general audience.
Raw NWS API Response:
{raw_json}
Please create a weather summary that includes:
1. A brief introduction with the location
2. Current conditions and today's forecast
3. The next 2-3 days outlook with key details (temperature, precipitation, wind)
4. Any notable weather patterns or alerts
5. Format the response to be easy to read and understand
Make it informative and practical for someone planning their activities. Focus on being helpful and clear.
"""
print(f"📊 AI is processing weather data and creating summary...")
success, response = call_claude_sonnet(prompt)
return success, response
def run_weather_agent():
"""
Main function that orchestrates our AI agent.
This demonstrates the complete agentic workflow.
"""
print("🌤️ Welcome to the Weather AI Agent!")
print("This agent uses Claude 4.5 Sonnet to help you get weather forecasts.")
print("=" * 60)
while True:
# Get user input
location = input("\n🔍 Enter a location name or description (or 'quit' to exit): ").strip()
if location.lower() in ['quit', 'exit', 'q']:
print("👋 Thanks for using the Weather Agent!")
break
if not location:
print("❌ Please enter a location name or description.")
continue
print(f"\n🚀 Starting weather analysis for '{location}'...")
print("-" * 40)
# Step 1: AI generates the Points API URL
print("Step 1: 🧠 AI Planning Phase")
success, api_calls = generate_weather_api_calls(location)
if not success:
print(f"❌ Failed to generate API calls: {api_calls}")
continue
points_url = api_calls[0]
print(f"✅ Generated Points API URL: {points_url}")
# Step 2: Execute the Points API call
print("\nStep 2: 🔗 Points API Execution")
print("Fetching location data from National Weather Service...")
success, points_response = execute_curl_command(points_url)
if not success:
print(f"❌ Failed to fetch points data: {points_response}")
continue
print(f"✅ Received points data")
# Step 3: Extract forecast URL from Points response
print("\nStep 3: 📍 Extracting Forecast URL")
success, forecast_url = get_forecast_url_from_points_response(points_response)
if not success:
print(f"❌ Failed to extract forecast URL: {forecast_url}")
continue
print(f"✅ Forecast URL: {forecast_url[:60]}...")
# Step 4: Execute the Forecast API call
print("\nStep 4: 🌦️ Forecast API Execution")
print("Fetching weather forecast data...")
success, forecast_response = execute_curl_command(forecast_url)
if not success:
print(f"❌ Failed to fetch forecast data: {forecast_response}")
continue
print(f"✅ Received {len(forecast_response)} characters of forecast data")
# Step 5: AI processes the response
print("\nStep 5: 📊 AI Analysis Phase")
success, summary = process_weather_response(forecast_response, location)
if not success:
print(f"❌ Failed to process data: {summary}")
continue
# Step 6: Display results
print("\nStep 6: 💬 Weather Forecast")
print("=" * 60)
print(summary)
print("=" * 60)
print(f"\n✅ Weather analysis complete for '{location}'!")
# Run the agent when the script is executed
if __name__ == " __main__":
run_weather_agent()
- Key Components : The code establishes a Bedrock Client in the us-west-2 region and structures prompts in the specific message format Claude expects
- Configuration : You must set inference parameters to control the agent’s response length and creativity , while implementing error handling to catch connection issues
Step 2: Developing the Agent’s Logic
An agent needs both “hands” to act and a “brain” to plan. This is achieved through four primary functions.
- execute_curl_command(): Functions as the agent’s hands , executing the actual HTTP requests to external APIs
- generate_weather_api_calls(): Acts as the planning brain , determining the correct coordinates and API endpoints based on user input
- get_forecast_url_from_points_response(): A utility function to extract the specific forecast URL from the National Weather Service (NWS) JSON response
- process_weather_response(): Serves as the analysis brain , translating complex technical data into human-readable insights
Step 3: Executing the Main Workflow
The agent follows a circular pattern that defines the Agentic AI Workflow :
- Planning : The AI analyzes the location (e.g., “Seattle” or “90210”) and maps out the necessary API strategy.
- Action : The agent executes the planned sequence, calling the Points API first to get office data, followed by the Forecast API.
- Processing : Claude analyzes the raw, multi-period JSON weather data to identify the most relevant information.
- Response : The final summary is presented to the user in a friendly format, such as: “Today: Partly cloudy with a high of 72°F”
Testing and Validation
Once your script is complete, you can run it from your terminal using python weather_agent_cli.py To see the agent's autonomy and flexibility in action,
Running the Web Application
To run the web application for your weather agent, you will use Streamlit , a Python library that transforms the agentic logic into an interactive, visual experience. While the web version uses the identical agentic AI logic as the command-line version, it provides a professional presentation with real-time progress indicators.
Launching the Application
Inside your agentic-ai-workshop folder, ensure you have created the weather_agent_web.py file with the complete code provided in the workshop.
Copy this complete code:
import streamlit as st
import boto3
import subprocess
import json
import time
from datetime import datetime
from PIL import Image
import os
# Page configuration
st.set_page_config(
page_title="Weather AI Agent",
page_icon="🌤️",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for better styling
st.markdown("""
<style>
.step-container {
border: 2px solid #e0e0e0;
border-radius: 10px;
padding: 20px;
margin: 10px 0;
background-color: #f9f9f9;
}
.step-header {
font-size: 18px;
font-weight: bold;
color: #1f77b4;
margin-bottom: 10px;
}
.success-box {
border-left: 5px solid #28a745;
background-color: #d4edda;
padding: 10px;
margin: 10px 0;
color: #000000;
}
.error-box {
border-left: 5px solid #dc3545;
background-color: #f8d7da;
padding: 10px;
margin: 10px 0;
color: #000000;
}
.info-box {
border-left: 5px solid #17a2b8;
background-color: #d1ecf1;
padding: 10px;
margin: 10px 0;
color: #000000;
}
</style>
""", unsafe_allow_html=True)
def call_claude_sonnet(prompt):
"""
Connect to Claude 4.5 Sonnet via Amazon Bedrock
"""
bedrock = boto3.client(
service_name='bedrock-runtime',
region_name='us-west-2'
)
try:
response = bedrock.converse(
modelId='us.anthropic.claude-sonnet-4-5-20250929-v1:0',
messages=[
{
"role": "user",
"content": [{"text": prompt}]
}
],
inferenceConfig={
"maxTokens": 2000,
"temperature": 0.7
}
)
return True, response['output']['message']['content'][0]['text']
except Exception as e:
return False, f"Error calling Claude: {str(e)}"
def execute_curl_command(url):
"""
Execute curl command to fetch API data
"""
try:
result = subprocess.run(
['curl', '-s', url],
capture_output=True,
text=True,
timeout=30
)
if result.returncode == 0:
return True, result.stdout
else:
return False, f"Curl command failed: {result.stderr}"
except subprocess.TimeoutExpired:
return False, "Request timed out after 30 seconds"
except Exception as e:
return False, f"Error executing curl: {str(e)}"
def generate_weather_api_calls(location):
"""
Use Claude to generate NWS API calls
"""
prompt = f"""
You are an expert at working with the National Weather Service (NWS) API.
Your task: Generate the NWS API URL to get weather forecast data for "{location}".
Instructions:
1. First, determine the approximate latitude and longitude coordinates for this location
2. Generate the NWS Points API URL: https://api.weather.gov/points/{{lat}},{{lon}}
For the coordinates, use your knowledge to estimate:
- Major cities: Use well-known coordinates
- ZIP codes: Estimate based on the area
- States: Use approximate center coordinates
- In case a location description is provided instead of a location name, please use the most likely city and state name as the location for the coordinates
Example for Seattle:
https://api.weather.gov/points/47.6062,-122.3321
Example for largest city in USA:
Based on your knowledge, you will establish location is New York City
https://api.weather.gov/points/40.7128,-74.0060
Now generate the API call (Points API) for the established location.
Return ONLY the complete Points API URL, nothing else.
Format: https://api.weather.gov/points/LAT,LON
"""
success, response = call_claude_sonnet(prompt)
if success:
api_url = response.strip()
if api_url.startswith('https://api.weather.gov/points/'):
return True, [api_url]
else:
return False, f"AI generated invalid URL: {api_url}"
else:
return False, response
def get_forecast_url_from_points_response(points_json):
"""
Extract forecast URL from Points API response
"""
try:
data = json.loads(points_json)
forecast_url = data['properties']['forecast']
return True, forecast_url
except (json.JSONDecodeError, KeyError) as e:
return False, f"Error parsing Points API response: {str(e)}"
def process_weather_response(raw_json, location):
"""
Use Claude to process NWS API response
"""
prompt = f"""
You are a weather information specialist. I have raw National Weather Service forecast data for "{location}" that needs to be converted into a clear, helpful summary for a general audience.
Raw NWS API Response:
{raw_json}
Please create a weather summary that includes:
1. A brief introduction with the location
2. Current conditions and today's forecast
3. The next 2-3 days outlook with key details (temperature, precipitation, wind)
4. Any notable weather patterns or alerts
5. Format the response to be easy to read and understand
Make it informative and practical for someone planning their activities. Focus on being helpful and clear.
"""
success, response = call_claude_sonnet(prompt)
return success, response
# Sidebar with information
st.sidebar.title("🤖 About This Agent")
st.sidebar.markdown("""
This AI agent demonstrates **Agentic AI** principles:
**🧠 Intelligence** : Uses Claude 4.5 Sonnet to understand locations and plan API calls
**🔗 Action** : Automatically calls the National Weather Service API
**📊 Processing** : Converts complex weather data into readable forecasts
**💬 Response** : Provides helpful, practical weather information
""")
st.sidebar.markdown("---")
st.sidebar.markdown("### 🏗️ Architecture")
st.sidebar.markdown("""
1. **User Input** → Location name
2. **AI Planning** → Generate API calls
3. **Points API** → Get forecast office
4. **Forecast API** → Get weather data
5. **AI Processing** → Create summary
6. **Display Results** → Show to user
""")
# Main application
st.title("🌤️ Weather AI Agent")
st.markdown("### Powered by Claude 4.5 Sonnet on Amazon Bedrock")
st.markdown("""
This intelligent agent helps you get weather forecasts using the National Weather Service API.
Enter any location below and watch the AI agent work through its reasoning process!
""")
# Initialize session state for results
if 'show_results' not in st.session_state:
st.session_state.show_results = False
# Input section
st.markdown("---")
location = st.text_input(
"🔍 Enter a location name or description:",
placeholder="e.g., Seattle, 90210, New York City, National park near Homestead in Florida",
help="You can enter city names, ZIP codes, state names, or location descriptions"
)
# Create columns for the buttons
button_col1, button_col2 = st.columns([2, 1])
with button_col1:
get_forecast = st.button("🚀 Get Weather Forecast", type="primary")
with button_col2:
clear_results = st.button("🗑️ Clear Results", type="secondary")
# Clear results functionality
if clear_results:
st.session_state.show_results = False
st.success("🗑️ Results cleared! Enter a new location to get a fresh forecast.")
if get_forecast:
st.session_state.show_results = True
if st.session_state.show_results and get_forecast:
if not location:
st.error("❌ Please enter a location name or description.")
else:
# Create columns for better layout
col1, col2 = st.columns([2, 1])
with col1:
st.markdown(f"## Weather Analysis for: **{location}**")
# Step 1: AI Planning
with st.container():
st.markdown('<div class="step-container">', unsafe_allow_html=True)
st.markdown('<div class="step-header">🧠 Step 1: AI Planning Phase</div>', unsafe_allow_html=True)
with st.spinner("Claude is analyzing the location and planning the API calls..."):
success, api_calls = generate_weather_api_calls(location)
if success:
points_url = api_calls[0]
st.markdown('<div class="success-box">✅ Points API URL generated successfully!</div>', unsafe_allow_html=True)
st.code(points_url, language="text")
else:
st.markdown(f'<div class="error-box">❌ Failed to generate API calls: {api_calls}</div>', unsafe_allow_html=True)
st.stop()
st.markdown('</div>', unsafe_allow_html=True)
# Step 2: Points API Execution
with st.container():
st.markdown('<div class="step-container">', unsafe_allow_html=True)
st.markdown('<div class="step-header">🔗 Step 2: Points API Execution</div>', unsafe_allow_html=True)
with st.spinner("Fetching location data from National Weather Service..."):
success, points_response = execute_curl_command(points_url)
if success:
st.markdown('<div class="success-box">✅ Received location data from NWS</div>', unsafe_allow_html=True)
# Show a preview of the raw data
with st.expander("🔍 View Raw Points API Response (first 500 characters)"):
st.code(points_response[:500] + "..." if len(points_response) > 500 else points_response, language="json")
else:
st.markdown(f'<div class="error-box">❌ Failed to fetch points data: {points_response}</div>', unsafe_allow_html=True)
st.stop()
st.markdown('</div>', unsafe_allow_html=True)
# Step 3: Extract Forecast URL
with st.container():
st.markdown('<div class="step-container">', unsafe_allow_html=True)
st.markdown('<div class="step-header">📍 Step 3: Extracting Forecast URL</div>', unsafe_allow_html=True)
success, forecast_url = get_forecast_url_from_points_response(points_response)
if success:
st.markdown('<div class="success-box">✅ Forecast URL extracted successfully!</div>', unsafe_allow_html=True)
st.code(forecast_url, language="text")
else:
st.markdown(f'<div class="error-box">❌ Failed to extract forecast URL: {forecast_url}</div>', unsafe_allow_html=True)
st.stop()
st.markdown('</div>', unsafe_allow_html=True)
# Step 4: Forecast API Execution
with st.container():
st.markdown('<div class="step-container">', unsafe_allow_html=True)
st.markdown('<div class="step-header">🌦️ Step 4: Forecast API Execution</div>', unsafe_allow_html=True)
with st.spinner("Fetching weather forecast data..."):
success, forecast_response = execute_curl_command(forecast_url)
if success:
st.markdown(f'<div class="success-box">✅ Received {len(forecast_response):,} characters of forecast data</div>', unsafe_allow_html=True)
# Show a preview of the raw data
with st.expander("🔍 View Raw Forecast API Response (first 500 characters)"):
st.code(forecast_response[:500] + "..." if len(forecast_response) > 500 else forecast_response, language="json")
else:
st.markdown(f'<div class="error-box">❌ Failed to fetch forecast data: {forecast_response}</div>', unsafe_allow_html=True)
st.stop()
st.markdown('</div>', unsafe_allow_html=True)
# Step 5: AI Processing
with st.container():
st.markdown('<div class="step-container">', unsafe_allow_html=True)
st.markdown('<div class="step-header">📊 Step 5: AI Analysis Phase</div>', unsafe_allow_html=True)
with st.spinner("Claude is processing the weather data and creating a summary..."):
success, summary = process_weather_response(forecast_response, location)
if success:
st.markdown('<div class="success-box">✅ Weather analysis complete!</div>', unsafe_allow_html=True)
else:
st.markdown(f'<div class="error-box">❌ Failed to process data: {summary}</div>', unsafe_allow_html=True)
st.stop()
st.markdown('</div>', unsafe_allow_html=True)
# Step 6: Results
st.markdown("---")
st.markdown("## 🌤️ Weather Forecast")
st.markdown(summary)
with col2:
# Real-time status updates
st.markdown("### 📊 Process Status")
status_container = st.container()
with status_container:
st.markdown("""
<div class="info-box">
<strong>🔄 Agent Workflow:</strong><br>
✅ Planning Phase<br>
✅ Points API Call<br>
✅ URL Extraction<br>
✅ Forecast API Call<br>
✅ Data Processing<br>
✅ Results Generated
</div>
""", unsafe_allow_html=True)
st.markdown("### 🎯 What Makes This Agentic?")
st.markdown("""
- **🧠 Reasoning** : AI understands location formats
- **📋 Planning** : Generates appropriate API call sequences
- **🔧 Action** : Executes real-world API requests
- **📊 Processing** : Converts raw data to insights
- **🔄 Adaptation** : Handles different location types
""")
# Footer
st.markdown("---")
st.markdown("""
### 🔬 About This Demo
This application demonstrates **Agentic AI** principles using:
- **Amazon Bedrock** with Claude 4.5 Sonnet for intelligent reasoning
- **National Weather Service API** for real-time weather data
- **Streamlit** for interactive web interface
**⚠️ Important** : This uses official NWS data for educational purposes. For critical weather decisions, consult official sources.
""")
# Add some example queries
st.markdown("### 💡 Try These Examples:")
st.markdown("""
**Suggested locations to test:**
- **Seattle** - Major city (tests city name recognition)
- **90210** - ZIP code (tests postal code handling)
- **New York City** - Multi-word city (tests complex location parsing)
- **Miami, FL** - City with state (tests state abbreviations)
- **Chicago** - Another major city (tests different coordinates)
- **National park near Homestead in Florida** - Location description (tests AI reasoning)
- **Largest City in California** - Descriptive query (tests knowledge-based location finding)
Simply copy any of these into the location input above and click "Get Weather Forecast"!
""")
To start the application, run the following command in your terminal: streamlit run weather\_agent\_web.py
Once executed, you will see output in your terminal indicating the local URL where you can view the interface in your web browser.
You should see output like:
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://192.168.1.100:8501
Interactive Features to Explore
The web interface is designed to make the “agentic” nature of the AI visible to the user through several key features:
- Step-by-Step Visualization : Unlike the CLI, the web app allows you to watch each phase of the workflow as it happens, including the AI Planning Phase , API Execution , and AI Analysis.
- Raw Data Inspection : You can use expandable sections to view the complex JSON data the agent is processing behind the scenes.
- Real-time Status : A sidebar allows you to monitor the agent’s progress as it moves from understanding your request to fetching and summarizing data
Observations and Testing
When running the web application, you should observe how the AI demonstrates Planning Intelligence and Data Processing :
- Input Flexibility : Test how it recognizes various inputs like “94129” or “Times Square” and maps them to coordinates.
- Data Translation : Observe how Claude 4.5 Sonnet identifies the most relevant information from multiple forecast periods to create a human-readable summary.
- Error Handling : Try entering misspelled city names or international locations (remembering that the NWS API only covers the US) to see how the agent provides helpful guidance rather than crashing
Source Code & Repository
You can access the full implementation of the weather_agent_cli.py and weather_agent_web.py files, along with the environment setup requirements, at the following GitHub repository here : Agentic AI Building Blocks using Amazon Bedrock
Why Use the Web Version?
The web application is particularly useful for non-technical users or for professional presentations. It provides a visual confirmation of the agent’s autonomy and reactivity, allowing you to see exactly how the “brain” (Claude) is directing the “hands” (API calls) to solve the problem
What to Observe
During the execution of the agent, you should pay close attention to how the AI handles the transition from natural language to technical execution:
- Planning Intelligence: Notice how the AI recognizes various input types, such as mapping “Seattle” to coordinates or handling ZIP codes like “90210”. Observe how it dynamically generates different API calls based on the specific location type provided.
- Data Processing: Watch how the AI converts complex JSON data often containing multiple forecast periods into a human-readable summary. It must identify the most relevant information and add appropriate context or recommendations.
- Error Handling: Test the agent’s resilience by entering invalid locations, misspelled city names, or international locations. Observe how it provides helpful guidance rather than failing, noting that the National Weather Service API is limited to US locations
Comparing CLI vs. Web Experience
While both versions use the identical agentic AI logic — relying on the same Claude 4.5 Sonnet reasoning and NWS API integration — they offer distinct advantages depending on the user:
| Feature | Command-Line Version (CLI) | Web Version (Streamlit) |
|---|---|---|
| Primary Audience | Developers and technical users. | Non-technical users or professional presentations. |
| Key Strength | Direct, focused interaction ideal for automation and scripting. | Visual, interactive experience with a polished presentation. |
| Visibility | Shows the raw workflow steps clearly in the terminal. | Provides real-time progress indicators and a sidebar to monitor status. |
| Visualization | Text-based output of the process. | Step-by-step visualization of the planning, execution, and analysis phases. |
| Inspection | Best for seeing the immediate code execution. | Includes expandable sections to inspect raw API responses. |
Ultimately, the choice between them depends on whether you prioritize developer efficiency and automation (CLI) or visual clarity and user-friendly status tracking (Web).
Key Takeaways
- Definition of Agentic AI: The fundamental shift in AI is moving from a “Question → Answer” model (smart encyclopedias) to a “Problem → Plan → Action → Result” workflow. Truly agentic systems are defined by autonomy (making independent decisions), reactivity (responding to environmental changes and errors), and proactivity (taking initiative through multi-step planning).
- The AI as a Reasoning Engine: Instead of just generating text, the AI (specifically Claude 4.5 Sonnet) acts as a reasoning engine. It dynamically interprets descriptive user input, such as “largest city in California,” maps it to precise coordinates, and constructs the necessary API URLs rather than relying on hardcoded logic.
- The Agentic Workflow: A successful agent follows a reusable four-step pattern: Planning (analyzing input and strategizing), Action (executing technical tasks like API calls), Processing (analyzing raw data for insights), and Response (presenting results in a human-friendly format).
- Building without Abstractions: Sophisticated agents can be built using pure Python and the AWS SDK (boto3) without the need for complex frameworks. This “from-scratch” approach helps developers understand every component, from establishing a Bedrock connection to creating an error-resilient architecture that handles network timeouts and invalid data.
- Versatile Real-World Applications: The patterns used to build a weather assistant such as coordinate resolution and sequential API execution are directly applicable to other fields like travel planning, emergency management, market analysis, and agriculture
Conclusion
The workshop concludes that the future of artificial intelligence is not just about chatbots, but about agents that can take meaningful actions in the world. By moving beyond static responses and integrating real-time data with AI reasoning, developers can create systems that provide genuine value across any domain. The core principle for success in this new landscape is to start simple and iterate quickly , using foundational building blocks to scale toward more complex multi-agent systems and advanced production environments.
Resources
- Amazon Bedrock Documentation
- Claude Model Parameters
- National Weather Service API
- Streamlit Documentation
A special thanks to BeSA (Become a Solutions Architect) for providing a free mentoring platform that enabled me to gain practical, hands-on experience with Generative AI through this workshop. BeSA’s guidance and community support played a key role in helping me strengthen my GenAI and cloud skills.
If you’d like to explore another hands-on agentic AI example using Amazon Bedrock, check out the AWS workshop 1 article. You can read it here:🔗 Building an Intelligent Shopping Assistant with Amazon Bedrock Agents .
Thank you for taking the time to read my article! If you found it helpful, feel free to like, share, and drop your thoughts in the comments; I’d love to hear from you.
If you want to connect or dive deeper into cloud, AI and DevOps, feel free to follow me on my socials:
👨💻 DEV Community
🛡️Medium
🐙 GitHub

Top comments (1)
The sequential Points API to Forecast API pattern is clean. One thing we learned building multi-step agents: adding a retry with backoff between the chained calls prevents the second call from failing when the first returns stale grid data.