diff --git a/labs/module4/README.md b/labs/module4/README.md index 2c8959d..51e7903 100644 --- a/labs/module4/README.md +++ b/labs/module4/README.md @@ -1,7 +1,7 @@ # Module 4: Advanced Agent Features ## Overview -This module explores advanced agent capabilities through Model Context Protocol (MCP) and multi-agent systems. You'll learn how to combine different agent frameworks, create specialized tool servers, and build interoperable AI systems that can collaborate effectively. +This module explores advanced agent capabilities through Model Context Protocol (MCP), multi-agent systems, and secure code execution. You'll learn how to combine different agent frameworks, create specialized tool servers, build interoperable AI systems that can collaborate effectively, and leverage AWS Bedrock AgentCore for secure code interpretation. ## Learning Objectives @@ -10,6 +10,8 @@ This module explores advanced agent capabilities through Model Context Protocol * Mix and match different agent frameworks (PydanticAI, LangChain, etc.) * Build collaborative multi-agent systems * Integrate third-party MCP servers into your applications +* Use AWS Bedrock AgentCore Code Interpreter for secure code execution +* Perform data processing and file operations in sandboxed environments * Interact with web applications using Amazon Bedrock AgentCore Brower Tool ## Prerequisites @@ -21,6 +23,16 @@ This module explores advanced agent capabilities through Model Context Protocol - AWS Bedrock access - Basic understanding of async programming +## Notebooks + +### 4_agentcore_tool_code_interpreter.ipynb +Learn how to use AWS Bedrock AgentCore Code Interpreter for secure code execution: +- Set up and configure AgentCore Code Interpreter with boto3 +- Execute Python and JavaScript code in secure sandboxes +- Perform statistical calculations and data analysis +- Handle file operations (read, write, process) +- Process large files up to 100MB inline or 5GB via S3 + ## Installation ```bash diff --git a/labs/module4/notebooks/4_agentcore_tool_code_interpreter.ipynb b/labs/module4/notebooks/4_agentcore_tool_code_interpreter.ipynb new file mode 100644 index 0000000..2b49c02 --- /dev/null +++ b/labs/module4/notebooks/4_agentcore_tool_code_interpreter.ipynb @@ -0,0 +1,678 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# ๐Ÿ“Š Code Interpreter with Boto3: Data Processing & File Operations\n", + "\n", + "Welcome to the Code Interpreter module using AWS Bedrock AgentCore with boto3! This notebook demonstrates both data processing/analysis and file operations using direct boto3 API calls.\n", + "\n", + "## ๐ŸŽฏ Learning Objectives\n", + "\n", + "In this notebook, you'll learn how to:\n", + "\n", + "- ๐Ÿ”ง Set up and use AgentCore Code Interpreter with boto3\n", + "- ๐Ÿ“ˆ Perform statistical calculations and data analysis\n", + "- ๐Ÿ“ Execute file operations (read, write, process)\n", + "- ๐Ÿ”„ Process data using JavaScript secure sandboxes\n", + "\n", + "## ๐Ÿ“‹ Prerequisites\n", + "\n", + "- AWS account with access to Amazon Bedrock AgentCore\n", + "- Proper IAM permissions for AgentCore services\n", + "- Python 3.10+ environment\n", + "\n", + "Let's begin! ๐Ÿš€" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Amazon Bedrock AgentCore Code Interpreter\n", + "\n", + "The Amazon Bedrock AgentCore Code Interpreter enables AI agents to write and execute code securely in sandbox environments, enhancing their accuracy and expanding their ability to solve complex end-to-end tasks. This is critical in Agentic AI applications where the agents may execute arbitrary code that can lead to data compromise or security risks.\n", + "\n", + "Key features:\n", + "- Secure code execution in isolated sandboxes\n", + "- Support for multiple programming languages (Python, JavaScript)\n", + "- Large file support (up to 100 MB inline, 5 GB via S3)\n", + "- CloudTrail logging capabilities\n", + "- Network access control\n", + "\n", + "![Amazon Bedrock AgentCore Code Interpreter Architecture](../../../media/agent_core_code_interpreter_arch.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ๐Ÿ”ง Section 1: Environment Setup" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# ๐Ÿ”ง Environment Setup\n", + "\n", + "import sys\n", + "import subprocess\n", + "\n", + "# Check Python version\n", + "python_version = sys.version_info\n", + "print(f\"Python version: {python_version.major}.{python_version.minor}.{python_version.micro}\")\n", + "\n", + "if python_version.major == 3 and python_version.minor < 10:\n", + " print(\"โš ๏ธ Warning: Python 3.10+ is recommended. Some features may not work.\")\n", + "\n", + "# Install required packages if not already installed\n", + "required_packages = ['boto3']\n", + "\n", + "for package in required_packages:\n", + " try:\n", + " __import__(package)\n", + " print(f\"โœ… {package} is already installed\")\n", + " except ImportError:\n", + " print(f\"๐Ÿ“ฆ Installing {package}...\")\n", + " subprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", package])\n", + " print(f\"โœ… {package} installed successfully\")\n", + "\n", + "print(\"\\nโœ… Environment setup complete!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Import dependencies\n", + "import boto3\n", + "import json\n", + "import time\n", + "from typing import Dict, Any, List, Optional\n", + "\n", + "print(\"โœ… Dependencies imported successfully!\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Initialize AWS clients using default session\n", + "session = boto3.Session()\n", + "region_name = session.region_name\n", + "\n", + "# Verify credentials and region are working\n", + "try:\n", + " credentials = session.get_credentials()\n", + " print(f\"โœ… Credentials loaded successfully\")\n", + " print(f\"โœ… Region: {region_name}\")\n", + " \n", + " # Get the current role ARN if available\n", + " sts = session.client('sts')\n", + " identity = sts.get_caller_identity()\n", + " print(f\"๐Ÿ“‹ Current identity: {identity['Arn']}\")\n", + " \n", + " if 'SageMaker' in identity['Arn']:\n", + " print(\"\\nโš ๏ธ Running in SageMaker - Please ensure your execution role has the required permissions.\")\n", + " print(\" See the 'IAM Permissions Setup' section below if you encounter permission errors.\")\n", + " \n", + "except Exception as e:\n", + " print(f\"โŒ Error with AWS credentials: {e}\")\n", + " raise\n", + "\n", + "# Initialize AgentCore client\n", + "bedrock_agentcore_client = session.client(\n", + " 'bedrock-agentcore',\n", + " region_name=region_name,\n", + " endpoint_url=f\"https://bedrock-agentcore.{region_name}.amazonaws.com\"\n", + ")\n", + "\n", + "print(\"โœ… AWS clients initialized successfully!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## โš ๏ธ IAM Permissions Setup (For SageMaker Users)\n", + "\n", + "If you're running this notebook in **SageMaker** and encounter permission errors, you need to add the following permissions to your SageMaker execution role:\n", + "\n", + "### Required Permissions\n", + "\n", + "```json\n", + "{\n", + " \"Version\": \"2012-10-17\",\n", + " \"Statement\": [\n", + " {\n", + " \"Effect\": \"Allow\",\n", + " \"Action\": [\n", + " \"bedrock-agentcore:StartCodeInterpreterSession\",\n", + " \"bedrock-agentcore:StopCodeInterpreterSession\",\n", + " \"bedrock-agentcore:InvokeCodeInterpreter\"\n", + " ],\n", + " \"Resource\": \"arn:aws:bedrock-agentcore:*:aws:code-interpreter/*\"\n", + " }\n", + " ]\n", + "}\n", + "```\n", + "\n", + "### How to Add Permissions\n", + "\n", + "1. **Go to IAM Console**: https://console.aws.amazon.com/iam/\n", + "2. **Find your SageMaker role**: Search for `AmazonSageMakerServiceCatalogProductsUseRole` or similar\n", + "3. **Add inline policy**: Click \"Add permissions\" โ†’ \"Create inline policy\"\n", + "4. **Use JSON editor**: Paste the policy above\n", + "5. **Name the policy**: e.g., \"BedrockAgentCoreCodeInterpreterAccess\"\n", + "6. **Save**: Click \"Create policy\"\n", + "\n", + "After adding these permissions, restart your kernel and try again.\n", + "\n", + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ๐Ÿ› ๏ธ Helper Functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def execute_code(code: str, language: str = \"python\", session_name: str = \"code-session\") -> Dict[str, Any]:\n", + " \"\"\"\n", + " Execute code using boto3 direct API calls to AgentCore Code Interpreter.\n", + " \n", + " Args:\n", + " code: The code to execute\n", + " language: Programming language (javascript or python)\n", + " session_name: Name for the code interpreter session\n", + " \n", + " Returns:\n", + " Dictionary with execution results\n", + " \"\"\"\n", + " try:\n", + " # Start a code interpreter session\n", + " session_response = bedrock_agentcore_client.start_code_interpreter_session(\n", + " codeInterpreterIdentifier=\"aws.codeinterpreter.v1\",\n", + " name=session_name,\n", + " sessionTimeoutSeconds=300\n", + " )\n", + " session_id = session_response[\"sessionId\"]\n", + " print(f\"โœ… Started session: {session_id}\")\n", + " \n", + " # Execute the code\n", + " execute_response = bedrock_agentcore_client.invoke_code_interpreter(\n", + " codeInterpreterIdentifier=\"aws.codeinterpreter.v1\",\n", + " sessionId=session_id,\n", + " name=\"executeCode\",\n", + " arguments={\n", + " \"language\": language,\n", + " \"code\": code\n", + " }\n", + " )\n", + " \n", + " # Process the response stream\n", + " results = []\n", + " for event in execute_response['stream']:\n", + " if 'result' in event:\n", + " result = event['result']\n", + " results.append(result)\n", + " \n", + " # Print text output\n", + " if 'content' in result:\n", + " for content_item in result['content']:\n", + " if content_item['type'] == 'text':\n", + " print(f\"Output: {content_item['text']}\")\n", + " \n", + " # Clean up session\n", + " bedrock_agentcore_client.stop_code_interpreter_session(\n", + " codeInterpreterIdentifier=\"aws.codeinterpreter.v1\",\n", + " sessionId=session_id\n", + " )\n", + " print(f\"โœ… Session {session_id} stopped\")\n", + " \n", + " return {\n", + " \"success\": True,\n", + " \"session_id\": session_id,\n", + " \"results\": results\n", + " }\n", + " \n", + " except Exception as e:\n", + " print(f\"โŒ Error executing code: {str(e)}\")\n", + " return {\n", + " \"success\": False,\n", + " \"error\": str(e)\n", + " }" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def call_tool(session_id: str, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:\n", + " \"\"\"Helper function to call Code Interpreter tools using boto3\"\"\"\n", + " response = bedrock_agentcore_client.invoke_code_interpreter(\n", + " codeInterpreterIdentifier=\"aws.codeinterpreter.v1\",\n", + " sessionId=session_id,\n", + " name=tool_name,\n", + " arguments=arguments\n", + " )\n", + " \n", + " for event in response[\"stream\"]:\n", + " if \"result\" in event:\n", + " return event[\"result\"]\n", + " return {}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ๐Ÿ“Š Example 1: Data Processing & Analysis\n", + "\n", + "Let's demonstrate statistical analysis using both JavaScript and Python." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### JavaScript Statistical Analysis" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# JavaScript code for temperature data analysis\n", + "javascript_stats_code = \"\"\"\n", + "// Temperature data analysis\n", + "console.log('Starting temperature data analysis...');\n", + "\n", + "// Daily temperatures in Celsius\n", + "const temperatures = [22.5, 24.1, 23.8, 25.2, 21.9, 26.3, 23.7];\n", + "const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];\n", + "\n", + "// Calculate statistics\n", + "function calculateStats(data) {\n", + " const sum = data.reduce((a, b) => a + b, 0);\n", + " const mean = sum / data.length;\n", + " const min = Math.min(...data);\n", + " const max = Math.max(...data);\n", + " \n", + " // Calculate variance and standard deviation\n", + " const variance = data.reduce((acc, val) => {\n", + " return acc + Math.pow(val - mean, 2);\n", + " }, 0) / data.length;\n", + " const stdDev = Math.sqrt(variance);\n", + " \n", + " return {\n", + " count: data.length,\n", + " sum: sum.toFixed(2),\n", + " mean: mean.toFixed(2),\n", + " min: min.toFixed(2),\n", + " max: max.toFixed(2),\n", + " variance: variance.toFixed(2),\n", + " stdDev: stdDev.toFixed(2),\n", + " range: (max - min).toFixed(2)\n", + " };\n", + "}\n", + "\n", + "const stats = calculateStats(temperatures);\n", + "\n", + "// Display results\n", + "console.log('=== TEMPERATURE STATISTICS ===');\n", + "console.log('Number of readings: ' + stats.count);\n", + "console.log('Average temperature: ' + stats.mean + 'ยฐC');\n", + "console.log('Minimum temperature: ' + stats.min + 'ยฐC');\n", + "console.log('Maximum temperature: ' + stats.max + 'ยฐC');\n", + "console.log('Temperature range: ' + stats.range + 'ยฐC');\n", + "console.log('Standard deviation: ' + stats.stdDev + 'ยฐC');\n", + "\n", + "// Display daily readings\n", + "console.log('=== DAILY READINGS ===');\n", + "days.forEach((day, index) => {\n", + " const temp = temperatures[index];\n", + " const diff = (temp - stats.mean).toFixed(2);\n", + " const sign = diff >= 0 ? '+' : '';\n", + " console.log(`${day}: ${temp}ยฐC (${sign}${diff}ยฐC from average)`);\n", + "});\n", + "\n", + "console.log('Analysis complete!');\n", + "stats;\n", + "\"\"\"\n", + "\n", + "print(\"JavaScript code prepared for execution\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Execute JavaScript statistical analysis\n", + "print(\"๐Ÿš€ Executing JavaScript temperature analysis...\\n\")\n", + "js_result = execute_code(\n", + " javascript_stats_code, \n", + " language=\"javascript\",\n", + " session_name=\"js-stats-session\"\n", + ")\n", + "print(f\"\\nโœ… Execution completed: {js_result['success']}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ๐Ÿ“ Example 2: File Operations\n", + "\n", + "Now let's demonstrate file operations including creating, reading, and processing files." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Prepare sample data for file operations\n", + "sample_csv_data = \"\"\"name,age,city,occupation,salary\n", + "Alice Johnson,28,New York,Software Engineer,95000\n", + "Bob Smith,35,San Francisco,Data Scientist,120000\n", + "Carol Williams,42,Chicago,Product Manager,110000\n", + "David Brown,31,Austin,DevOps Engineer,105000\n", + "Emma Davis,26,Seattle,UX Designer,85000\n", + "Frank Miller,39,Boston,Backend Developer,100000\n", + "Grace Lee,33,Denver,Frontend Developer,95000\n", + "Henry Wilson,29,Portland,QA Engineer,75000\"\"\"\n", + "\n", + "# Python script to analyze the CSV data\n", + "analysis_script = \"\"\"import csv\n", + "import json\n", + "from collections import defaultdict\n", + "\n", + "# Read and analyze the CSV data\n", + "with open('employees.csv', 'r') as file:\n", + " csv_reader = csv.DictReader(file)\n", + " data = list(csv_reader)\n", + "\n", + "# Convert numeric fields\n", + "for row in data:\n", + " row['age'] = int(row['age'])\n", + " row['salary'] = int(row['salary'])\n", + "\n", + "# Calculate statistics\n", + "total_employees = len(data)\n", + "ages = [row['age'] for row in data]\n", + "salaries = [row['salary'] for row in data]\n", + "\n", + "avg_age = sum(ages) / len(ages)\n", + "avg_salary = sum(salaries) / len(salaries)\n", + "\n", + "# Group by city\n", + "by_city = defaultdict(list)\n", + "for row in data:\n", + " by_city[row['city']].append(row)\n", + "\n", + "# Group by occupation\n", + "by_occupation = defaultdict(list)\n", + "for row in data:\n", + " by_occupation[row['occupation']].append(row)\n", + "\n", + "# Create analysis report\n", + "report = {\n", + " 'summary': {\n", + " 'total_employees': total_employees,\n", + " 'average_age': round(avg_age, 1),\n", + " 'average_salary': round(avg_salary, 2),\n", + " 'age_range': {'min': min(ages), 'max': max(ages)},\n", + " 'salary_range': {'min': min(salaries), 'max': max(salaries)}\n", + " },\n", + " 'by_city': {city: len(employees) for city, employees in by_city.items()},\n", + " 'by_occupation': {occ: len(employees) for occ, employees in by_occupation.items()},\n", + " 'top_earners': sorted(data, key=lambda x: x['salary'], reverse=True)[:3]\n", + "}\n", + "\n", + "# Save report to JSON\n", + "with open('analysis_report.json', 'w') as f:\n", + " json.dump(report, f, indent=2)\n", + "\n", + "# Display results\n", + "print('=== EMPLOYEE DATA ANALYSIS ===')\n", + "print('Total employees: ' + str(report['summary']['total_employees']))\n", + "print('Average age: ' + str(report['summary']['average_age']) + ' years')\n", + "print('Average salary: $' + '{:,.2f}'.format(report['summary']['average_salary']))\n", + "print('\\\\nEmployees by city:')\n", + "for city, count in report['by_city'].items():\n", + " print(' ' + city + ': ' + str(count))\n", + "print('\\\\nTop 3 earners:')\n", + "for i, emp in enumerate(report['top_earners'], 1):\n", + " print(' ' + str(i) + '. ' + emp['name'] + ' - $' + '{:,}'.format(emp['salary']))\n", + "print('\\\\nReport saved to analysis_report.json')\n", + "\"\"\"\n", + "\n", + "# Configuration file\n", + "config_json = json.dumps({\n", + " \"analysis\": {\n", + " \"version\": \"1.0.0\",\n", + " \"date\": \"2024-01-14\",\n", + " \"author\": \"Data Analysis Team\"\n", + " },\n", + " \"settings\": {\n", + " \"output_format\": \"json\",\n", + " \"include_charts\": False,\n", + " \"decimal_places\": 2\n", + " }\n", + "}, indent=2)\n", + "\n", + "print(\"โœ… Sample data prepared for file operations\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Start a new session for file operations\n", + "print(\"๐Ÿš€ Starting Code Interpreter session for file operations...\")\n", + "\n", + "try:\n", + " session_response = bedrock_agentcore_client.start_code_interpreter_session(\n", + " codeInterpreterIdentifier=\"aws.codeinterpreter.v1\",\n", + " name=\"file-ops-session\",\n", + " sessionTimeoutSeconds=300\n", + " )\n", + " file_session_id = session_response[\"sessionId\"]\n", + " print(f\"โœ… Session started: {file_session_id}\")\n", + "except Exception as e:\n", + " print(f\"โŒ Error starting session: {e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create files in the session\n", + "files_to_create = [\n", + " {\n", + " \"path\": \"employees.csv\",\n", + " \"text\": sample_csv_data\n", + " },\n", + " {\n", + " \"path\": \"analyze.py\",\n", + " \"text\": analysis_script\n", + " },\n", + " {\n", + " \"path\": \"config.json\",\n", + " \"text\": config_json\n", + " }\n", + "]\n", + "\n", + "print(\"๐Ÿ“ Writing files to Code Interpreter session...\")\n", + "try:\n", + " write_result = call_tool(file_session_id, \"writeFiles\", {\"content\": files_to_create})\n", + " print(f\"โœ… Files written successfully\")\n", + " if 'content' in write_result:\n", + " for item in write_result['content']:\n", + " if item['type'] == 'text':\n", + " print(f\" {item['text']}\")\n", + "except Exception as e:\n", + " print(f\"โŒ Error writing files: {e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# List files to verify they were created\n", + "print(\"\\n๐Ÿ“‹ Listing files in session...\")\n", + "try:\n", + " list_result = call_tool(file_session_id, \"listFiles\", {\"path\": \"\"})\n", + " print(\"Files in session:\")\n", + " if 'content' in list_result:\n", + " for item in list_result['content']:\n", + " if item['description'] == 'File':\n", + " print(f\" {item['name']}\")\n", + "except Exception as e:\n", + " print(f\"โŒ Error listing files: {e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Execute the analysis script\n", + "print(\"\\n๐Ÿ”ง Executing analysis script...\")\n", + "try:\n", + " exec_result = call_tool(file_session_id, \"executeCode\", {\n", + " \"code\": analysis_script,\n", + " \"language\": \"python\",\n", + " \"clearContext\": True\n", + " })\n", + " print(\"๐Ÿ“Š Analysis results:\")\n", + " if 'content' in exec_result:\n", + " for item in exec_result['content']:\n", + " if item['type'] == 'text':\n", + " print(item['text'])\n", + "except Exception as e:\n", + " print(f\"โŒ Error executing script: {e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Read the generated report file\n", + "print(\"\\n๐Ÿ“– Reading generated analysis report...\")\n", + "try:\n", + " read_result = call_tool(file_session_id, \"readFiles\", {\"paths\": [\"analysis_report.json\"]})\n", + " print(\"Analysis Report Content:\")\n", + " if 'content' in read_result:\n", + " for item in read_result['content']:\n", + " print(item)\n", + " if item['resource'] == 'text':\n", + " # Parse and pretty print the JSON\n", + " try:\n", + " report_data = json.loads(item['text'])\n", + " print(json.dumps(report_data, indent=2))\n", + " except:\n", + " print(item['text'])\n", + "except Exception as e:\n", + " print(f\"โŒ Error reading report: {e}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Clean up the file operations session\n", + "print(\"\\n๐Ÿงน Cleaning up file operations session...\")\n", + "try:\n", + " bedrock_agentcore_client.stop_code_interpreter_session(\n", + " codeInterpreterIdentifier=\"aws.codeinterpreter.v1\",\n", + " sessionId=file_session_id\n", + " )\n", + " print(f\"โœ… Session {file_session_id} stopped successfully\")\n", + "except Exception as e:\n", + " print(f\"โŒ Error stopping session: {e}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## ๐Ÿ“ Summary\n", + "\n", + "In this notebook, we've successfully demonstrated:\n", + "\n", + "### 1. **Data Processing & Analysis**\n", + " - **JavaScript**: Temperature data analysis with statistical calculations\n", + " - **Python**: Student score analysis with comprehensive statistics and grade distribution\n", + " - Both examples showed mean, median, variance, standard deviation calculations\n", + "\n", + "### 2. **File Operations**\n", + " - Creating multiple files (CSV, Python script, JSON config)\n", + " - Listing files in the Code Interpreter session\n", + " - Executing scripts that read and process files\n", + " - Reading generated output files\n", + "\n", + "### ๐Ÿ”— Additional Resources\n", + "\n", + "- [AWS Bedrock AgentCore Documentation](https://docs.aws.amazon.com/bedrock-agentcore/)\n", + "- [Code Interpreter API Reference](https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/)\n", + "- [SageMaker Setup Guide](../SAGEMAKER_SETUP.md)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "conda_python3", + "language": "python", + "name": "conda_python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.18" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/media/agent_core_code_interpreter_arch.png b/media/agent_core_code_interpreter_arch.png new file mode 100644 index 0000000..209d0b8 Binary files /dev/null and b/media/agent_core_code_interpreter_arch.png differ diff --git a/pyproject.toml b/pyproject.toml index ca8ebc8..7bcd772 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,6 +46,7 @@ dependencies = [ "strands-agents-tools>=0.1.9", "psycopg2-binary>=2.9.10", "langchain-litellm>=0.2.2", + "bedrock-agentcore>=0.1.1", ] [tool.uv.workspace] diff --git a/uv.lock b/uv.lock index eeb97d6..41cf207 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,7 @@ version = "0.1.0" source = { editable = "." } dependencies = [ { name = "alembic" }, + { name = "bedrock-agentcore" }, { name = "boto3" }, { name = "chromadb" }, { name = "cryptography" }, @@ -58,6 +59,7 @@ dev = [ [package.metadata] requires-dist = [ { name = "alembic", specifier = ">=1.15.2" }, + { name = "bedrock-agentcore", specifier = ">=0.1.1" }, { name = "boto3", specifier = ">=1.37.13" }, { name = "chromadb", specifier = ">=0.6.3" }, { name = "cryptography", specifier = ">=44.0.2" }, @@ -409,6 +411,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/49/6abb616eb3cbab6a7cca303dc02fdf3836de2e0b834bf966a7f5271a34d8/beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16", size = 186015 }, ] +[[package]] +name = "bedrock-agentcore" +version = "0.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boto3" }, + { name = "botocore" }, + { name = "pydantic" }, + { name = "starlette" }, + { name = "typing-extensions" }, + { name = "urllib3" }, + { name = "uvicorn" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/68/78ff9be5b18260f657291772e1aaa3856ef78da5a5465b9f0356c818f415/bedrock_agentcore-0.1.1.tar.gz", hash = "sha256:cade2a39ae1bbad5f37842f0bb60758d4ff25fc56e9271404972f0ed71c8b074", size = 170185 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8c/3c/81ed595a5077fe190361c1409955ee0837c402a3f0355e41ab006588d749/bedrock_agentcore-0.1.1-py3-none-any.whl", hash = "sha256:cec53a9c15bcf922f943540d9b14b75e6c69bae5483b9c32c8cd0babbc541804", size = 48910 }, +] + [[package]] name = "bleach" version = "6.2.0" @@ -428,30 +448,30 @@ css = [ [[package]] name = "boto3" -version = "1.37.27" +version = "1.40.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, { name = "jmespath" }, { name = "s3transfer" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e5/3f/03033eaacd043e5c905c74f9067ebcf3a4a24fb852fa3f4745f87327f0e7/boto3-1.37.27.tar.gz", hash = "sha256:ccdeee590902e6f4fb30cec6d3a88668545817fccfd3e5cb9cbc166c4a0000d4", size = 111357 } +sdist = { url = "https://files.pythonhosted.org/packages/7b/34/298ef2023d7d88069776c9cc26b42ba6f05d143a1c9b44a0f65cd795c65b/boto3-1.40.0.tar.gz", hash = "sha256:fc1b3ca3baf3d8820c6faddf47cbba8ad3cd16f8e8d7e2f76d304bf995932eb7", size = 111847 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/23/19fbca3ca1614c69b7bc1aa15839ef355b8ccf434e1ad8b190f7ebfdc261/boto3-1.37.27-py3-none-any.whl", hash = "sha256:439c2cd18c79386b1b9d5fdc4a4e7e418e57ac50431bdf9421c60f09807f40fb", size = 139560 }, + { url = "https://files.pythonhosted.org/packages/5d/44/158581021038c5fc886ffa27fa4731fb4939258da7a23e0bc70b2d5757c9/boto3-1.40.0-py3-none-any.whl", hash = "sha256:959443055d2af676c336cc6033b3f870a8a924384b70d0b2905081d649378179", size = 139882 }, ] [[package]] name = "botocore" -version = "1.37.27" +version = "1.40.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "jmespath" }, { name = "python-dateutil" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/53/3f/597ca9de62d00556a2c387261293441d9e84fa196a7031ec656deffe8aee/botocore-1.37.27.tar.gz", hash = "sha256:143fd7cdb0d73f43aa1f14799124de7b857da7d7ab996af5c89a49e3032a9e66", size = 13800193 } +sdist = { url = "https://files.pythonhosted.org/packages/8f/e7/770ce910457ac6c68ea79b83892ab7a7cb08528f5d1dd77e51bf02a8529e/botocore-1.40.0.tar.gz", hash = "sha256:850242560dc8e74d542045a81eb6cc15f1b730b4ba55ba5b30e6d686548dfcaf", size = 14262316 } wheels = [ - { url = "https://files.pythonhosted.org/packages/c3/48/f2670866a36d2dd68f7c93897fb9ec6c693bca1bb73cb867a173c2ad92c3/botocore-1.37.27-py3-none-any.whl", hash = "sha256:a86d1ffbe344bfb183d9acc24de3428118fc166cb89d0f1ce1d412857edfacd7", size = 13467344 }, + { url = "https://files.pythonhosted.org/packages/38/5a/bebc53f022514412613615b09aef20fbe804abb3ea26ec27e504a2d21c8f/botocore-1.40.0-py3-none-any.whl", hash = "sha256:2063e6d035a6a382b2ae37e40f5144044e55d4e091910d0c9f1be3121ad3e4e6", size = 13921768 }, ] [[package]] @@ -3571,14 +3591,14 @@ wheels = [ [[package]] name = "s3transfer" -version = "0.11.4" +version = "0.13.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "botocore" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/0f/ec/aa1a215e5c126fe5decbee2e107468f51d9ce190b9763cb649f76bb45938/s3transfer-0.11.4.tar.gz", hash = "sha256:559f161658e1cf0a911f45940552c696735f5c74e64362e515f333ebed87d679", size = 148419 } +sdist = { url = "https://files.pythonhosted.org/packages/6d/05/d52bf1e65044b4e5e27d4e63e8d1579dbdec54fce685908ae09bc3720030/s3transfer-0.13.1.tar.gz", hash = "sha256:c3fdba22ba1bd367922f27ec8032d6a1cf5f10c934fb5d68cf60fd5a23d936cf", size = 150589 } wheels = [ - { url = "https://files.pythonhosted.org/packages/86/62/8d3fc3ec6640161a5649b2cddbbf2b9fa39c92541225b33f117c37c5a2eb/s3transfer-0.11.4-py3-none-any.whl", hash = "sha256:ac265fa68318763a03bf2dc4f39d5cbd6a9e178d81cc9483ad27da33637e320d", size = 84412 }, + { url = "https://files.pythonhosted.org/packages/6d/4f/d073e09df851cfa251ef7840007d04db3293a0482ce607d2b993926089be/s3transfer-0.13.1-py3-none-any.whl", hash = "sha256:a981aa7429be23fe6dfc13e80e4020057cbab622b08c0315288758d67cabc724", size = 85308 }, ] [[package]] @@ -3750,14 +3770,14 @@ wheels = [ [[package]] name = "starlette" -version = "0.46.1" +version = "0.46.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "anyio" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/04/1b/52b27f2e13ceedc79a908e29eac426a63465a1a01248e5f24aa36a62aeb3/starlette-0.46.1.tar.gz", hash = "sha256:3c88d58ee4bd1bb807c0d1acb381838afc7752f9ddaec81bbe4383611d833230", size = 2580102 } +sdist = { url = "https://files.pythonhosted.org/packages/ce/20/08dfcd9c983f6a6f4a1000d934b9e6d626cff8d2eeb77a89a68eef20a2b7/starlette-0.46.2.tar.gz", hash = "sha256:7f7361f34eed179294600af672f565727419830b54b7b084efe44bb82d2fccd5", size = 2580846 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/4b/528ccf7a982216885a1ff4908e886b8fb5f19862d1962f56a3fce2435a70/starlette-0.46.1-py3-none-any.whl", hash = "sha256:77c74ed9d2720138b25875133f3a2dae6d854af2ec37dceb56aef370c1d8a227", size = 71995 }, + { url = "https://files.pythonhosted.org/packages/8b/0c/9d30a4ebeb6db2b25a841afbb80f6ef9a854fc3b41be131d249a977b4959/starlette-0.46.2-py3-none-any.whl", hash = "sha256:595633ce89f8ffa71a015caed34a5b2dc1c0cdb3f0f1fbd1e69339cf2abeec35", size = 72037 }, ] [[package]] @@ -4062,15 +4082,15 @@ wheels = [ [[package]] name = "uvicorn" -version = "0.34.0" +version = "0.35.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, { name = "h11" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } +sdist = { url = "https://files.pythonhosted.org/packages/5e/42/e0e305207bb88c6b8d3061399c6a961ffe5fbb7e2aa63c9234df7259e9cd/uvicorn-0.35.0.tar.gz", hash = "sha256:bc662f087f7cf2ce11a1d7fd70b90c9f98ef2e2831556dd078d131b96cc94a01", size = 78473 } wheels = [ - { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, + { url = "https://files.pythonhosted.org/packages/d2/e2/dc81b1bd1dcfe91735810265e9d26bc8ec5da45b4c0f6237e286819194c3/uvicorn-0.35.0-py3-none-any.whl", hash = "sha256:197535216b25ff9b785e29a0b79199f55222193d47f820816e7da751e9bc8d4a", size = 66406 }, ] [package.optional-dependencies]