<?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>DEV Community: Minoru Onda</title>
    <description>The latest articles on DEV Community by Minoru Onda (@minorun365).</description>
    <link>https://dev.to/minorun365</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%2F916712%2Fb2960a2f-2bc9-439b-8f12-77dd262ed14a.jpeg</url>
      <title>DEV Community: Minoru Onda</title>
      <link>https://dev.to/minorun365</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/minorun365"/>
    <language>en</language>
    <item>
      <title>Amazon Bedrock Agents "PowerPoint Generator" Hands-On!</title>
      <dc:creator>Minoru Onda</dc:creator>
      <pubDate>Thu, 20 Mar 2025 07:44:03 +0000</pubDate>
      <link>https://dev.to/minorun365/amazon-bedrock-agents-powerpoint-generator-hands-on-45ie</link>
      <guid>https://dev.to/minorun365/amazon-bedrock-agents-powerpoint-generator-hands-on-45ie</guid>
      <description>&lt;h1&gt;
  
  
  Overview of this Hands-on Workshop
&lt;/h1&gt;

&lt;p&gt;The generative AI boom shows no signs of slowing down, but many of you may have already experimented enough with RAG systems. The next trend appears to be "AI agents" that can automatically complete tasks on behalf of humans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://xtech.nikkei.com/atcl/nxt/column/18/00001/09497/" rel="noopener noreferrer"&gt;https://xtech.nikkei.com/atcl/nxt/column/18/00001/09497/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS cloud's generative AI service "Amazon Bedrock" includes a managed service called &lt;strong&gt;"Agents for Amazon Bedrock"&lt;/strong&gt; that makes it easy to create such agents.&lt;/p&gt;

&lt;p&gt;With this service, you can create intelligent agents just by clicking through the AWS Management Console GUI, without having to write extensive Python code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Application We'll Build
&lt;/h3&gt;

&lt;p&gt;When a user requests "create a document about xxx," the agent will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perform web searches to gather information&lt;/li&gt;
&lt;li&gt;Create a PowerPoint presentation and store it in S3, generating a signed URL&lt;/li&gt;
&lt;li&gt;Send the URL to the user via email&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The process happens automatically. If there are any questions, the agent will ask the user for clarification, and the AI will flexibly adjust the next actions based on the results of each step (for example, if email delivery fails, it will display the results on the chat screen).&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%2F0exenbwejz2yz25f837o.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%2F0exenbwejz2yz25f837o.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture
&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%2F5sxozkbvoymnj2j5mpls.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%2F5sxozkbvoymnj2j5mpls.png" alt="Screenshot 2024-08-27 19.25.51.png" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We were previously using DuckDuckGo for web searches as it didn't require an API key, but due to recent rate limiting issues, we've updated the instructions to use Tavily instead.&lt;/p&gt;

&lt;p&gt;Although not included in this workshop, you can also combine this with the "Knowledge Base" feature to implement RAG for searching internal company documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Bedrock?
&lt;/h3&gt;

&lt;p&gt;It's an AWS service that allows you to use various AI models as APIs in a serverless manner.&lt;br&gt;
For those interested, I've prepared an overview document:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://speakerdeck.com/minorun365/awsnosheng-cheng-aisabisu-amazon-bedrockru-men-2025nian-1yue-ban" rel="noopener noreferrer"&gt;https://speakerdeck.com/minorun365/awsnosheng-cheng-aisabisu-amazon-bedrockru-men-2025nian-1yue-ban&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Hands-on Instructions
&lt;/h1&gt;

&lt;p&gt;You can complete this workshop with just a web browser.&lt;br&gt;
Since everything is built using serverless architecture, the cost should be minimal.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Create an AWS Account
&lt;/h2&gt;

&lt;p&gt;Create a new AWS account by following the instructions at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/jp/register-flow/" rel="noopener noreferrer"&gt;https://aws.amazon.com/jp/register-flow/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating your account, sign in to the AWS Management Console using the URL below:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://console.aws.amazon.com" rel="noopener noreferrer"&gt;https://console.aws.amazon.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once signed in, switch your region to "Oregon" in the top right.&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%2Fwcknc4pto7o5g56d8fom.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%2Fwcknc4pto7o5g56d8fom.png" alt="Screenshot 2024-08-25 14.01.56.png" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this workshop, we'll only use the Oregon region (as it has the most lenient model usage quota restrictions for Bedrock).&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Bedrock Configuration
&lt;/h2&gt;

&lt;p&gt;Now let's set up the generative AI service.&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%2Fkic1qk98uv7trvqrbuyy.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%2Fkic1qk98uv7trvqrbuyy.png" alt="Screenshot 2024-08-28 0.50.44.png" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Type &lt;code&gt;bedrock&lt;/code&gt; in the search box at the top of the Management Console to navigate to the Amazon Bedrock console.&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%2Ftxktqw2hwcwsnlp9af68.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%2Ftxktqw2hwcwsnlp9af68.png" alt="Screenshot 2024-08-27 20.01.05.png" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Enable Model Access
&lt;/h3&gt;

&lt;p&gt;From "Model access" in the bottom left, let's enable Anthropic's Claude.&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%2Flmmfgryfds0ctl5oo41u.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%2Flmmfgryfds0ctl5oo41u.png" alt="Screenshot 2024-08-25 14.05.18.png" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Enable specific models" and check &lt;code&gt;Anthropic &amp;gt; Claude 3.5 Sonnet v2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You'll be asked to declare your intended use. Fill in the following basic information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Company name: Your company name&lt;/li&gt;
&lt;li&gt;Company website URL: Your company's website&lt;/li&gt;
&lt;li&gt;Industry: Your company's industry&lt;/li&gt;
&lt;li&gt;Target users: &lt;code&gt;Internal employees&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use case description: &lt;code&gt;Personal testing&lt;/code&gt; or similar&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%2F2hf9icgfu907ig3r8aq9.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%2F2hf9icgfu907ig3r8aq9.png" alt="Screenshot 2024-08-27 19.31.39.png" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After completion, the model will be enabled in 1-2 minutes. You can proceed to the next step without waiting.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create an Agent
&lt;/h3&gt;

&lt;p&gt;Next, go to "Agents &amp;gt; Create agent".&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%2Fqeplhqstftetelqcfcxe.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%2Fqeplhqstftetelqcfcxe.png" alt="Screenshot 2024-08-25 14.09.34.png" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keep the default agent name and click "Create".&lt;/p&gt;

&lt;p&gt;The agent builder screen will open. Configure it as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select model: Anthropic &amp;gt; Claude 3.5 Sonnet v2 &amp;gt; US Claude 3.5 Sonnet v2 (select the inference profile, not on-demand)&lt;/li&gt;
&lt;li&gt;Instructions for the agent:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Based on user requests, formulate queries to perform web searches and create PowerPoint presentations summarizing your research.
- Create at least 6 slides, with each slide having a clear heading and multiple bullet points of content.
- Send the slide URL to the user via email.
- Once all processes are complete, inform the user that the email has been sent.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Additional settings

