<?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: Luis Fernando de León Ramírez</title>
    <description>The latest articles on DEV Community by Luis Fernando de León Ramírez (@luisferdeleon).</description>
    <link>https://dev.to/luisferdeleon</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3806746%2F6f0185c8-3518-431b-8063-707777f59db7.png</url>
      <title>DEV Community: Luis Fernando de León Ramírez</title>
      <link>https://dev.to/luisferdeleon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/luisferdeleon"/>
    <language>en</language>
    <item>
      <title>AWS Lambda MicroVMs: Cómo crear entornos de código aislados por usuario</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Tue, 07 Jul 2026 16:00:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-lambda-microvms-como-crear-entornos-de-codigo-aislados-por-usuario-5cp3</link>
      <guid>https://dev.to/aws-builders/aws-lambda-microvms-como-crear-entornos-de-codigo-aislados-por-usuario-5cp3</guid>
      <description>&lt;h1&gt;
  
  
  AWS Lambda MicroVMs
&lt;/h1&gt;

&lt;p&gt;💡 AWS lanzó Lambda MicroVMs: máquinas virtuales aisladas con Firecracker, arranque en milisegundos y sin infraestructura que administrar.&lt;/p&gt;

&lt;p&gt;📝 En este artículo comparto mi experiencia creando un laboratorio de codificación donde cada usuario obtiene su propio VS Code en la nube para resolver ejercicios de Python con pruebas automatizadas — todo corriendo sobre Lambda MicroVMs.&lt;/p&gt;

&lt;p&gt;"AWS Lambda MicroVMs: Cómo crear entornos de código aislados por usuario"&lt;/p&gt;

&lt;p&gt;AWS Lambda MicroVMs es una tecnología utilizada para virtualización ligera, permitiendo la creación de ambientes de forma segura y aislada con duración de hasta 8 horas y se suspenden sin costo de cómputo cuando están inactivas.&lt;/p&gt;

&lt;p&gt;En este artículo exploraremos las experiencias y retos que tuve al crear un laboratorio para evaluar el conocimiento sobre funciones en Python, proporcionando a cada usuario una interfaz de code-server (VS Code web), que le permitiera realizar ajustes en su código y pruebas automatizadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Beneficios
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ejecución de código aislada utilizando Firecracker: No son contenedores, cuando inicias a conocer el servicio podrías confundirlo con contenedores, pero no es así, son maquinas virtuales con su propio kernel y aislamiento a nivel de hardware.&lt;/li&gt;
&lt;li&gt;Serverless: Tendrás disponibles servidores aislados, sin redes o balanceadores para su acceso, solamente definirás el Dokerfile y empiezas a usarlo.&lt;/li&gt;
&lt;li&gt;Escalado vertical flexible: Hasta 4x los recursos base configurados.&lt;/li&gt;
&lt;li&gt;Arranque en milisegundos: Se restaura de un snapshot pre construido, en segundos tu app ya está corriendo. &lt;/li&gt;
&lt;li&gt;No pagas por cómputo mientras se encuentre en estado suspendido: Cuando no existe tráfico la aplicación se suspende preservando disco y memoria.&lt;/li&gt;
&lt;li&gt;Autenticación JWE: Permite que cada endpoint este protegido por token con una expiración configurable.&lt;/li&gt;
&lt;li&gt;El modelo básico de construcción: Dockerfile &amp;gt; Código &amp;gt; Snapshot &amp;gt; Lanzar N microVMs desde esa imagen base&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Casos de aplicación
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Plataformas de desarrollo aisladas por usuario&lt;/li&gt;
&lt;li&gt;Aislamiento de pruebas de seguridad y escaneos de seguridad, impidiendo que el código malicioso pueda afectar otros recursos&lt;/li&gt;
&lt;li&gt;Ambientes aislados con configuraciones específicas para análisis de datos&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. ¿Contenedores corriendo dentro de Lambdas?
&lt;/h2&gt;

&lt;p&gt;La respuesta es no, al utilizar un Dockerfile, podríamos confundirnos pensando que es así, sin embargo acá este archivo cumple con un rol distinto. Lambda lo utiliza únicamente para definir el listado de lo que necesita instalar y como iniciar la aplicación durante la fase de construcción, El resultado no será una imagen de docker, que pueda ser utilizada desde un contenedor, sino un snapshot de Firecracker.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. ¿Qué sucede detrás del modelo de construcción?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;El Dockerfile define qué instalar y cómo inicia la aplicación&lt;/li&gt;
&lt;li&gt;Lambda provisiona una VM, ejecuta las instrucciones del Dockerfile y arranca tu app con CMD&lt;/li&gt;
&lt;li&gt;Se captura un snapshot del estado completo de la VM (disco, memoria y procesos en ejecución)&lt;/li&gt;
&lt;li&gt;Al lanzar una MicroVM, Lambda restaura ese snapshot. Tu aplicación reanuda exactamente donde quedó, sin repetir el arranque&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Estructura de los archivos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Proyecto:&lt;/strong&gt; Puedes utilizar cualquier lenguaje o framework que pueda ser ejecutado en Linux&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dockerfile:&lt;/strong&gt; Las instrucciones que necesito para preparar el entorno de ejecución&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Manos a la obra
&lt;/h2&gt;

&lt;p&gt;Vamos a definir un entorno adecuado para que se puedan hacer ejercicios con un entorno aislado con la finalidad de que el usuario que ingrese pueda realizar un ejercicio de codificación personalizado sin afectar las pruebas de otros.&lt;/p&gt;

&lt;p&gt;Nota: Desactivamos la autenticación propia de code-server (auth: none) porque el acceso a la MicroVM ya está protegido por el token JWE a nivel del endpoint. Nadie puede llegar al puerto 8080 sin un token válido.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; codercom/code-server:latest&lt;/span&gt;

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; root&lt;/span&gt;

&lt;span class="c"&gt;# Instalar Node.js (para hook server) y Python con pytest&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    nodejs &lt;span class="se"&gt;\
&lt;/span&gt;    python3 python3-pip &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip3 &lt;span class="nb"&gt;install &lt;/span&gt;pytest &lt;span class="nt"&gt;--break-system-packages&lt;/span&gt;

&lt;span class="c"&gt;# Instalar extensión de Python para code-server&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;code-server &lt;span class="nt"&gt;--install-extension&lt;/span&gt; ms-python.python

&lt;span class="c"&gt;# Config sin auth&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /root/.config/code-server &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"bind-addr: 0.0.0.0:8080"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /root/.config/code-server/config.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"auth: none"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /root/.config/code-server/config.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"cert: false"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /root/.config/code-server/config.yaml

&lt;span class="c"&gt;# Copiar ejercicio al workspace&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ejercicio/ /home/coder/workspace/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; coder:coder /home/coder/workspace

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; hook_server.js /hook_server.js&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; start.sh /start.sh&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /start.sh

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080 8081&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/start.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Ejercicio en Python
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;main.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;TODO: Retorna la suma de a y b&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;TODO: Retorna True si el texto es un palíndromo&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;TODO: Retorna los primeros n números de Fibonacci&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;tests/test_main.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_suma&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_palindromo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hola&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_fibonacci&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. ¿Cómo construir un snapshot?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Creo los archivos base

&lt;ul&gt;
&lt;li&gt;Proyecto&lt;/li&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Empaquetar en zip
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   zip &lt;span class="nt"&gt;-r&lt;/span&gt; bootcamp-lab.zip Dockerfile start.sh hook_server.js README.md ejercicio/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Subirlo a un bucket de S3
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws s3 &lt;span class="nb"&gt;cp &lt;/span&gt;bootcamp-lab.zip s3://mi-bucket/bootcamp-lab.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Creo el snapshot&lt;/li&gt;
&lt;/ol&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhbptv5nao6mo17lxqe5g.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhbptv5nao6mo17lxqe5g.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Al crear el snapshot, puedes elegir un rol por defecto que Lambda genera automáticamente. Este rol incluye los permisos necesarios para leer del bucket S3 que especificaste. Para pruebas iniciales, te recomiendo usar esta opción y no complicarte con roles personalizados.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  8. Vamos a correr nuestra primera Lambda MicroVM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Le daremos al botón "Run MicroVM"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwnuu4ll1vjcf59g95tmp.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwnuu4ll1vjcf59g95tmp.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creación de token: a través de este podremos acceder a la URL de la MicroVM&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdztwtpqy5y8ee3mqiljl.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdztwtpqy5y8ee3mqiljl.png" alt=" " width="588" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Iniciar microVM&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyctrnrqwey6u06m39rql.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyctrnrqwey6u06m39rql.png" alt=" " width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con el endpoint utilizado podremos acceder desde el navegador. Toda petición requiere el header X-aws-proxy-auth con el token que generamos en el paso anterior, el cual deberás agregar al navegador. Para este caso utilicé la extensión de Chrome &lt;a href="https://modheader.com/docs/modheader" rel="noopener noreferrer"&gt;ModHeader&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Al ingresar al endpoint generado podré ver el ambiente aislado. De esta forma podré crear los ambientes que necesite exactamente con la misma estructura para que los usuarios puedan realizar sus pruebas sin afectar los recursos existentes ni los ambientes de otros usuarios.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ugmwyu82pw8nwt2zgap.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1ugmwyu82pw8nwt2zgap.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Probar usando un IDE para base de datos
&lt;/h2&gt;

&lt;p&gt;La estructura utilizada para este caso puede ser adaptada para otros escenarios que puedan llegar a utilizar un IDE, por ejemplo una MicroVM que sea utilizada para ejercicios de base de datos (CloudBeaver, PgAdmin, Workbench, etc). Es la misma estructura, utiliza un Dockerfile para configurar el ambiente , crea el snapshot y lanza la ejecución.&lt;/p&gt;

&lt;p&gt;En mi repositorio podrás encontrar el código completo:&lt;br&gt;
 &lt;a href="https://github.com/lfdeleonramirez/aws-lambda-microvms" rel="noopener noreferrer"&gt;https://github.com/lfdeleonramirez/aws-lambda-microvms&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Sobre el autor
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Luis Fernando de León&lt;/strong&gt; — AWS Community Builder 🇬🇹&lt;/p&gt;

&lt;p&gt;📸 Instagram: &lt;a href="https://instagram.com/luisenlanube" rel="noopener noreferrer"&gt;instagram.com/luisenlanube&lt;/a&gt;&lt;br&gt;
📝 DEV: &lt;a href="https://dev.to/luisferdeleon"&gt;dev.to/luisferdeleon&lt;/a&gt;&lt;br&gt;
👤 Facebook: &lt;a href="https://facebook.com/luisenlanube" rel="noopener noreferrer"&gt;facebook.com/luisenlanube&lt;/a&gt;&lt;br&gt;
💼 LinkedIn: &lt;a href="https://linkedin.com/in/luisfdeleonramirez" rel="noopener noreferrer"&gt;linkedin.com/in/luisfdeleonramirez&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recursos&lt;br&gt;
📖 Documentación oficial — &lt;a href="https://aws.amazon.com/es/lambda/lambda-microvms/" rel="noopener noreferrer"&gt;AWS Lambda MicroVMs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscommunity</category>
      <category>serverless</category>
    </item>
    <item>
      <title>AWS Lambda MicroVMs: How to create isolated code environments per user</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Mon, 06 Jul 2026 10:37:00 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-lambda-microvms-how-to-create-isolated-code-environments-per-user-3a53</link>
      <guid>https://dev.to/aws-builders/aws-lambda-microvms-how-to-create-isolated-code-environments-per-user-3a53</guid>
      <description>&lt;p&gt;AWS Lambda MicroVMs is a lightweight virtualization technology that enables the creation of secure, isolated environments with a duration of up to 8 hours, which suspend at no compute cost when idle.&lt;/p&gt;

&lt;p&gt;In this article we'll explore the experiences and challenges I faced while building a lab to evaluate Python function knowledge, providing each user with a code-server interface (VS Code web) where they could edit their code and run automated tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Benefits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Isolated code execution using Firecracker: These are not containers. When you first discover the service you might confuse it with containers, but they are actually virtual machines with their own kernel and hardware-level isolation.&lt;/li&gt;
&lt;li&gt;Serverless: You get isolated servers with no networks or load balancers to configure — just define your Dockerfile and start using them.&lt;/li&gt;
&lt;li&gt;Flexible vertical scaling: Up to 4x the configured base resources.&lt;/li&gt;
&lt;li&gt;Millisecond startup: It restores from a pre-built snapshot; in seconds your app is already running.&lt;/li&gt;
&lt;li&gt;No compute charges while suspended: When there is no traffic, the application suspends preserving disk and memory.&lt;/li&gt;
&lt;li&gt;JWE Authentication: Each endpoint is protected by a token with configurable expiration.&lt;/li&gt;
&lt;li&gt;Basic build model: Dockerfile &amp;gt; Code &amp;gt; Snapshot &amp;gt; Launch N MicroVMs from that base image&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Use cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Isolated development platforms per user&lt;/li&gt;
&lt;li&gt;Security testing and scanning isolation, preventing malicious code from affecting other resources&lt;/li&gt;
&lt;li&gt;Isolated environments with specific configurations for data analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Containers running inside Lambdas?
&lt;/h2&gt;

&lt;p&gt;The answer is no. When using a Dockerfile, we might assume that's what's happening, but the Dockerfile plays a different role here. Lambda uses it only to define what needs to be installed and how to start the application during the build phase. The result is not a Docker image that runs as a container, but a Firecracker snapshot.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. What happens behind the build model?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The Dockerfile defines what to install and how the application starts&lt;/li&gt;
&lt;li&gt;Lambda provisions a VM, executes the Dockerfile instructions, and starts your app with CMD&lt;/li&gt;
&lt;li&gt;A snapshot of the VM's full state is captured (disk, memory, and running processes)&lt;/li&gt;
&lt;li&gt;When launching a MicroVM, Lambda restores that snapshot. Your application resumes exactly where it left off, without repeating the startup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. File structure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project:&lt;/strong&gt; You can use any language or framework that can run on Linux&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dockerfile:&lt;/strong&gt; The instructions needed to prepare the execution environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Hands-on
&lt;/h2&gt;

&lt;p&gt;We're going to define an environment suitable for isolated coding exercises, so that each user can complete a personalized coding challenge without affecting other users' tests.&lt;/p&gt;

&lt;p&gt;Note: We disable code-server's built-in authentication (auth: none) because access to the MicroVM is already protected by the JWE token at the endpoint level. Nobody can reach port 8080 without a valid token.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; codercom/code-server:latest&lt;/span&gt;

&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; root&lt;/span&gt;

&lt;span class="c"&gt;# Install Node.js (for hook server) and Python with pytest&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    nodejs &lt;span class="se"&gt;\
&lt;/span&gt;    python3 python3-pip &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pip3 &lt;span class="nb"&gt;install &lt;/span&gt;pytest &lt;span class="nt"&gt;--break-system-packages&lt;/span&gt;

&lt;span class="c"&gt;# Install Python extension for code-server&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;code-server &lt;span class="nt"&gt;--install-extension&lt;/span&gt; ms-python.python

&lt;span class="c"&gt;# Config without auth&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /root/.config/code-server &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"bind-addr: 0.0.0.0:8080"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /root/.config/code-server/config.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"auth: none"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /root/.config/code-server/config.yaml &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"cert: false"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /root/.config/code-server/config.yaml

&lt;span class="c"&gt;# Copy exercise to workspace&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ejercicio/ /home/coder/workspace/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; coder:coder /home/coder/workspace

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; hook_server.js /hook_server.js&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; start.sh /start.sh&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /start.sh

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080 8081&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/start.sh"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Python Exercise
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;main.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;TODO: Return the sum of a and b&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texto&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;TODO: Return True if the text is a palindrome&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;TODO: Return the first n Fibonacci numbers&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;tests/test_main.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fibonacci&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_suma&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;suma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_palindromo&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ana&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;es_palindromo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hola&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_fibonacci&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  7. How to build a snapshot?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create the base files