&lt;ul&gt;
&lt;li&gt;User input: Enabled&lt;/li&gt;
&lt;/ul&gt;
&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%2Fxw92ybzqx0q9xmuzntn0.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%2Fxw92ybzqx0q9xmuzntn0.png" alt="Screenshot 2024-08-27 19.36.06.png" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After configuring these settings, click "Save" at the top of the screen.&lt;/p&gt;
&lt;h3&gt;
  
  
  Create Action Groups
&lt;/h3&gt;

&lt;p&gt;In Bedrock agents, tasks that the AI can execute are defined as "action groups." We'll create three action groups: "Web Search," "Slide Creation," and "Email Sending."&lt;/p&gt;

&lt;p&gt;Click the "Add" button in the action groups section at the bottom of the agent builder screen.&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%2Fkp59vbpiz5vd1aonjd7r.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%2Fkp59vbpiz5vd1aonjd7r.png" alt="Screenshot 2024-08-25 14.26.17.png" width="800" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create the following three action groups:&lt;/p&gt;
&lt;h4&gt;
  
  
  Action Group (First)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Action group name: search-web&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Performs a web search with the given query and returns the results.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Action group function 1

&lt;ul&gt;
&lt;li&gt;Name: search-web&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Performs a web search with the given query and returns the results.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Parameters: As follows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;query&lt;/td&gt;
&lt;td&gt;Web search query&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After configuring these settings, leave the rest at their defaults and click "Create" in the bottom right.&lt;br&gt;
Similarly, click "Add" for action groups to create the next one.&lt;/p&gt;
&lt;h4&gt;
  
  
  Action Group (Second)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Action group name: create-pptx&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Creates a PowerPoint explanatory document in Japanese for the given topic.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Action group function 1

&lt;ul&gt;
&lt;li&gt;Name: create-pptx&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Creates a PowerPoint explanatory document in Japanese for the given topic.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Parameters: As follows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;topic&lt;/td&gt;
&lt;td&gt;Main topic of the slides&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;content&lt;/td&gt;
&lt;td&gt;Content of the slides&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After configuring these settings, leave the rest at their defaults and click "Create" in the bottom right.&lt;br&gt;
Similarly, click "Add" for action groups to create the next one.&lt;/p&gt;
&lt;h4&gt;
  
  
  Action Group (Third)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Action group name: send-email&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Sends the URL of the created PPTX file to the user via email.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Action group function 1

&lt;ul&gt;
&lt;li&gt;Name: send-email&lt;/li&gt;
&lt;li&gt;Description: &lt;code&gt;Sends the URL of the created PPTX file to the user via email.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Parameters: As follows&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;url&lt;/td&gt;
&lt;td&gt;Signed URL of the PPTX file&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;True&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After configuring these settings, leave the rest at their defaults and click "Create" in the bottom right.&lt;br&gt;
Once you've created all three action groups, they should appear in the agent builder as shown below.&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%2Fliuejsgrila2164l44ku.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%2Fliuejsgrila2164l44ku.png" alt="Screenshot 2024-08-27 19.43.57.png" width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Create an S3 Bucket
&lt;/h2&gt;

&lt;p&gt;Let's create a storage location for the PowerPoint documents that the agent will generate.&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%2Fe0cug3tw93lvkykq8sqp.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%2Fe0cug3tw93lvkykq8sqp.png" alt="Screenshot 2024-08-28 0.51.20.png" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the Amazon S3 console and create a new bucket.&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%2F7k81kevqgsfgktyru1vq.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%2F7k81kevqgsfgktyru1vq.png" alt="Screenshot 2024-08-27 19.46.34.png" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose a unique name (such as &lt;code&gt;pptx-yournickname-YYYYMMDD&lt;/code&gt;) that won't conflict with other users. All other settings can remain at their defaults.&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%2Fddu02g8fdso47p244cch.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%2Fddu02g8fdso47p244cch.png" alt="Screenshot 2024-08-27 19.47.47.png" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make a note of the S3 bucket name, as you'll need it later.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. SNS Configuration
&lt;/h2&gt;

&lt;p&gt;To send emails from Lambda, we need to configure Amazon SNS in advance.&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%2Fmxz2cufa6owslcn3lc20.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%2Fmxz2cufa6owslcn3lc20.png" alt="Screenshot 2024-08-28 0.51.56.png" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the SNS console, create a topic named &lt;code&gt;bedrock-agent&lt;/code&gt;. You can leave all other settings at their defaults.&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%2Frkl11hj2qij99nzafpi5.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%2Frkl11hj2qij99nzafpi5.png" alt="Screenshot 2024-08-25 15.40.41.png" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the topic is created, copy the "ARN" to a notepad as you'll need it later.&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%2F4f61ar8git0qrw34ocrf.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%2F4f61ar8git0qrw34ocrf.png" alt="Screenshot 2024-08-27 19.52.27.png" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, let's create a "subscription" to deliver messages that arrive at this topic.&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%2Fkvp6e1j5mce9eeipyhfa.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%2Fkvp6e1j5mce9eeipyhfa.png" alt="Screenshot 2024-08-25 15.42.19.png" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Protocol: Email&lt;/li&gt;
&lt;li&gt;Endpoint: Your email address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After configuring these settings, a confirmation email will be sent to the address you specified. Click the "Confirm subscription" link to enable notification delivery.&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%2Fe0d8inp4i2qxdachjly9.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%2Fe0d8inp4i2qxdachjly9.png" alt="Screenshot 2024-08-27 19.56.23.png" width="764" height="265"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Lambda Configuration
&lt;/h2&gt;

&lt;p&gt;Lambda functions were automatically created when we set up the Bedrock agent action groups, but the code is mostly empty, so we need to edit it.&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%2F5d4nzpjdalx5ypmqhyaj.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%2F5d4nzpjdalx5ypmqhyaj.png" alt="Screenshot 2024-08-28 0.52.26.png" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the AWS Lambda console, open "Functions," and confirm that three functions have been created in the Northern Virginia region.&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%2Ftor35h917c3uuxztoooj.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%2Ftor35h917c3uuxztoooj.png" alt="Screenshot 2024-08-27 20.03.46.png" width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Prepare Lambda Layers
&lt;/h3&gt;

&lt;p&gt;Before creating Lambda functions for each action group, let's prepare the external Python libraries needed by Lambda as "layers."&lt;/p&gt;

&lt;p&gt;First, launch CloudShell by clicking the &lt;code&gt;[&amp;gt;.]&lt;/code&gt; icon in the top right of the management console.&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%2Ft2qhw64yscdtn7e7ahrf.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%2Ft2qhw64yscdtn7e7ahrf.png" alt="Screenshot 2024-08-25 15.17.05.png" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the following commands to ZIP the two Python libraries (Tavily and python-pptx):&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```bash: CloudShell&lt;/p&gt;

&lt;h1&gt;
  
  
  Create a directory for the layer
&lt;/h1&gt;

&lt;p&gt;mkdir python&lt;/p&gt;