&lt;ul&gt;
&lt;li&gt;Project&lt;/li&gt;
&lt;li&gt;Dockerfile&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Package into a zip
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   zip &lt;span class="nt"&gt;-r&lt;/span&gt; bootcamp-lab.zip Dockerfile start.sh hook_server.js README.md ejercicio/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Upload to an S3 bucket
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws s3 &lt;span class="nb"&gt;cp &lt;/span&gt;bootcamp-lab.zip s3://my-bucket/bootcamp-lab.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create the snapshot&lt;/li&gt;
&lt;/ol&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr62yfqpz45z8isakrbhm.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr62yfqpz45z8isakrbhm.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: When creating the snapshot, you can choose a default role that Lambda generates automatically. This role includes the necessary permissions to read from the S3 bucket you specified. For initial testing, I recommend using this option instead of dealing with custom roles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  8. Let's run our first Lambda MicroVM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Click the "Run MicroVM" button&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fowe4hjsiehrx3hknhzaw.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fowe4hjsiehrx3hknhzaw.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Token creation: through this we can access the MicroVM URL&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fej0cugbdipjl4b3voj49.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fej0cugbdipjl4b3voj49.png" alt=" " width="588" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start the MicroVM&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5xux8l2y249gen1ebn28.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5xux8l2y249gen1ebn28.png" alt=" " width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the generated endpoint we can access it from the browser. Every request requires the &lt;code&gt;X-aws-proxy-auth&lt;/code&gt; header with the token we generated in the previous step, which you'll need to add to the browser. For this case I used the Chrome extension &lt;a href="https://modheader.com/docs/modheader" rel="noopener noreferrer"&gt;ModHeader&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you navigate to the generated endpoint you'll see the isolated environment. This way I can create as many environments as needed with the exact same structure so that users can run their tests without affecting existing resources or other users' environments.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fudj3lpncnb23qgbp5in9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fudj3lpncnb23qgbp5in9.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Testing with a database IDE
&lt;/h2&gt;

&lt;p&gt;The structure used for this case can be adapted for other scenarios that use an IDE — for example, a MicroVM used for database exercises (CloudBeaver, pgAdmin, Workbench, etc.). It's the same pattern: use a Dockerfile to configure the environment, create the snapshot, and launch the execution.&lt;/p&gt;

&lt;p&gt;You can find the complete code in my repository:&lt;br&gt;
&lt;a href="https://github.com/lfdeleonramirez/aws-lambda-microvms" rel="noopener noreferrer"&gt;https://github.com/lfdeleonramirez/aws-lambda-microvms&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  About the author
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Luis Fernando de León&lt;/strong&gt; — AWS Community Builder 🇬🇹&lt;/p&gt;

&lt;p&gt;📸 Instagram: &lt;a href="https://instagram.com/luisenlanube" rel="noopener noreferrer"&gt;instagram.com/luisenlanube&lt;/a&gt;&lt;br&gt;
📝 DEV: &lt;a href="https://dev.to/luisferdeleon"&gt;dev.to/luisferdeleon&lt;/a&gt;&lt;br&gt;
👤 Facebook: &lt;a href="https://facebook.com/luisenlanube" rel="noopener noreferrer"&gt;facebook.com/luisenlanube&lt;/a&gt;&lt;br&gt;
💼 LinkedIn: &lt;a href="https://linkedin.com/in/luisfdeleonramirez" rel="noopener noreferrer"&gt;linkedin.com/in/luisfdeleonramirez&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resources&lt;br&gt;
📖 Official documentation — &lt;a href="https://aws.amazon.com/lambda/lambda-microvms/" rel="noopener noreferrer"&gt;AWS Lambda MicroVMs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>awscommunity</category>
      <category>lambdamicrovm</category>
    </item>
    <item>
      <title>¿Y si construir un chatbot con IA fuera tan fácil como armar con LEGO? — AWS Blocks"</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Sat, 04 Jul 2026 05:02:56 +0000</pubDate>
      <link>https://dev.to/aws-builders/y-si-construir-un-chatbot-con-ia-fuera-tan-facil-como-armar-con-lego-aws-blocks-1kb3</link>
      <guid>https://dev.to/aws-builders/y-si-construir-un-chatbot-con-ia-fuera-tan-facil-como-armar-con-lego-aws-blocks-1kb3</guid>
      <description>&lt;h2&gt;
  
  
  1. ¿Qué es Blocks?
&lt;/h2&gt;

&lt;p&gt;Es un marco de trabajo de código abierto lanzado recientemente que facilita la implementación de proyectos en AWS; tú solamente te encargarás de desarrollar tu proyecto como lo haces normalmente en TypeScript. El marco de trabajo se encargará de convertir tu código en servicios de AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Beneficios
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Desarrollo sin necesidad de una cuenta de AWS.&lt;/li&gt;
&lt;li&gt;Puedes probar tu código en local y tendrás la certeza de que el funcionamiento será igual en producción.&lt;/li&gt;
&lt;li&gt;Orientado a costo bajo utilizando la tecnología serverless.&lt;/li&gt;
&lt;li&gt;Experiencia de desarrollo con IA al incluir guías que permiten hacer uso de herramientas de IA para codificación, como Kiro, ya que el framework orienta al agente sobre cómo mejorar tus arquitecturas.&lt;/li&gt;
&lt;li&gt;Tendrás un ambiente de desarrollo aislado y totalmente funcional.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. ¿Qué es un Block?
&lt;/h2&gt;

&lt;p&gt;Un Block es una pieza de funcionalidad que encapsula lógica + infraestructura AWS en una sola abstracción que usas con una a tres líneas de código.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogía:&lt;/strong&gt;&lt;br&gt;
Piensa en un Block como un módulo de LEGO: cada pieza tiene una forma y función específica, y las combinas para construir lo que quieras. No te preocupas de cómo está hecha internamente.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. ¿Qué Blocks puedo utilizar?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Datos y almacenamiento&lt;/li&gt;
&lt;li&gt;Autenticación&lt;/li&gt;
&lt;li&gt;Cómputo y trabajos en segundo plano&lt;/li&gt;
&lt;li&gt;Inteligencia artificial&lt;/li&gt;
&lt;li&gt;Comunicación&lt;/li&gt;
&lt;li&gt;Configuración&lt;/li&gt;
&lt;li&gt;Observabilidad&lt;/li&gt;
&lt;li&gt;Alojamiento y despliegue&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  5. ¿Cómo inicio con mi proyecto?
&lt;/h2&gt;

&lt;p&gt;Con un comando de npm podemos crear la estructura principal del proyecto. Para entender cómo funciona todo desde cero, creé un repositorio que cuenta con una plantilla en blanco la cual puedes utilizar para crear tu proyecto. Ejecuta lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @luisfdeleonramirez/create-aws-blocks-base chatbot-ia
&lt;span class="nb"&gt;cd &lt;/span&gt;chatbot-ia
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al ejecutar estos comandos tendremos un servicio local corriendo en &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; donde podrás realizar tus pruebas.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. ¿Qué vamos a construir?
&lt;/h2&gt;

&lt;p&gt;Desarrollé una app que funciona como un agente que usa Amazon Nova Lite (amazon.nova-lite-v1:0) y responde consultas de los usuarios. Luego de varias pruebas, considero que un flujo adecuado para organizar el desarrollo es el siguiente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Primero defino qué hace mi app (index.ts)"&lt;/li&gt;
&lt;li&gt;"Luego defino dónde corre (index.cdk.ts)"&lt;/li&gt;
&lt;li&gt;"Finalmente defino cómo se ve para el usuario (app.tsx)"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. ¿Qué Blocks utilicé?
&lt;/h2&gt;

&lt;p&gt;Originalmente pensé que utilizaría los bloques únicamente del lado del backend, pero en la interfaz web terminé utilizando funciones propias de Blocks para el manejo de conversaciones.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scope
&lt;/h3&gt;

&lt;p&gt;Para la agrupación de recursos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatbot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AuthBasic
&lt;/h3&gt;

&lt;p&gt;Para la configuración de autenticación utilizando correo y contraseña.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthBasic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Agent
&lt;/h3&gt;

&lt;p&gt;Bloque para el agente de IA con Bedrock, que incluye configuración, streaming y tools. Algo sumamente interesante es que solamente en un par de líneas puedes configurar el comportamiento de tu agente para su interacción.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;deployed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bedrock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amazon.nova-lite-v1:0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Eres un agente amigable que se encargará de solucionar dudas a los usuarios sobre tecnología.
Debes responderles en el mismo idioma que te hagan las preguntas.
Cuando el usuario pregunte sobre la empresa, productos, precios o información específica, 
usa la herramienta searchKnowledge para buscar en la base de conocimiento antes de responder.
Si no encuentras información relevante en la base de conocimiento, responde con tu conocimiento general.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;searchKnowledge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Busca información relevante en la base de conocimiento de la empresa. Usa esta herramienta cuando el usuario pregunte sobre productos, precios, servicios o información específica de la empresa.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Consulta de búsqueda en lenguaje natural&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No se encontró información relevante en la base de conocimiento.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  KnowledgeBase
&lt;/h3&gt;