&lt;h1&gt;
  
  
  Install the required libraries in the created directory
&lt;/h1&gt;

&lt;p&gt;pip install tavily-python python-pptx -t python --platform manylinux2014_x86_64 --only-binary=:all:&lt;/p&gt;

&lt;h1&gt;
  
  
  Compress the installed libraries into a ZIP file
&lt;/h1&gt;

&lt;p&gt;zip -r layer.zip python&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Click "Actions &amp;gt; Download File" in the top right of CloudShell, enter `layer.zip` as the file path, and download the ZIP file to your local machine.

![Screenshot 2024-08-27 20.09.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/9903e4e0-1b48-aab1-65a4-c699007e0575.png)

Once the download is complete, you can close the CloudShell window.

### Create a Lambda Layer

First, go to "Layers &amp;gt; Create layer" and create a Lambda layer with the ZIP file we just created:

- Name: `tavily-pptx`
- Upload .zip file: Specify the downloaded ZIP file (approximately 14MB)
- Compatible architectures: x86_64
- Compatible runtimes: Python 3.9

![Screenshot 2024-08-27 20.12.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/6e4e812f-f3fc-e127-6bc1-a91aee159794.png)

Leave the other settings as they are and click "Create." It will take about 10 seconds.

### Configure Lambda Functions

Next, from the left sidebar's "Functions," we'll configure each of the three functions.

#### search-web Function

- Code source: Overwrite with the following and click "Deploy":



```py: dummy_lambda.py
import os
import json
from tavily import TavilyClient

def lambda_handler(event, context):
    # Get API key from environment variables
    tavily_api_key = os.environ.get('TAVILY_API_KEY')

    # Extract query parameter from event
    parameters = event.get('parameters', [])
    for param in parameters:
        if param.get('name') == 'query':
            query = param.get('value')
            break

    # Initialize Tavily client and execute search
    client = TavilyClient(api_key=tavily_api_key)
    search_result = client.get_search_context(
        query=query,
        search_depth="advanced",
        max_results=10
    )

    # Return success response
    return {
        'messageVersion': event['messageVersion'],
        'response': {
            'actionGroup': event['actionGroup'],
            'function': event['function'],
            'functionResponse': {
                'responseBody': {
                    'TEXT': {
                        'body': json.dumps(search_result, ensure_ascii=False)
                    }
                }
            }
        }
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F5n11sydlwmz8ui4bedvd.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%2F5n11sydlwmz8ui4bedvd.png" alt="Screenshot 2024-08-27 20.28.31.png" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then scroll down and configure the following settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runtime settings: Click "Edit"

&lt;ul&gt;
&lt;li&gt;Runtime: Python 3.9&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Layers: Click "Add a layer"

&lt;ul&gt;
&lt;li&gt;Custom layers: tavily-pptx&lt;/li&gt;
&lt;li&gt;Version: 1&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Next, configure the following from the "Configuration" tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;General configuration: Click "Edit"

&lt;ul&gt;
&lt;li&gt;Timeout: 0 minutes 30 seconds&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Environment variables: Click "Edit"

&lt;ul&gt;
&lt;li&gt;Key: &lt;code&gt;TAVILY_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: Sign up at the following site and copy your API key&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://tavily.com/" rel="noopener noreferrer"&gt;https://tavily.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tavily is a web search service specialized for LLMs. Remarkably, you can execute up to 1,000 search API calls per month with the free plan.&lt;/p&gt;

&lt;p&gt;For this simple workshop, we're setting the API key as an environment variable, but for production use, please utilize AWS Secrets Manager or similar services for secure operations.&lt;/p&gt;

&lt;p&gt;Once completed, find the next function and proceed with the following configuration.&lt;/p&gt;

&lt;h4&gt;
  
  
  create-pptx Function
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Code source: Overwrite with the following and click "Deploy":
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;```py: dummy_lambda.py&lt;br&gt;
import os&lt;br&gt;
import json&lt;br&gt;
import boto3&lt;br&gt;
from pptx import Presentation&lt;br&gt;
from datetime import datetime&lt;/p&gt;
&lt;h1&gt;
  
  
  Get S3 bucket name from environment variables
&lt;/h1&gt;

&lt;p&gt;S3_BUCKET_NAME = os.getenv("S3_BUCKET_NAME")&lt;/p&gt;

&lt;p&gt;def lambda_handler(event, context):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Extract topic and content from event parameters
topic = next((item["value"] for item in event["parameters"] if item["name"] == "topic"), "")
content = next((item["value"] for item in event["parameters"] if item["name"] == "content"), "")

# Remove whitespace and split content by blank lines
content = content.strip()
slides_content = content.split('\n\n')

# Create presentation object
prs = Presentation()

# Create title slide
title_slide_layout = prs.slide_layouts[0]
slide = prs.slides.add_slide(title_slide_layout)
title = slide.shapes.title
subtitle = slide.placeholders[1]
title.text = topic
subtitle.text = f"Created: {datetime.now().strftime('%Y-%m-%d')}"

# Create content slides
for i, slide_content in enumerate(slides_content):
    content_slide_layout = prs.slide_layouts[1]
    slide = prs.slides.add_slide(content_slide_layout)
    title = slide.shapes.title
    content_shape = slide.placeholders[1]

    # Create heading and body
    lines = slide_content.split('\n')
    title.text = lines[0].lstrip('- ')
    content_shape.text = '\n'.join([line.lstrip('- ') for line in lines[1:]])

# Prepare to save file to S3
s3 = boto3.client("s3")
bucket_name = S3_BUCKET_NAME
file_name = f"{topic.replace(' ', '_')}.pptx"
file_path = f"/tmp/{file_name}"

# Upload file to S3 bucket
prs.save(file_path)
s3.upload_file(file_path, bucket_name, file_name)

# Generate signed URL for the file
url = s3.generate_presigned_url(
    'get_object',
    Params={'Bucket': bucket_name, 'Key': file_name},
    ExpiresIn=3600
)