&lt;p&gt;Base de conocimiento RAG con documentos propios que el agente usará para responder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KnowledgeBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;docs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./knowledge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Documentación y base de conocimiento del chatbot',&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ApiNamespace
&lt;/h3&gt;

&lt;p&gt;Para la comunicación de la API mediante JSON-RPC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Desarrollo
&lt;/h2&gt;

&lt;p&gt;Luego de ajustar el código para que fuera funcional, quise probar si funcionaba totalmente en local y la respuesta es que sí: tenía un funcionamiento básico que podía simular usando datos mock en el código. Sin embargo, la funcionalidad del agente sí requiere que al menos hagamos la prueba en el sandbox. Teniendo algo listo, pasé al sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Configuración de IAM
&lt;/h2&gt;

&lt;p&gt;Para poder realizar esto bajo el principio del privilegio mínimo, hice pruebas con los permisos mínimos que debería tener el usuario que ejecutará los deploys. Te dejo a continuación la política:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWSBlocksCloudFormationAndIAM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"cloudformation:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:CreateRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:DeleteRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:GetRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:GetRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:ListRolePolicies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:ListAttachedRolePolicies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:PassRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:AttachRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:DetachRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:PutRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:DeleteRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:TagRole"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWSBlocksAllPossibleFrameworkServices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"lambda:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"dynamodb:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"apigateway:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"events:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sqs:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ecr:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssm:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Bootstrap
&lt;/h2&gt;

&lt;p&gt;Inicié con la prueba de sandbox, sin embargo, para esto necesitaba tener el bootstrap listo. El bootstrap es una preparación base para que las aplicaciones de Blocks puedan funcionar correctamente. Esta preparación se realiza una sola vez por cuenta y región. La realizas de esta forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cdk bootstrap aws://&lt;span class="o"&gt;{&lt;/span&gt;id_de_tu_cuenta&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado de esta ejecución es la creación de un CloudFormation y la pregunta más grande: ¿esto genera costos? La respuesta es no, únicamente crea un bucket de S3 vacío, los roles en IAM y un parámetro en SSM. El costo se genera cuando el CDK sube los assets del código estático durante los deploys. Toma en cuenta que para el sandbox el CDK no copia estos archivos, ya que la interfaz sigue corriendo en tu ambiente.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Sandbox
&lt;/h2&gt;

&lt;p&gt;Durante la creación del sandbox, encontré diversos retos. Al ser una nueva tecnología, es posible encontrar detalles que puedan generar un funcionamiento inesperado. Puedes iniciar el sandbox ejecutando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run sandbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opté por probar el sandbox en la región de us-west-2. La experiencia fue buena y fortalecí mis conocimientos sobre el framework. Te dejo algunos consejos:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Crea tags en tu proyecto
&lt;/h3&gt;

&lt;p&gt;Para tener control sobre tus recursos, así como el monitoreo de tus costos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.cdk.ts:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Project&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blocks-chatbot-ia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sandboxMode&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sandbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Team&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CostCenter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatbot-ia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Nombres de stack cortos
&lt;/h3&gt;

&lt;p&gt;En ocasiones los recursos no podrán crearse si el nombre de tu proyecto es muy largo, por lo cual puedes cambiar el nombre base de tu stack, ya que los recursos se crean con este prefijo. Para este caso hice cambios para que el stack fuera el nombre del proyecto definido en el package:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.cdk.ts:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stackName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sandboxMode&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;`-sandbox`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blocksStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;BlocksStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stackName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;backendHandlerPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.handler.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;backendCDKPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Cuotas de Bedrock en Organizations
&lt;/h3&gt;

&lt;p&gt;Si tu cuenta forma parte de una organización, recuerda que debes establecer las cuotas en los modelos de Bedrock, de lo contrario no podrás verificar la respuesta de los modelos.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Bug de región en @strands-agents/sdk
&lt;/h3&gt;

&lt;p&gt;El bloque @aws-blocks/bb-agent usa internamente el módulo @strands-agents/sdk en su última versión disponible hasta la fecha de la prueba (1.7.0), para guardar las conversaciones del agente en S3. Sin embargo, este módulo por defecto apunta a la región us-east-1, por lo que al intentar hacer uso del agente en otra región podrías tener problemas. Para eso únicamente debes hacer el siguiente cambio:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;node_modules/@strands-agents/sdk/dist/src/session/s3-storage.js:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3Client&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con este cambio, por defecto ahora revisará la variable de ambiente de la región para que puedas ver el histórico de tus conversaciones. Esta solución es para esa versión. Hice el reporte #120 al equipo de mantenimiento del framework de AWS Blocks y fue resuelto, así que ya es poco probable que encuentres ese error. Te dejo detalles de la corrección que aplicaron:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aws-devtools-labs/aws-blocks/issues/120" rel="noopener noreferrer"&gt;https://github.com/aws-devtools-labs/aws-blocks/issues/120&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al finalizar las pruebas del sandbox, pude ver un CloudFormation con los diversos recursos creados. En este caso es posible darles un mejor seguimiento gracias a los tags, que identifican a qué proyecto pertenece cada recurso.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb1h4xpctopwehkg27shg.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb1h4xpctopwehkg27shg.png" alt=" " width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Despliegue
&lt;/h2&gt;

&lt;p&gt;Al haber realizado las pruebas en el sandbox, solamente queda hacer el deploy para que la aplicación sea accesible para todo el mundo. Es una experiencia satisfactoria, ya que este framework permite llevar a producción aplicaciones estables y seguras utilizando arquitecturas serverless. Para este paso, la diferencia con el sandbox es que se genera el hosting estático almacenado en S3 y distribuido por CloudFront. El tiempo de despliegue fue de 12 minutos.&lt;/p&gt;

&lt;p&gt;A continuación podemos ver el funcionamiento del chatbot en ambiente productivo.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1xsp6awp783udutyrvh9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1xsp6awp783udutyrvh9.png" alt=" " width="451" height="764"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Limpieza de recursos
&lt;/h2&gt;

&lt;p&gt;Posterior a las pruebas y para no incurrir en gastos, destruí la infraestructura creada. Esto es tan sencillo como ejecutar los siguientes comandos:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Borrar Sandbox:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run sandbox:destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Borrar despliegue:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Borrar el CDK&lt;/strong&gt; (tomar en cuenta que no genera gasto mientras no se transfieran assets):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;rm &lt;/span&gt;s3://cdk-hnb659fds-assets-xxxxx-&lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt;
aws cloudformation delete-stack &lt;span class="nt"&gt;--stack-name&lt;/span&gt; CDKToolkit &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Sobre el autor
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Luis Fernando de León&lt;/strong&gt; — AWS Community Builder 🇬🇹&lt;/p&gt;

&lt;p&gt;📸 Instagram: instagram.com/luisenlanube&lt;br&gt;
📝 DEV: dev.to/luisferdeleon&lt;br&gt;
👤 Facebook: facebook.com/luisenlanube&lt;br&gt;
💼 LinkedIn: linkedin.com/in/luisfdeleonramirez&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscdk</category>
      <category>awscommunity</category>
      <category>serverless</category>
    </item>
    <item>
      <title>What if building an AI chatbot was as easy as snapping LEGO bricks together? — AWS Blocks</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Fri, 03 Jul 2026 02:38:38 +0000</pubDate>
      <link>https://dev.to/aws-builders/what-if-building-an-ai-chatbot-was-as-easy-as-snapping-lego-bricks-together-aws-blocks-3lhm</link>
      <guid>https://dev.to/aws-builders/what-if-building-an-ai-chatbot-was-as-easy-as-snapping-lego-bricks-together-aws-blocks-3lhm</guid>
      <description>&lt;h2&gt;
  
  
  1. What is Blocks?
&lt;/h2&gt;

&lt;p&gt;It is a recently launched open-source framework that simplifies deploying projects to AWS; you only need to develop your project as you normally do in TypeScript. The framework takes care of converting your code into AWS services.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Benefits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Development without needing an AWS account.&lt;/li&gt;
&lt;li&gt;You can test your code locally with the certainty that it will work the same in production.&lt;/li&gt;
&lt;li&gt;Low-cost oriented using serverless technology.&lt;/li&gt;
&lt;li&gt;AI-powered development experience by including guides that enable the use of AI coding tools, such as Kiro, since the framework guides the agent on how to improve your architectures.&lt;/li&gt;
&lt;li&gt;You will have an isolated and fully functional development environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. What is a Block?
&lt;/h2&gt;

&lt;p&gt;A Block is a piece of functionality that encapsulates logic + AWS infrastructure in a single abstraction that you use with one to three lines of code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analogy:&lt;/strong&gt;&lt;br&gt;
Think of a Block as a LEGO module: each piece has a specific shape and function, and you combine them to build whatever you want. You don't worry about how it's made internally.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. What Blocks can I use?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Data and storage&lt;/li&gt;
&lt;li&gt;Authentication&lt;/li&gt;
&lt;li&gt;Compute and background jobs&lt;/li&gt;
&lt;li&gt;Artificial intelligence&lt;/li&gt;
&lt;li&gt;Communication&lt;/li&gt;
&lt;li&gt;Configuration&lt;/li&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;li&gt;Hosting and deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  5. How do I start my project?
&lt;/h2&gt;

&lt;p&gt;With a single npm command we can create the main project structure. To understand how everything works from scratch, I created a repository with a blank template that you can use to create your project. Run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @luisfdeleonramirez/create-aws-blocks-base chatbot-ia
&lt;span class="nb"&gt;cd &lt;/span&gt;chatbot-ia
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running these commands, we will have a local service running at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; where you can run your tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. What are we going to build?
&lt;/h2&gt;

&lt;p&gt;I developed an app that works as an agent using Amazon Nova Lite (amazon.nova-lite-v1:0) and responds to user queries. After several tests, I consider that an adequate flow to organize development is the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"First I define what my app does (index.ts)"&lt;/li&gt;
&lt;li&gt;"Then I define where it runs (index.cdk.ts)"&lt;/li&gt;
&lt;li&gt;"Finally I define how it looks for the user (app.tsx)"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  7. What Blocks did I use?
&lt;/h2&gt;

&lt;p&gt;Originally I thought I would only use blocks on the backend side, but on the web interface I ended up using Blocks' own functions for conversation management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scope
&lt;/h3&gt;

&lt;p&gt;For resource grouping.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Scope&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatbot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AuthBasic
&lt;/h3&gt;

&lt;p&gt;For authentication configuration using email and password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthBasic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Agent
&lt;/h3&gt;

&lt;p&gt;Block for the AI agent with Bedrock, which includes configuration, streaming, and tools. Something really interesting is that in just a couple of lines you can configure your agent's behavior for its interactions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;deployed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bedrock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amazon.nova-lite-v1:0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;systemPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are a friendly agent that will help users solve their questions about technology.
You must respond in the same language the user asks the question.
When the user asks about the company, products, prices or specific information,
use the searchKnowledge tool to search the knowledge base before responding.
If you don't find relevant information in the knowledge base, respond with your general knowledge.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;searchKnowledge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Searches for relevant information in the company knowledge base. Use this tool when the user asks about products, prices, services or specific company information.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Search query in natural language&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;kb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;maxResults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No relevant information found in the knowledge base.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;---&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  KnowledgeBase
&lt;/h3&gt;

&lt;p&gt;RAG knowledge base with custom documents that the agent will use to respond.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;kb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;KnowledgeBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;docs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./knowledge&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;'Documentation and chatbot knowledge base',&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ApiNamespace
&lt;/h3&gt;

&lt;p&gt;For API communication via JSON-RPC.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiNamespace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  8. Development
&lt;/h2&gt;

&lt;p&gt;After adjusting the code to make it functional, I wanted to test if it worked entirely locally and the answer is yes: it had basic functionality that I could simulate using mock data in the code. However, the agent functionality does require that we at least run the test in the sandbox. Having something ready, I moved on to the sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. IAM Configuration
&lt;/h2&gt;

&lt;p&gt;To accomplish this under the principle of least privilege, I tested with the minimum permissions that the user running the deploys should have. Here is the policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWSBlocksCloudFormationAndIAM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"cloudformation:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:CreateRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:DeleteRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:GetRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:GetRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:ListRolePolicies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:ListAttachedRolePolicies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:PassRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:AttachRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:DetachRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:PutRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:DeleteRolePolicy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"iam:TagRole"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWSBlocksAllPossibleFrameworkServices"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"lambda:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"dynamodb:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"apigateway:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"events:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sqs:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ecr:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssm:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  10. Bootstrap
&lt;/h2&gt;

&lt;p&gt;I started with the sandbox test, however, I needed to have the bootstrap ready first. The bootstrap is a base preparation so that Blocks applications can work correctly. This preparation is done once per account and region. You do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cdk bootstrap aws://&lt;span class="o"&gt;{&lt;/span&gt;your_account_id&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of this execution is the creation of a CloudFormation stack and the biggest question: does this generate costs? The answer is no, it only creates an empty S3 bucket, IAM roles, and an SSM parameter. The cost is generated when CDK uploads the static code assets during deploys. Keep in mind that for the sandbox, CDK does not copy these files since the interface keeps running in your local environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Sandbox
&lt;/h2&gt;

&lt;p&gt;During the sandbox creation, I encountered several challenges. Being a new technology, it is possible to find details that may cause unexpected behavior. You can start the sandbox by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run sandbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose to test the sandbox in the us-west-2 region. The experience was good and I strengthened my knowledge of the framework. Here are some tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Create tags in your project&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To have control over your resources, as well as cost monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.cdk.ts:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Project&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blocks-chatbot-ia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sandboxMode&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sandbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Team&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dev&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blocksStack&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CostCenter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chatbot-ia&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Short stack names&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes resources cannot be created if your project name is too long, so you can change the base name of your stack since resources are created with this prefix. In this case, I made changes so the stack would be the project name defined in the package:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;index.cdk.ts:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stackName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;sandboxMode&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;`-sandbox`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blocksStack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;BlocksStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stackName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;backendHandlerPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.handler.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;backendCDKPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bedrock quotas in Organizations&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your account is part of an organization, remember that you must set the quotas for Bedrock models, otherwise you won't be able to verify the model responses.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Region bug in @strands-agents/sdk&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The @aws-blocks/bb-agent block internally uses the @strands-agents/sdk module in its latest version available at the time of testing (1.7.0), to save agent conversations in S3. However, this module by default points to the us-east-1 region, so when trying to use the agent in another region you might encounter issues. To fix this, you only need to make the following change:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;node_modules/@strands-agents/sdk/dist/src/session/s3-storage.js:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_s3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;s3Client&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;S3Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;us-east-1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this change, it will now check the region environment variable by default so you can see the history of your conversations. This fix is for that version. I filed report #120 to the AWS Blocks framework maintenance team and it was resolved, so it's unlikely you'll encounter this error anymore. Here are the details of the fix they applied:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aws-devtools-labs/aws-blocks/issues/120" rel="noopener noreferrer"&gt;https://github.com/aws-devtools-labs/aws-blocks/issues/120&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After finishing the sandbox tests, I could see a CloudFormation with the various created resources. In this case, it is possible to better track them thanks to the tags, which identify which project each resource belongs to.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0akeyp8l90i8tubgxvc9.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0akeyp8l90i8tubgxvc9.png" alt=" " width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Deployment
&lt;/h2&gt;

&lt;p&gt;Having completed the tests in the sandbox, the only thing left is to deploy so the application is accessible to everyone. It is a satisfying experience, since this framework allows you to take stable and secure applications to production using serverless architectures. For this step, the difference from the sandbox is that static hosting is generated, stored in S3 and distributed by CloudFront. The deployment time was 12 minutes.&lt;/p&gt;

&lt;p&gt;Below we can see the chatbot working in the production environment.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxixt65har0ulhp21mssz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxixt65har0ulhp21mssz.png" alt=" " width="451" height="764"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Resource Cleanup
&lt;/h2&gt;

&lt;p&gt;After testing and to avoid incurring costs, I destroyed the created infrastructure. This is as simple as running the following commands:&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run sandbox:destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Delete CDK&lt;/strong&gt; (keep in mind that it does not generate costs as long as no assets are transferred):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3 &lt;span class="nb"&gt;rm &lt;/span&gt;s3://cdk-hnb659fds-assets-xxxxx-&lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt;
aws cloudformation delete-stack &lt;span class="nt"&gt;--stack-name&lt;/span&gt; CDKToolkit &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;region&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  About the author
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Luis Fernando de León&lt;/strong&gt; — AWS Community Builder 🇬🇹&lt;/p&gt;