# Return response for the agent
return {
    "messageVersion": "1.0",
    "response": {
        "actionGroup": event["actionGroup"],
        "function": event["function"],
        "functionResponse": {
            "responseBody": {
                "TEXT": {
                    "body": json.dumps(
                        {"signed_url": url}
                    )
                }
            }
        },
    },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


- Runtime settings: Click "Edit"
    - Runtime: Python 3.9
- Layers: Click "Add a layer"
    - Custom layers: tavily-pptx
    - Version: 1

Next, configure the following from the "Configuration" tab:

- General configuration: Click "Edit"
    - Timeout: 0 minutes 30 seconds
- Environment variables: Click "Edit &amp;gt; Add environment variable"
    - Key: `S3_BUCKET_NAME`
    - Value: The S3 bucket name you created earlier (check in another tab if you didn't make a note of it)
- Permissions: Click the "Role name" under execution role

![Screenshot 2024-08-27 20.36.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/5bdb6b15-a641-61df-ccc3-79180dd16d00.png)

You'll be taken to the IAM role editing screen. Click "Add permissions &amp;gt; Attach policies".

![Screenshot 2024-08-27 20.36.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/530a07be-b9b3-0c44-ec97-3bc1f9a29d6e.png)

Find and check `AmazonS3FullAccess`, then click "Add permissions".

![Screenshot 2024-08-27 20.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/1ac428e0-9e71-45e4-162b-8bd7a51c68c4.png)

Once completed, find the next function and proceed with the following configuration.

#### send-email Function

- Code source: Overwrite with the following and click "Deploy":



```py: dummy_lambda.py
import os
import json
import boto3

# Get SNS topic ARN from environment variables
SNS_TOPIC_ARN = os.environ.get("SNS_TOPIC_ARN")

def lambda_handler(event, context):
    # Get URL from event parameters
    url = event.get("parameters", [{}])[0].get("value")

    # Publish SNS message
    boto3.client("sns").publish(
        TopicArn=SNS_TOPIC_ARN, 
        Message=f"The Bedrock agent has created a slide deck. The URL is valid for 1 hour:\n{url}",
        Subject="Slide Creation Notification"
    )

    # Return response for the agent
    return {
        "messageVersion": "1.0",
        "response": {
            "actionGroup": event.get("actionGroup", "send-email"),
            "function": event.get("function", "send-email"),
            "functionResponse": {
                "responseBody": {
                    "TEXT": {
                        "body": json.dumps(
                            {
                                "message": "Email sent successfully",
                                "presentationUrl": url,
                            }
                        )
                    }
                }
            },
        },
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;Note: Runtime and layer settings are not required for this function.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next, configure the following from the "Configuration" tab:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment variables: Click "Edit"

&lt;ul&gt;
&lt;li&gt;Key: &lt;code&gt;SNS_TOPIC_ARN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: The SNS topic ARN you created earlier (check in another tab if you didn't make a note of it)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Permissions: Click the "Role name" under execution role&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%2F50axelzxgj40kh88fmsr.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%2F50axelzxgj40kh88fmsr.png" alt="Screenshot 2024-08-25 16.21.58.png" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll be taken to the IAM role editing screen. Click "Add permissions &amp;gt; Attach policies".&lt;/p&gt;

&lt;p&gt;Check &lt;code&gt;AmazonSNSFullAccess&lt;/code&gt; and click "Add permissions".&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%2Fgtcr214hfw7s1b8k05u2.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%2Fgtcr214hfw7s1b8k05u2.png" alt="Screenshot 2024-08-25 16.24.12.png" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This completes the configuration of all three functions. To summarize:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;search-web&lt;/th&gt;
&lt;th&gt;create-pptx&lt;/th&gt;
&lt;th&gt;send-email&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Python 3.9&lt;/td&gt;
&lt;td&gt;Python 3.9&lt;/td&gt;
&lt;td&gt;(No change needed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Layer&lt;/td&gt;
&lt;td&gt;tavily-pptx&lt;/td&gt;
&lt;td&gt;tavily-pptx&lt;/td&gt;
&lt;td&gt;(No change needed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timeout&lt;/td&gt;
&lt;td&gt;30 seconds&lt;/td&gt;
&lt;td&gt;30 seconds&lt;/td&gt;
&lt;td&gt;(No change needed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment Variables&lt;/td&gt;
&lt;td&gt;(No change needed)&lt;/td&gt;
&lt;td&gt;S3_BUCKET_NAME&lt;/td&gt;
&lt;td&gt;SNS_TOPIC_ARN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permissions&lt;/td&gt;
&lt;td&gt;(No change needed)&lt;/td&gt;
&lt;td&gt;Added S3&lt;/td&gt;
&lt;td&gt;Added SNS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  6. Verify Agent Operation
&lt;/h2&gt;

&lt;p&gt;Now that we've configured everything, let's test if the agent works properly before integrating it into the application.&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%2Fogd4ujj77msldfwh7f2e.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%2Fogd4ujj77msldfwh7f2e.png" alt="Screenshot 2024-08-28 0.54.43.png" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the Bedrock console, go to "Agents," and click on the agent name you created earlier.&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%2F2euoqbe7z018ndpqqqlo.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%2F2euoqbe7z018ndpqqqlo.png" alt="Screenshot 2024-08-27 20.44.00.png" width="800" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click "Prepare" in the test sidebar on the right.&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%2Fjsyjlaaqodh86sesr573.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%2Fjsyjlaaqodh86sesr573.png" alt="Screenshot 2024-08-25 16.36.39.png" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try sending &lt;code&gt;Research KAG company and create a PowerPoint&lt;/code&gt; in the chat box.&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%2F0xpmqfou3fp1780pg0oe.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%2F0xpmqfou3fp1780pg0oe.png" alt="Screenshot 2024-08-27 21.16.48.png" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After waiting 30 seconds to 1 minute, you'll get a response from the agent.&lt;br&gt;
You should also receive an email from Amazon SNS.&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%2Fws0c4lwysqms27344twc.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%2Fws0c4lwysqms27344twc.png" alt="Screenshot 2024-08-27 21.19.08.png" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking the URL allows you to download the PowerPoint!&lt;/p&gt;

&lt;p&gt;The CEO's name might be slightly off, but since the agent is performing web searches, it's able to gather quite accurate information just from the company acronym, with minimal hallucination.&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%2F11jmrzulvykr1sfjt9pq.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%2F11jmrzulvykr1sfjt9pq.png" alt="Screenshot 2024-08-27 21.20.04.png" width="800" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've confirmed it's working, create an alias by clicking "Aliases &amp;gt; Create" at the bottom of the agent screen. This is like releasing a new version of the agent.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alias name: v1&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%2Fgsskkexv96bq4oq1mgm9.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%2Fgsskkexv96bq4oq1mgm9.png" alt="Screenshot 2024-08-25 17.32.19.png" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the alias is registered, copy both the agent "ID" at the top of the screen and the "Alias ID" at the bottom of the screen to a notepad, as you'll need them later.&lt;/p&gt;

&lt;p&gt;If things aren't working properly, try the following to identify the cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the agent trace&lt;/li&gt;
&lt;li&gt;Check the log stream via "Monitoring &amp;gt; View CloudWatch logs" in Lambda&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Common issues include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the model properly enabled?&lt;/li&gt;
&lt;li&gt;Are you working in a region other than Northern Virginia?&lt;/li&gt;
&lt;li&gt;Are there any errors in the action group parameters (e.g., typos in variable names)?&lt;/li&gt;
&lt;li&gt;Did you forget to "Deploy" the Lambda function code?&lt;/li&gt;
&lt;li&gt;Is there an issue with the Lambda layer contents?&lt;/li&gt;
&lt;li&gt;Are there any gaps in Lambda runtime settings, layers, environment variables, or IAM roles?&lt;/li&gt;
&lt;li&gt;Did you click the confirmation email from SNS?&lt;/li&gt;
&lt;li&gt;Have you hit the rate limit (Service Quotas) for Claude 3.5 Sonnet v2?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that Bedrock is in high demand globally, and newly created AWS accounts have quite low initial quotas. If you hit rate limits, consider switching to a different model like Claude 3 Sonnet, or submit a request to AWS Support to increase your quota (though this can take several days).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/jp/blogs/news/generative-ai-amazon-bedrock-handling-quota-problems/" rel="noopener noreferrer"&gt;https://aws.amazon.com/jp/blogs/news/generative-ai-amazon-bedrock-handling-quota-problems/&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  7. Frontend Development
&lt;/h2&gt;

&lt;p&gt;Now that the agent is working on its own, let's integrate it into an application.&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%2Fsx3j32ey02txnpr57t74.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%2Fsx3j32ey02txnpr57t74.png" alt="Screenshot 2024-08-28 0.52.52.png" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, paste the following source code into a notepad on your computer, and replace the &lt;code&gt;XXXXXXXXXX&lt;/code&gt; in lines 8-9 with the agent ID and alias ID you created earlier.&lt;/p&gt;

&lt;p&gt;Then save it locally as &lt;code&gt;frontend.py&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```py: frontend.py&lt;br&gt;
import json&lt;br&gt;
import uuid&lt;br&gt;
import boto3&lt;br&gt;
import streamlit as st&lt;br&gt;
from botocore.exceptions import ClientError&lt;br&gt;
from botocore.eventstream import EventStreamError&lt;/p&gt;

&lt;p&gt;agent_id = "XXXXXXXXXX" # Paste your agent ID here&lt;br&gt;
agent_alias_id = "XXXXXXXXXX" # Paste your alias ID here&lt;/p&gt;

&lt;p&gt;def initialize_session():&lt;br&gt;
    """Initialize session settings"""&lt;br&gt;
    if "client" not in st.session_state:&lt;br&gt;
        st.session_state.client = boto3.client("bedrock-agent-runtime")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if "session_id" not in st.session_state:
    st.session_state.session_id = str(uuid.uuid4())

if "messages" not in st.session_state:
    st.session_state.messages = []

if "last_prompt" not in st.session_state:
    st.session_state.last_prompt = None

return st.session_state.client, st.session_state.session_id, st.session_state.messages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def display_chat_history(messages):&lt;br&gt;
    """Display chat history"""&lt;br&gt;
    st.title("PowerPoint Creator and Emailer")&lt;br&gt;
    st.text("I'll search the web, create slides, and email them to you!")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for message in messages:
    with st.chat_message(message['role']):
        st.markdown(message['text'])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def handle_trace_event(event):&lt;br&gt;
    """Process trace events"""&lt;br&gt;
    if "orchestrationTrace" not in event["trace"]["trace"]:&lt;br&gt;
        return&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trace = event["trace"]["trace"]["orchestrationTrace"]

# Display "Model Input" trace
if "modelInvocationInput" in trace:
    with st.expander("🤔 Thinking...", expanded=False):
        input_trace = trace["modelInvocationInput"]["text"]
        try:
            st.json(json.loads(input_trace))
        except:
            st.write(input_trace)

# Display "Model Output" trace
if "modelInvocationOutput" in trace:
    output_trace = trace["modelInvocationOutput"]["rawResponse"]["content"]
    with st.expander("💡 Thoughts organized", expanded=False):
        try:
            thinking = json.loads(output_trace)["content"][0]["text"]
            if thinking:
                st.write(thinking)
            else:
                st.write(json.loads(output_trace)["content"][0])
        except:
            st.write(output_trace)

# Display "Rationale" trace
if "rationale" in trace:
    with st.expander("✅ Decided on next action", expanded=True):
        st.write(trace["rationale"]["text"])

# Display "Tool Invocation" trace
if "invocationInput" in trace:
    invocation_type = trace["invocationInput"]["invocationType"]

    if invocation_type == "ACTION_GROUP":
        with st.expander("💻 Executing Lambda...", expanded=False):
            st.write(trace['invocationInput']['actionGroupInvocationInput'])

# Display "Observation" trace
if "observation" in trace:
    obs_type = trace["observation"]["type"]

    if obs_type == "ACTION_GROUP":
        with st.expander(f"💻 Retrieved Lambda execution results", expanded=False):
            st.write(trace["observation"]["actionGroupInvocationOutput"]["text"])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def invoke_bedrock_agent(client, session_id, prompt):&lt;br&gt;
    """Invoke Bedrock agent"""&lt;br&gt;
    return client.invoke_agent(&lt;br&gt;
        agentId=agent_id,&lt;br&gt;
        agentAliasId=agent_alias_id,&lt;br&gt;
        sessionId=session_id,&lt;br&gt;
        enableTrace=True,&lt;br&gt;
        inputText=prompt,&lt;br&gt;
    )&lt;/p&gt;

&lt;p&gt;def handle_agent_response(response, messages):&lt;br&gt;
    """Process agent responses"""&lt;br&gt;
    with st.chat_message("assistant"):&lt;br&gt;
        for event in response.get("completion"):&lt;br&gt;
            if "trace" in event:&lt;br&gt;
                handle_trace_event(event)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        if "chunk" in event:
            answer = event["chunk"]["bytes"].decode()
            st.write(answer)
            messages.append({"role": "assistant", "text": answer})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def show_error_popup(exeption):&lt;br&gt;
    """Display error popup"""&lt;br&gt;
    if exeption == "throttlingException":&lt;br&gt;
        error_message = "【ERROR】Bedrock model load seems high. Please wait about a minute, reload the browser, and try again 🙏 (If issues persist, consider changing models or &lt;a href="https://aws.amazon.com/jp/blogs/news/generative-ai-amazon-bedrock-handling-quota-problems/" rel="noopener noreferrer"&gt;requesting a service quota increase&lt;/a&gt;)"&lt;br&gt;
    st.error(error_message)&lt;/p&gt;

&lt;p&gt;def main():&lt;br&gt;
    """Main application processing"""&lt;br&gt;
    client, session_id, messages = initialize_session()&lt;br&gt;
    display_chat_history(messages)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if prompt := st.chat_input("Example: Research the latest Bedrock use cases in Japan"):
    messages.append({"role": "human", "text": prompt})
    with st.chat_message("user"):
        st.markdown(prompt)

    try:
        response = invoke_bedrock_agent(client, session_id, prompt)
        handle_agent_response(response, messages)

    except (EventStreamError, ClientError) as e:
        if "throttlingException" in str(e):
            show_error_popup("throttlingException")
        else:
            raise e
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    main()&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Open CloudShell again and upload this file via "Actions &amp;gt; Upload file" in the top right.

![Screenshot 2024-08-27 21.34.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/fe36590e-f1bb-bec1-6b6c-9ce070d6664b.png)

Then, run the following commands:



```bash: CloudShell
# Install Python external libraries
pip install boto3 streamlit

# Launch the Streamlit app
streamlit run frontend.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If a Streamlit access URL appears, the app has started successfully.&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%2Fr58eb2ek51611efzlqjs.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%2Fr58eb2ek51611efzlqjs.png" alt="Screenshot 2024-08-25 17.22.33.png" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click the "+" at the top of CloudShell to launch a second "us-east-1" terminal and run:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```bash: CloudShell&lt;/p&gt;

&lt;h1&gt;
  
  
  Connect to Pinggy via SSH to generate a URL accessible from the internet
&lt;/h1&gt;

&lt;p&gt;ssh -p 443 -R0:localhost:8501 a.pinggy.io&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


When a confirmation message appears, type `yes` and press Enter. This will generate a URL through the Pinggy external service that allows access to this app.

Copy the HTTP**S** URL (the one on the bottom) and access it from a separate browser tab.

![Screenshot 2024-08-25 17.26.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/e88d75ac-6b34-696a-c68b-4787a9140a06.png)

Click "Enter site" to access the Python app you uploaded. The frontend is displayed using the Streamlit framework.

![Screenshot 2025-02-04 1.58.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/a838ed7a-11a2-5bd2-83ba-fc9ddd831065.png)

Let's try using this app.

The agent's trace information is output in real-time to the Streamlit frontend.

If you encounter errors, recheck that you correctly copied the agent ID and alias ID into the Python file you uploaded.

To delete an existing file before re-uploading, you can use the following command:



```bash: CloudShell
rm frontend.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To allow access to the Python app running on CloudShell, we're using an external service called Pinggy to generate a temporary URL accessible from the internet.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: For security reasons, be careful not to share this URL with unintended third parties.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pinggy.io/" rel="noopener noreferrer"&gt;https://pinggy.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can share the URL you copied with colleagues to let them try the app.&lt;/p&gt;

&lt;p&gt;Note that CloudShell automatically stops after 20-30 minutes, requiring you to restart Streamlit and Pinggy. Also, with the free version of Pinggy, URLs are accessible for only 60 minutes.&lt;/p&gt;

&lt;p&gt;If you have time, consider experimenting with prompt tuning or Lambda modifications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modify the agent instructions&lt;/li&gt;
&lt;li&gt;Revise the action group descriptions&lt;/li&gt;
&lt;li&gt;Create a knowledge base and add RAG functionality&lt;/li&gt;
&lt;li&gt;Modify Lambda functions to add features like image generation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;

&lt;p&gt;Since we used a serverless configuration, leaving the environment as is will generate minimal charges, but to prevent security incidents, we recommend closing the AWS account (or, if not closing it, setting up MFA for the root user).&lt;/p&gt;

&lt;p&gt;If you close your account, you won't be able to create another AWS account with the same email address, so consider changing to a disposable email address beforehand.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>bedrock</category>
      <category>ai</category>
    </item>
    <item>
      <title>Let's see AWS W-A "Reliability Pillar" from SRE's view</title>
      <dc:creator>Minoru Onda</dc:creator>
      <pubDate>Wed, 30 Nov 2022 15:02:44 +0000</pubDate>
      <link>https://dev.to/aws-builders/lets-see-aws-w-a-reliability-pillar-from-sres-view-5c0h</link>
      <guid>https://dev.to/aws-builders/lets-see-aws-w-a-reliability-pillar-from-sres-view-5c0h</guid>
      <description>&lt;p&gt;&lt;em&gt;This article is the first entry for &lt;a href="https://qiita.com/advent-calendar/2022/sre" rel="noopener noreferrer"&gt;SRE advent calendar 2022 in Qiita&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I'm a member of JAWS-UG (Japan AWS User Group) and hosting the &lt;a href="https://jawsug-sre.connpass.com" rel="noopener noreferrer"&gt;SRE branch&lt;/a&gt; with cool mates.&lt;/p&gt;

&lt;p&gt;As you know SRE stands for Site Reliability Engineering, which was born in Google and widely spreading as a practice for solving problems of system operations by SWE.&lt;/p&gt;

&lt;p&gt;In AWS's W-A (Well-Architected Framework) you can also find similar philosophies to SRE's ones, especially in "Reliability Pillar." Let's dive deep into some best practices of it and get insights from SRE's point of view.&lt;/p&gt;

&lt;h1&gt;
  
  
  What's W-A?
&lt;/h1&gt;

&lt;p&gt;AWS has learned many practices for building cloud-native applications, in running huge cloud infrastructure for many years and providing these knowledges as a whitepaper. &lt;/p&gt;

&lt;p&gt;This is Well-Architected Framework (known as W-A.)&lt;br&gt;
&lt;a href="https://aws.amazon.com/architecture/well-architected/" rel="noopener noreferrer"&gt;https://aws.amazon.com/architecture/well-architected/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;W-A has 6 pillars.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Operational exellence&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Reliability&lt;/li&gt;
&lt;li&gt;Performance efficiency&lt;/li&gt;
&lt;li&gt;Cost optimization&lt;/li&gt;
&lt;li&gt;Sustainability (newly added in 2021)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What's SRE?
&lt;/h1&gt;

&lt;p&gt;Site Reliability Engineering is a practice for solving issues in operating IT systems approaching from software engineering.&lt;/p&gt;

&lt;p&gt;Google put it by publishing the first "SRE book," which consists of many lessons learned in experience of running huge infrastructure as a distributed system known as "Borg."&lt;br&gt;
&lt;a href="https://sre.google/books/" rel="noopener noreferrer"&gt;https://sre.google/books/&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  SRE's choice of best practices in Reliability Pillar
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Provide service contracts per API
&lt;/h2&gt;

&lt;p&gt;(REL03-BP03)&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_service_architecture_api_contracts.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_service_architecture_api_contracts.html&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you build your application with microservices architecture, you'd better make isolated contracts for each API. You can scale the application and teams building it, since each API has different goals, limits, and other considerations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For example, you can use Amazon API Gateway for making API-based contracts with OpenAPI specification.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we apply SRE practice in our applications, we may put SLO for them. In that case we can use this practice by setting SLO isolated in each API so that we can reduce toils for maintaining them. You don't have to sustain SLO too high when the API does not have strict requirement for running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do constant work
&lt;/h2&gt;

&lt;p&gt;(REL04-BP03)&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_prevent_interaction_failure_constant_work.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_prevent_interaction_failure_constant_work.html&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To avoid convergence in system trouble, you'd better design your application to behave as doing constant work even if in abnormal situation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For example, if your application send irregular logs to clients only when it has detected unhealthy nodes, network traffic goes busy soon and easily cause traffic storm. You have to make it send complete logs despite all the nodes are healthy.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to practices above, you should use "exponential backoff and jitter" for retries in error, not to face convergence.&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/general/latest/gr/api-retries.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/general/latest/gr/api-retries.html&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use automation when obtaining or scaling resources
&lt;/h2&gt;

&lt;p&gt;(REL07-BP01)&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_adapt_to_changes_autoscale_adapt.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_adapt_to_changes_autoscale_adapt.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The anti-patterns shown in this article are interesting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementing Auto Scaling groups for automated healing, but not implementing elasticity.&lt;/li&gt;
&lt;li&gt;Using automatic scaling to respond to large increases in traffic.&lt;/li&gt;
&lt;li&gt;Deploying highly stateful applications, eliminating the option of elasticity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To scale your workload elastically and automatically, you must make it stateless. Server nodes consisting application were loved like our pets before, however now we'd better consider them as livestocks in modern application architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy using immutable infrastructure
&lt;/h2&gt;

&lt;p&gt;(REL08-BP04)&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_tracking_change_management_immutable_infrastructure.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_tracking_change_management_immutable_infrastructure.html&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;When you update your application, do add new versions of nodes into its cluster instead of changing them in-place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use deployment strategies such as "blue/green deployment" and "canary deployment." In AWS services, Route 53 has the weighted DNS routing useful for take the strategies.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you use immutable infrastructure for your application, you can scale it easily and rollback it in short time when it is in trouble.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We can find many practices similar to SRE's ones in AWS W-A Reliability Pillar. I also recommend you to read Operational Excellence Pillar since it has many points in SRE essence, too :)&lt;/p&gt;

</description>
      <category>aws</category>
      <category>sre</category>
      <category>wellarchitected</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Try Istio, Kiali, Grafana, and Jaeger using Amazon EKS!</title>
      <dc:creator>Minoru Onda</dc:creator>
      <pubDate>Mon, 29 Aug 2022 18:00:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/try-istio-kiali-grafana-jaeger-using-amazon-eks-25ai</link>
      <guid>https://dev.to/aws-builders/try-istio-kiali-grafana-jaeger-using-amazon-eks-25ai</guid>
      <description>&lt;p&gt;Recently we don't have a day that we never hear about "service mesh" at all.&lt;br&gt;
The best way to understand misterious technology is trying it out by youeself.&lt;/p&gt;

&lt;p&gt;We are so lucky to be born in this rich age that we have Amazon EKS, yes we can try cloud native tools whenever we like!&lt;/p&gt;

&lt;p&gt;In this article I show you how to get started with Istio, one of the most popular OSS in the service mesh world.&lt;br&gt;
Don't forget to try related tools for observability in the later part here, such as Kiali, Grafana, and Jaeger.&lt;/p&gt;

&lt;p&gt;(For Japanese I have the same post here)&lt;br&gt;
&lt;a href="https://qiita.com/minorun365/items/f02eaa0786536741223a" rel="noopener noreferrer"&gt;https://qiita.com/minorun365/items/f02eaa0786536741223a&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What to prepare
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;a PC for hands-on&lt;/li&gt;
&lt;li&gt;a CLI terminal app&lt;/li&gt;
&lt;li&gt;an AWS account&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Istio &amp;amp; Kiali hands-on
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Install tools
&lt;/h3&gt;

&lt;p&gt;Install AWS CLI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Initial setup for AWS CLI and register your AWS account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-quickstart.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-quickstart.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Execute below in your terminal app.&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="nv"&gt;$ &lt;/span&gt;aws configure
AWS Access Key ID &lt;span class="o"&gt;[&lt;/span&gt;None]: &lt;span class="k"&gt;********&lt;/span&gt;
AWS Secret Access Key &lt;span class="o"&gt;[&lt;/span&gt;None]: &lt;span class="k"&gt;********&lt;/span&gt;
Default region name &lt;span class="o"&gt;[&lt;/span&gt;None]: ap-northeast-1
Default output format &lt;span class="o"&gt;[&lt;/span&gt;None]: json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can check your access key ID and a secret via AWS Management Console.&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%2F9l1bi73ef149t6qfq5re.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%2F9l1bi73ef149t6qfq5re.png" alt="スクリーンショット 2022-06-11 22.10.10.png" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install eksctl and kubectl. It's easy to use Homebrew.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eksctl.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/eksctl.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/" rel="noopener noreferrer"&gt;https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create EKS Cluster
&lt;/h3&gt;

&lt;p&gt;Execute command for creating EKS cluster via terminal.&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="nv"&gt;$ &lt;/span&gt;eksctl create cluster &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"CLUSTER NAME AS YOU LIKE"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enjoy coffee for 20 minutes so you can get a list of your woker nodes.&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="nv"&gt;$ &lt;/span&gt;kubectl get node
NAME                                                STATUS   ROLES    AGE   VERSION
ip-192-168-26-107.ap-northeast-1.compute.internal   Ready    &amp;lt;none&amp;gt;   13m   v1.22.6-eks-7d68063
ip-192-168-73-174.ap-northeast-1.compute.internal   Ready    &amp;lt;none&amp;gt;   13m   v1.22.6-eks-7d68063
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Install Istio
&lt;/h3&gt;

&lt;p&gt;The official website of Istio provides us fabulous "Getting Started" guide so we use it here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://istio.io/latest/docs/setup/getting-started/" rel="noopener noreferrer"&gt;https://istio.io/latest/docs/setup/getting-started/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download the latest Istio. 1.14.1 in this example.&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="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-L&lt;/span&gt; https://istio.io/downloadIstio | sh -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move Istio directory you downloaded.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;istio-1.14.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add an environment variable into your PC.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;/bin:&lt;span class="nv"&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install istiocel.&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="nv"&gt;$ &lt;/span&gt;istioctl &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--set&lt;/span&gt; &lt;span class="nv"&gt;profile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;demo &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't forget to check your Istio version.&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="nv"&gt;$ &lt;/span&gt;istioctl version
client version: 1.14.1
control plane version: 1.14.1
data plane version: 1.14.1 &lt;span class="o"&gt;(&lt;/span&gt;2 proxies&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable namespace setting for Istio on your EKS cluster.&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="nv"&gt;$ &lt;/span&gt;kubectl label namespace default istio-injection&lt;span class="o"&gt;=&lt;/span&gt;enabled
namespace/default labeled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy sample app on EKS
&lt;/h3&gt;

&lt;p&gt;Deploy sample app named "bookinfo" on your EKS cluster.&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="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; samples/bookinfo/platform/kube/bookinfo.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the service you deployed.&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="nv"&gt;$ &lt;/span&gt;kubectl get services

NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;    AGE
details       ClusterIP   10.100.124.27    &amp;lt;none&amp;gt;        9080/TCP   4m14s
kubernetes    ClusterIP   10.100.0.1       &amp;lt;none&amp;gt;        443/TCP    49m
productpage   ClusterIP   10.100.251.75    &amp;lt;none&amp;gt;        9080/TCP   4m13s
ratings       ClusterIP   10.100.54.25     &amp;lt;none&amp;gt;        9080/TCP   4m14s
reviews       ClusterIP   10.100.249.201   &amp;lt;none&amp;gt;        9080/TCP   4m13s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait a minute and find your pods waking.&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="nv"&gt;$ &lt;/span&gt;kubectl get pods

NAME                              READY   STATUS    RESTARTS   AGE
details-v1-7d88846999-j97r2       2/2     Running   0          98s
productpage-v1-7795568889-vzg9j   2/2     Running   0          98s
ratings-v1-754f9c4975-btfk9       2/2     Running   0          98s
reviews-v1-55b668fc65-rg2ft       2/2     Running   0          98s
reviews-v2-858f99c99-dkmmk        2/2     Running   0          98s
reviews-v3-7886dd86b9-m9xqh       2/2     Running   0          98s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute an command below on your pod for "ratings" app and you may get title section of an HTML page.&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="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl get pod &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;app&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ratings &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.items[0].metadata.name}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; ratings &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-sS&lt;/span&gt; productpage:9080/productpage | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;title&amp;gt;.*&amp;lt;/title&amp;gt;"&lt;/span&gt;
&amp;lt;title&amp;gt;Simple Bookstore App&amp;lt;/title&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Enable external access to sample app
&lt;/h3&gt;

&lt;p&gt;Deploy Ingress Gateway on you EKS Cluster.&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="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; samples/bookinfo/networking/bookinfo-gateway.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if there is no poblems on your service mesh.&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="nv"&gt;$ &lt;/span&gt;istioctl analyze
✔ No validation issues found when analyzing namespace: default.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm an External IP of the Ingress Gateway service.&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="nv"&gt;$ &lt;/span&gt;kubectl get svc istio-ingressgateway &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP                                                                    PORT&lt;span class="o"&gt;(&lt;/span&gt;S&lt;span class="o"&gt;)&lt;/span&gt;                                                                      AGE
istio-ingressgateway   LoadBalancer   10.100.8.158   &lt;span class="k"&gt;********&lt;/span&gt;.ap-northeast-1.elb.amazonaws.com   15021:32244/TCP,80:31172/TCP,443:32028/TCP,31400:32681/TCP,15443:30730/TCP   29m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set environment variables for Ingress.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;INGRESS_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system get service istio-ingressgateway &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.status.loadBalancer.ingress[0].hostname}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;INGRESS_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system get service istio-ingressgateway &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.ports[?(@.name=="http2")].port}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;SECURE_INGRESS_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system get service istio-ingressgateway &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.ports[?(@.name=="https")].port}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GATEWAY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$INGRESS_HOST&lt;/span&gt;:&lt;span class="nv"&gt;$INGRESS_PORT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check a combination of external host name and port number.&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="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GATEWAY_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;********&lt;/span&gt;.ap-northeast-1.elb.amazonaws.com:80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try external access.&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="nv"&gt;$ &lt;/span&gt;open http://&lt;span class="nv"&gt;$GATEWAY_URL&lt;/span&gt;/productpage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Got it! You can access bookinfo app via your web browser.&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%2Ftsvz7qxc7tal2yt0bw9i.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%2Ftsvz7qxc7tal2yt0bw9i.png" alt="スクリーンショット 2022-06-12 0.04.34.png" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Get o11y with dashboards
&lt;/h3&gt;

&lt;p&gt;Deploy monitoring add-ons like Kiali and Grafana.&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="nv"&gt;$ &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; samples/addons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Execute below and wait for deploying Kiali.&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="nv"&gt;$ &lt;/span&gt;kubectl rollout status deployment/kiali &lt;span class="nt"&gt;-n&lt;/span&gt; istio-systemWaiting &lt;span class="k"&gt;for &lt;/span&gt;deployment &lt;span class="s2"&gt;"kiali"&lt;/span&gt; rollout to finish: 0 of 1 updated replicas are available...
deployment &lt;span class="s2"&gt;"kiali"&lt;/span&gt; successfully rolled out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then launch Kiali.&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="nv"&gt;$ &lt;/span&gt;istioctl dashboard kiali
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may successfully access to Kiali via web browser.&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%2Fqogy0zyahlhoj4o0g43b.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%2Fqogy0zyahlhoj4o0g43b.png" alt="スクリーンショット 2022-06-12 0.05.00.png" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open "Graph" in left columun and change namespace to "Select all" then you can see your service mesh graphically.&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%2Ffwttbvg8zvt7wm88zax7.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%2Ffwttbvg8zvt7wm88zax7.png" alt="スクリーンショット 2022-06-12 0.12.40.png" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Grafana &amp;amp; Jaeger hands-on
&lt;/h2&gt;

&lt;p&gt;You may be wise to find that you already have famous monitoring tools in &lt;code&gt;samples/addons&lt;/code&gt; you installed for Kiali.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Grafana&lt;/li&gt;
&lt;li&gt;Jaeger&lt;/li&gt;
&lt;li&gt;Zipkin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you've deployed above so try to launch them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try Grafana
&lt;/h3&gt;

&lt;p&gt;First launch Grafana, OSS for monitoring dashboard.&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="nv"&gt;$ &lt;/span&gt;istioctl dashboard grafana
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access preset dashboard for Istio, clicking &lt;code&gt;Dashboard &amp;gt; Browse&lt;/code&gt; in left pane.&lt;br&gt;
Try to open "Istio Control Plane Dashboard.”&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%2Fzk1aokhh14t7zo4y28bl.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%2Fzk1aokhh14t7zo4y28bl.png" alt="スクリーンショット 2022-06-12 14.27.50.png" width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Try Jaeger
&lt;/h3&gt;

&lt;p&gt;Next try Jeager, OSS for distributed tracing.&lt;br&gt;
Enable tracing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;istioctl &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--set&lt;/span&gt; meshConfig.enableTracing&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;This will &lt;span class="nb"&gt;install &lt;/span&gt;the Istio 1.14.1 default profile with &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Istio core"&lt;/span&gt; &lt;span class="s2"&gt;"Istiod"&lt;/span&gt; &lt;span class="s2"&gt;"Ingress gateways"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; components into the cluster. Proceed? &lt;span class="o"&gt;(&lt;/span&gt;y/N&lt;span class="o"&gt;)&lt;/span&gt; y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch Jaegar.&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="nv"&gt;$ &lt;/span&gt;istioctl dashboard jaeger
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set any service in left pane and search traces.&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%2F497jz595f9q7h6211npg.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%2F497jz595f9q7h6211npg.png" alt="スクリーンショット 2022-06-12 14.37.14.png" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find details of a trace if you click a marker of the trace in a graph in right pane.&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%2Fscib18ah0l05kabn3dbl.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%2Fscib18ah0l05kabn3dbl.png" alt="スクリーンショット 2022-06-12 14.38.18.png" width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  For next steps
&lt;/h2&gt;

&lt;p&gt;Next I'm excited to try "Next steps" contents in Istio official page.&lt;br&gt;
&lt;a href="https://istio.io/latest/docs/setup/getting-started/#next-steps" rel="noopener noreferrer"&gt;https://istio.io/latest/docs/setup/getting-started/#next-steps&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of cource, I'm really interested in trying AWS App Mesh as well!&lt;/p&gt;

&lt;p&gt;When you quit this hands-on, clean up your environment as below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delete your EKS cluster
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;eksctl delete cluster &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"YOUR CLUSTER NAME"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Clear your environment variables
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;INGRESS_HOST
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;INGRESS_PORT
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;SECURE_INGRESS_PORT
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;unset &lt;/span&gt;GATEWAY_URL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>eks</category>
      <category>istio</category>
      <category>beginners</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