&lt;p&gt;📸 Instagram: instagram.com/luisenlanube&lt;br&gt;
📝 DEV: dev.to/luisferdeleon&lt;br&gt;
👤 Facebook: facebook.com/luisenlanube&lt;br&gt;
💼 LinkedIn: linkedin.com/in/luisfdeleonramirez&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscdk</category>
      <category>awscommunity</category>
      <category>serverless</category>
    </item>
    <item>
      <title>¿Para que sirve Kubernetes (k8s)?</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Mon, 18 May 2026 03:31:32 +0000</pubDate>
      <link>https://dev.to/luisferdeleon/para-que-sirve-kubernetes-k8s-546a</link>
      <guid>https://dev.to/luisferdeleon/para-que-sirve-kubernetes-k8s-546a</guid>
      <description>&lt;p&gt;Kubernetes es una plataforma de código abierto para la orquestación de contenedores, en muchos casos es una tecnología que no tiene mucha aceptación por la complejidad que puede representar, sin embargo, en escenarios donde las arquitecturas pueden llegar a crear demasiado, puede ser un aliado estratégico para la administración de estos ambientes.&lt;br&gt;
AWS provee el servicio de EKS, el cual permite el uso de Kubernetes de forma sencilla al administrar por nosotros el plano de control, lo cual permite que podamos ir directo al despliegue de nuestras aplicaciones y para conocer más sobre este servicio estaré realizando un proyecto que pueda hacer uso de la mayor parte de sus características.&lt;/p&gt;

&lt;p&gt;¡Acompáñame durante estas semanas a ir conociendo más a fondo de este servicio!&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%2Fuw71ked5qgn3cs4tavcl.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%2Fuw71ked5qgn3cs4tavcl.png" alt=" " width="800" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>awscommunitybuilders</category>
      <category>kubernetes</category>
      <category>aws</category>
      <category>containers</category>
    </item>
    <item>
      <title>Application Load Balancer de EKS se desvincula de WAF</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Wed, 15 Apr 2026 03:40:57 +0000</pubDate>
      <link>https://dev.to/aws-builders/application-load-balancer-de-eks-se-desvincula-de-waf-38g1</link>
      <guid>https://dev.to/aws-builders/application-load-balancer-de-eks-se-desvincula-de-waf-38g1</guid>
      <description>&lt;p&gt;La creación de recursos fuera de infraestructura como código suele darnos sorpresas, regularmente muchos dan mantenimiento a su infraestructura a través de cloudformation, sin embargo en algunos servicios es recomendable que se tome en cuenta la documentación oficial para prevenir imprevistos que puedan ponernos en aprietos.&lt;/p&gt;

&lt;p&gt;Hace unos días revisando mi infraestructura la cual se compone de varios clústeres de kubernetes, los cuales aún utilizan ingress controler para definir los paths que dirigen a los servicios publicados, dentro de estos ingress utilicé la función de que automáticamente al crearlos se generara un balanceador de aplicaciones dentro de la infraestructura de AWS, todo había ido muy bien, hasta que hice la actualización de versión de kubernetes.&lt;/p&gt;

&lt;p&gt;Todo funcionó correctamente, hice mi actualización a la versión 1.33 de Kubernetes en EKS y todo fue sencillo como siempre, inicialmente hice la actualización de mi plano de control, tratando de ser muy ordenado (En lo personal me gusta realizarlo desde el cli), de la siguiente forma.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Verifiqué la versión actual del clúster: 
       aws eks describe-cluster --name eks-cluster-infraestructura --query cluster.version --output text

2. Actualicé el plano de control:
       aws eks update-cluster-version --name eks-cluster-infraestructura  --kubernetes-version 1.33 --output json

3. Actualicé los grupos de nodos:
      aws eks update-nodegroup-version --cluster-name eks-cluster-infraestructura --nodegroup-name ng-cluster-infraestructura --kubernetes-version 1.33

4. Y finalmente actualicé los complementos del clúster:
     aws eks update-addon --cluster-name eks-cluster-infraestructura  --addon-name coredns --addon-version v1.13.2-eksbuild.1 --configuration-values '{}'
     aws eks update-addon --cluster-name eks-cluster-infraestructura   --addon-name vpc-cni --addon-version v1.21.1-eksbuild.5  --configuration-values '{}'
     aws eks update-addon --cluster-name eks-cluster-infraestructura  --addon-name kube-proxy --addon-version v1.33.9-eksbuild.2   --configuration-values '{}'
     aws eks update-addon --cluster-name eks-cluster-infraestructura   --addon-name amazon-cloudwatch-observability --addon-version  v5.2.2-eksbuild.1   --configuration-values '{}'
     aws eks update-addon --cluster-name eks-cluster-infraestructura  --addon-name eks-pod-identity-agent --addon-version  v1.3.10-eksbuild.2 -  --configuration-values '{}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Como dato adicional les recomiendo esta actualización del complemento de amazon-cloudwatch-observability, acá ya podrán integrar el uso de applications signals (APM) el cual permite un monitoreo a detalle de lo que puede estar pasando en cada carga de trabajo dentro de tu clúster de EKS.    &lt;/p&gt;

&lt;p&gt;Hasta el momento todo iba muy bien, la actualización fue exitosa, no hubo necesidad de realizar cambios adicionales, sin embargo para revisar que todo estuviera bien hice algunas pruebas y vaya sorpresa, resulta que el web ACL que tenía vinculado el balanceador del cluster, ya no tenía recursos vinculados, luego de leer a fondo la documentación pude observar que es necesario que dentro de la definición de mi recurso Ingress debo vincular el ARN del web ACL, y esto sucede porqué cuando se vincula manualmente el balanceador desde la consola de AWS esa configuración termina siendo efímera, solamente existirá mientras no hayan cambios en el clúster, el archivo yaml de tu ingress no tiene idea de que en algún momento vinculaste el balanceador a un WAF, por lo que al actualizar el clúster este toma la definición inicial del YAML del ingress y al no estar declarado el vinculo al WAF asume que no debe estar ahí.&lt;/p&gt;

&lt;p&gt;Es por eso que para que no te suceda esto, te dejaré la forma en la cual debes agregar el ARN del WAF a tu ingress.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: mi-app-web
  annotations:
    # En esta línea debes agregar el ARN de tu web ACL 
    alb.ingress.kubernetes.io/wafv2-acl-arn: arn:aws:wafv2:region:123456789012:regional/webacl/nombre-waf/a1b2c3d4...
spec:
  ingressClassName: alb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;La propiedad en el recurso de ingress ha sido permitida desde hace varios años, sin embargo el adoptar infraestructura que no fue creada por nosotros puede generar inconvenientes como este que en muchos casos genera confusión.&lt;/p&gt;

</description>
      <category>awscommunitybuilder</category>
      <category>aws</category>
      <category>eks</category>
      <category>waf</category>
    </item>
    <item>
      <title>Billing and Cost Manager (Administración de facturación y costos)</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Thu, 19 Mar 2026 05:28:43 +0000</pubDate>
      <link>https://dev.to/aws-builders/billing-and-cost-manager-administracion-de-facturacion-y-costos-5ap</link>
      <guid>https://dev.to/aws-builders/billing-and-cost-manager-administracion-de-facturacion-y-costos-5ap</guid>
      <description>&lt;p&gt;Cuando inicie a conocer sobre los servicios de AWS, me generaba miedo el no saber utilizar los créditos de la capa gratuita y tener que pagar una factura muy costosa solamente por hacer pruebas, por lo que cada vez que pensaba en crear una cuenta recordaba eso y no lo hacía, sin embargo existe un servicio dentro de la consola de AWS llamado "Gestión de facturación y costes de AWS", a través de este es posible la generación de reportes y el monitoreo constante de los costos que estamos generando en la consola, cuando descubrí el uso de esto tuve paz al saber que no tendría que pagar cuando estuviera utilizando la capa gratuita, a continuación te dejo un artículo donde te explico cómo crear estos presupuestos.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Al iniciar sesión en  tu cuenta debes ingresar al servicio de  &lt;strong&gt;"Billing and Cost Manager (Administración de facturación y costos"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhn2x1af82in347x9rdni.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%2Fhn2x1af82in347x9rdni.png" alt="Captura de pantalla 1 - Servicio Billing" width="716" height="125"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selecciona la opción de &lt;strong&gt;"Budgets"&lt;/strong&gt; (Presupuestos) &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Para este ejercicio crearemos un presupuesto, el cual nos permitirá saber el total gastado hasta el momento, tomando como referencia que el máximo a gastar por mes serán 50 dólares, para esto  utilizaremos la opción de plantillas simplificadas, lo cual utilizará las configuraciones recomendadas, pudiendo cambiar algunas de estas después de haber creado el presupuesto (Alertas configurables).&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%2Fo67yzl2vvbq8w0kv5p3n.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%2Fo67yzl2vvbq8w0kv5p3n.png" alt="Captura de pantalla 3 - Crear Presupuesto" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al finalizar la creación del presupuesto se listarán los presupuestos disponibles en esta sección daremos clic sobre el presupuesto creado para realizar la configuración de las alertas.&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%2Fb8qihb8to4cn5dtxidia.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%2Fb8qihb8to4cn5dtxidia.png" alt="Captura de pantalla 4 - Seleccionar Presupuesto Creado" width="797" height="106"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al editar el presupuesto, en el paso 1 se visualizará el presupuesto creado, en esta sección se deberá indicar el periodo para el cual se asignará el presupuesto, así como el mes en el cual se iniciará la evaluación del presupuesto.&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%2Ft42qoor9vqs5lrljzaep.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%2Ft42qoor9vqs5lrljzaep.png" alt="Captura de pantalla 5 - Editar Paso 1" width="800" height="442"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el paso 2 se configurarán tres alertas las cuales nos informarán cuando alguna de estas se cumpla, las condiciones serán las siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cuando el total del consumo exceda el 25%&lt;/li&gt;
&lt;li&gt;Cuando el total del consumo exceda el 50%&lt;/li&gt;
&lt;li&gt;Cuando el total del consumo exceda el 90%&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%2F6xvhc5g1u2t0wxq6k2hm.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%2F6xvhc5g1u2t0wxq6k2hm.png" alt="Captura de pantalla 6 - Configurar Alertas Paso 2" width="800" height="467"&gt;&lt;/a&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%2Fi2jli8iortux3eeivwxt.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%2Fi2jli8iortux3eeivwxt.png" alt="Captura de pantalla 6-1 - Configurar Alertas Paso 2" width="799" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A cada alerta podremos indicarle un máximo de 10 direcciones de correo electrónico a las cuales se notificará, con la finalidad de mantener un control sobre los recursos que podamos dejar encendidos por equivocación, y poder tomar acciones correctivas de forma manual para evitar el incremento de gastos.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el paso 3  se presentará un resumen de las alertas y las acciones que se tendrán cuando estas se cumplan (tomar en cuenta que el uso de acciones personalizadas podría incurrir en un gasto adicional, por lo cual con fines de prueba únicamente se establece la notificación por correo electrónico).&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%2Fxtmdxei4m7c8j5ubztsk.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%2Fxtmdxei4m7c8j5ubztsk.png" alt="Captura de pantalla 7 - Resumen Alertas Paso 3" width="800" height="480"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En el paso 4 se generará un resumen con todas tus configuraciones realizadas en el presupuesto, al dar clic en guardar todas las configuraciones se aplicarán, de esta forma se habrá creado el presupuesto para monitorear el total consumido en tu cuenta.&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%2Fdfnogzjt8r7bmvtd0hd0.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%2Fdfnogzjt8r7bmvtd0hd0.png" alt="Captura de pantalla 8 - Guardar Paso 4" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Bonus
&lt;/h3&gt;

&lt;p&gt;Si prefieres tener un resumen de lo que recopilan las alertas podrás configurar reportes diarios que lleguen a tu correo electrónico en el cual tendrás el detalle del consumo hasta el final del día.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Ingresa a la opción &lt;strong&gt;"Budgets reports (Reportes de presupuesto)"&lt;/strong&gt; y dar clic sobre la opción de crear reporte, al visualizar la configuración inicial podrás seleccionar el presupuesto al cual deseas dar seguimiento y establecer la frecuencia del envío, para este ejercicio se seleccionará diario, para que el correo sea enviado al final del día con los datos recopilados por la alerta.&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%2Farxhr58jc634z26icp0w.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%2Farxhr58jc634z26icp0w.png" alt="Captura de pantalla B1 - Reportes de Presupuesto" width="799" height="386"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al final del día recibirás un correo en el cual tendrás el resumen de tus gastos.&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%2Ffzbkwpbmnv23sil8y9ic.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%2Ffzbkwpbmnv23sil8y9ic.png" alt="Captura de pantalla B2 - Ejemplo de Correo" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Recuerda que el crear presupuestos para seguimiento de costos no tendrá ningún valor en tu factura, siempre y cuando sean alertas básicas y con notificación a un máximo de 10 correos electrónicos y sin el uso de acciones correctivas de forma automática.&lt;/p&gt;

&lt;p&gt;Accede al siguiente enlace para leer la documentación oficial: &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/create-budget-report.html" rel="noopener noreferrer"&gt;Documentación AWS Cost Management&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscommunity</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Dockerfile</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Tue, 10 Mar 2026 02:29:42 +0000</pubDate>
      <link>https://dev.to/aws-builders/dockerfile-3ba</link>
      <guid>https://dev.to/aws-builders/dockerfile-3ba</guid>
      <description>&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%2Fs0jtcr9gurqa6poortf0.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%2Fs0jtcr9gurqa6poortf0.png" alt=" " width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El traslado de aplicaciones entre ambientes sigue siendo un problema constante, ya que pueden utilizar diversos tipos de servidores, sistemas operativos, dependencias, etc. &lt;/p&gt;

&lt;p&gt;Pero esto tiene una solución muy sencilla, el uso de contenedores facilita el traslado de entornos de trabajo generando copias inmutables,  las cuales no pueden tener cambios posteriores a su compilación, para realizar esto se hace uso de un archivo de texto plano en el cual se establecen las condiciones para la generación del contenedor.&lt;/p&gt;

&lt;p&gt;Dockerfile, este archivo contiene una serie de instrucciones en este caso nuestro robot ensamblador, que se encarga de la construcción del contenedor siguiendo paso a paso las indicaciones proporcionadas, este proceso consiste en la creación de diversas capas que contienen los elementos que serán utilizados.&lt;/p&gt;

&lt;p&gt;Es importante conocer estas instrucciones y las acciones que pueden realizar, esto facilitará la administración de la infraestructura de las aplicaciones sin afectar el funcionamiento interno de las aplicaciones, las instrucciones más comunes son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FROM&lt;/strong&gt;: Define una base para la imagen, normalmente acá se hacen uso de sistemas operativos optimizados, normalmente se dividen en sistemas operativos completos y mínimos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RUN&lt;/strong&gt;: A través de esta instrucción ejecuta un comando sobre una capa nueva, también es posible utilizarla para le ejecución de comandos shell.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WORKDIR&lt;/strong&gt;: Permite situarse sobre un directorio específico.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;COPY&lt;/strong&gt;:  Copia nuevos archivos a la imagen del contenedor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CMD&lt;/strong&gt;:  Permite que puedan ejecutarse comandos al iniciar el contenedor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora crearemos un ejemplo sencillo para que puedas interactuar con docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTA&lt;/strong&gt;: Para este ejercicio haremos uso del Subsistema de Windows para Linux (WSL) con docker instalado.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Crearemos una carpeta en la cual desarrollaremos la creación de nuestra imagen&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creamos un archivo sin extensión llamado Dockerfile&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Agregaremos las siguientes líneas dentro del archivo &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Usa una imagen mínima - Alpine Linux
FROM alpine:latest

# Ejecuta un comando para identificar el progreso de la construcción
RUN echo "Construyendo mi primera imagen desde el Dockerfile..."

# Define el comando por defecto que se ejecutará al iniciar el contenedor
CMD ["echo", "¡Hola mundo desde mi primer imagen en docker!"]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generaremos la imagen por primera vez a través del siguiente comando:&lt;br&gt;
    &lt;code&gt;docker build -t mi-hola-mundo .&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deberíamos ver algo similar a esta salida.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Ffbc8jjeegwu2q961xu77.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%2Ffbc8jjeegwu2q961xu77.png" alt=" " width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Verificaremos que la imagen fue creada correctamente a través del siguiente comando:&lt;br&gt;
    &lt;code&gt;Docker images&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deberemos ver nuestra imagen lista para ser utilizada&lt;br&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%2Fnnsxf9vh3pe7j41i5ph7.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%2Fnnsxf9vh3pe7j41i5ph7.png" alt=" " width="798" height="15"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ejecutaremos la imagen, cabe mencionar que usaremos la opción --rm para que docker elimine la imagen cuando esta termine de utilizarse.&lt;br&gt;
    &lt;code&gt;docker run --rm mi-hola-mundo&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Obtendrás la siguiente salida:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;¡Hola mundo desde mi primera imagen en docker!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Acá habrás creado tu primera imagen de Docker, esto será el inicio de muchas imágenes que crearas, las cuales podrás modificar para mejores resultados.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;¿Quieres saber más de &lt;strong&gt;docker&lt;/strong&gt;?, ingresa al siguiente enlace: &lt;a href="https://docs.docker.com/build/concepts/dockerfile/" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la nube de AWS podrás hacer uso los contenedores que crees en diferentes servicios como ECS y EKS, te invito a que puedas conocer estos servicios &lt;br&gt;
ECS: &lt;a href="https://aws.amazon.com/es/ecs/" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;br&gt;
EKS: &lt;a href="https://aws.amazon.com/es/eks/" rel="noopener noreferrer"&gt;Link&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Y recuerda que puedes obtener hasta 200 dólares en la capa gratuita de AWS para hacer tus pruebas, si quieres conocer más de esto, ingresa al siguiente enlace: &lt;a href="https://aws.amazon.com/es/free/" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;#Containers #Dockerfile #AWS #AWSComunityBuilders #ECS #EKS&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>containers</category>
      <category>docker</category>
      <category>awscomunitybuilders</category>
    </item>
    <item>
      <title>¿Qué es un contenedor?</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Thu, 05 Mar 2026 01:09:16 +0000</pubDate>
      <link>https://dev.to/luisferdeleon/que-es-un-contenedor-2498</link>
      <guid>https://dev.to/luisferdeleon/que-es-un-contenedor-2498</guid>
      <description>&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%2Fuk7zp9ztwqfsnw42bzca.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%2Fuk7zp9ztwqfsnw42bzca.png" alt=" " width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los contenedores son elementos de transporte o cajas de almacenamiento que son utilizadas para facilitar el traslado de diversos objetos.&lt;/p&gt;

&lt;p&gt;¡Ahora imaginate hacer todo esto con software!&lt;/p&gt;

&lt;p&gt;En muchas ocasiones necesitamos trasladar software a un ambiente productivo, sin embargo las versiones de dependencias o sistemas operativos generan comportamientos distintos al trasladarlo, es por ello que en 2013 buscando solucionar este problema se lanzó una tecnología llamada Docker que buscaba empaquetar el software haciendo uso de sistemas operativos ligeros para aumentar la eficiencia de los servidores y manteniendo las versiones de dependencias utilizadas.&lt;/p&gt;

&lt;p&gt;Quieres conocer más sobre esta tecnología, puedes leer el artículo completo acá: &lt;a href="https://www.docker.com/resources/what-container/" rel="noopener noreferrer"&gt;Link&lt;/a&gt; &lt;/p&gt;

</description>
      <category>containers</category>
      <category>aws</category>
      <category>awscomunitybuilders</category>
      <category>cloudarchitecture</category>
    </item>
    <item>
      <title>💡☁️ Ciclo de operaciones en la nube</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Thu, 05 Mar 2026 00:12:41 +0000</pubDate>
      <link>https://dev.to/luisferdeleon/ciclo-de-operaciones-en-la-nube-5646</link>
      <guid>https://dev.to/luisferdeleon/ciclo-de-operaciones-en-la-nube-5646</guid>
      <description>&lt;p&gt;📈La creciente incursión de la tecnología en empresas y organizaciones requiere la administración adecuada de las cargas de trabajo, para poder destacarse frente a sus competidores, es necesario fomentar la innovación y optimización de procesos, promoviendo la eficiencia en el desarrollo e implementación de software en producción.&lt;/p&gt;

&lt;p&gt;Es por ello que es importante conocer el ciclo de operaciones en la nube, el cual se desarrolla a través de las siguientes etapas:&lt;br&gt;
🚀 Despliegue.&lt;br&gt;
📊 Monitoreo.&lt;br&gt;
🔧 Mantenimiento.&lt;br&gt;
🔏 Seguridad. &lt;br&gt;
✅ Optimización.&lt;/p&gt;

&lt;p&gt;¿Quieres conocer más sobre el ciclo de operaciones en la nube?&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%2F0p1fcedd3e77l4r9z5q1.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%2F0p1fcedd3e77l4r9z5q1.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Puedes seguir el curso gratuito de AWS CloudOps Engineer en Skillbuilders, a través del siguiente enlace:&lt;br&gt;
&lt;a href="https://lnkd.in/eNf_kNtN" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>aws</category>
      <category>gt</category>
      <category>cloudoperationscycle</category>
    </item>
    <item>
      <title>AWS cloud Adoption Framework</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Thu, 05 Mar 2026 00:10:18 +0000</pubDate>
      <link>https://dev.to/luisferdeleon/aws-cloud-adoption-framework-475e</link>
      <guid>https://dev.to/luisferdeleon/aws-cloud-adoption-framework-475e</guid>
      <description>&lt;p&gt;🚀☁️¿Trabajas on-premises y te preguntas como iniciar con el traslado de cargas de trabajo a la nube?&lt;/p&gt;

&lt;p&gt;Es una pregunta muy común; Para llevar a cabo una migración es necesario definir una planificación que contribuya a la transformación digital y la entrega de resultados empresariales de forma eficiente.&lt;/p&gt;

&lt;p&gt;AWS Cloud Adoption Framework (AWS CAF) provee una serie de buenas prácticas que se enfocan en proveer conocimientos que faciliten a las organizaciones una migración eficaz a la nube de AWS.&lt;/p&gt;

&lt;p&gt;El CAF se enfoca en seis perspectivas principales:&lt;br&gt;
💰 Comercial&lt;br&gt;
🙋 Personas&lt;br&gt;
⚖ Gobernanza&lt;br&gt;
💻 Plataforma&lt;br&gt;
 🔐 Seguridad&lt;br&gt;
⚒ Operaciones&lt;br&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%2F06x1ihszn34nhsvzue2l.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%2F06x1ihszn34nhsvzue2l.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Quieres conocer más sobre AWS Cloud Adoption Framework ?&lt;/p&gt;

&lt;p&gt;Puedes leer el artículo completo acá&lt;br&gt;
&lt;a href="https://lnkd.in/eEFrieAv" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Cloud hashtag#AWS #gt #AWSCAF #CloudComputing #CloudArchitecture #Architecture #AWSCloudAdoptionFramework&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AWS Identity and Access Managment (IAM)</title>
      <dc:creator>Luis Fernando de León Ramírez</dc:creator>
      <pubDate>Thu, 05 Mar 2026 00:01:15 +0000</pubDate>
      <link>https://dev.to/luisferdeleon/aws-identity-and-access-managment-iam-1h2g</link>
      <guid>https://dev.to/luisferdeleon/aws-identity-and-access-managment-iam-1h2g</guid>
      <description>&lt;p&gt;🔐 AWS Identity and Access Managment (IAM) fortalece el control de los recursos en AWS, al crear una cuenta se establece un usuario raíz que tendrá acceso ilimitado a todos los servicios en la cuenta.&lt;/p&gt;

&lt;p&gt;Dentro del servicio de IAM existen identidades, las cuales pueden asociarse a diversas políticas que definen acciones a realizar con los servicios, los tipos de identidades son:&lt;/p&gt;

&lt;p&gt;🙋 Usuarios&lt;br&gt;
 👨‍👩‍👦‍👦 Grupos de usuarios&lt;br&gt;
👮Roles&lt;/p&gt;

&lt;p&gt;📜 Las políticas permiten establecer a detalle los permisos que tendrán las identidades para la interacción con los servicios de AWS&lt;/p&gt;

&lt;p&gt;➡️ Si quieres conocer más sobre IAM el sitio de AWS SkillBuilder ofrece una introducción a IAM en 10 minutos, ¿Quieres verlo?&lt;br&gt;
&lt;a href="https://lnkd.in/eg9QvWHN" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;➡️ Quieres saber más sobre IAM: &lt;a href="https://lnkd.in/eDffye-s" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbp9yhdygwti0qe1ux1mu.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%2Fbp9yhdygwti0qe1ux1mu.png" alt=" " width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;#Cloud #AWS #gt #SkillBuilder #IAM #CloudComputing #CloudArchitecture #Architecture&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>security</category>
      <category>spanish</category>
    </item>
  </channel>
</rss>
