/ notebook / test_agentcore_deployed_executed.ipynb
test_agentcore_deployed_executed.ipynb
  1  {
  2   "cells": [
  3    {
  4     "cell_type": "markdown",
  5     "id": "rkf3pvn7utl",
  6     "metadata": {},
  7     "source": [
  8      "# Test AgentCore Deployed Runtime\n",
  9      "\n",
 10      "This notebook tests the **deployed** AgentCore Runtime via `invoke-agent-runtime`.\n",
 11      "\n",
 12      "It validates:\n",
 13      "1. Text messages through the deployed endpoint\n",
 14      "2. Image processing (base64 encoded)\n",
 15      "3. Audio transcript processing\n",
 16      "4. Video analysis via TwelveLabs Pegasus\n",
 17      "5. Memory persistence across invocations (short-term + long-term)\n",
 18      "\n",
 19      "> **Prerequisites**: The `AgentAgentCoreStack` must be deployed successfully."
 20     ]
 21    },
 22    {
 23     "cell_type": "code",
 24     "execution_count": 1,
 25     "id": "npkagulzftq",
 26     "metadata": {
 27      "execution": {
 28       "iopub.execute_input": "2026-03-19T02:25:13.538544Z",
 29       "iopub.status.busy": "2026-03-19T02:25:13.538416Z",
 30       "iopub.status.idle": "2026-03-19T02:25:18.205049Z",
 31       "shell.execute_reply": "2026-03-19T02:25:18.204395Z"
 32      }
 33     },
 34     "outputs": [
 35      {
 36       "name": "stdout",
 37       "output_type": "stream",
 38       "text": [
 39        "\r\n",
 40        "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.2.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m26.0.1\u001b[0m\r\n",
 41        "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\r\n"
 42       ]
 43      },
 44      {
 45       "name": "stdout",
 46       "output_type": "stream",
 47       "text": [
 48        "Note: you may need to restart the kernel to use updated packages.\n"
 49       ]
 50      }
 51     ],
 52     "source": [
 53      "%pip install boto3 --quiet"
 54     ]
 55    },
 56    {
 57     "cell_type": "code",
 58     "execution_count": 2,
 59     "id": "6psoan3fp1",
 60     "metadata": {
 61      "execution": {
 62       "iopub.execute_input": "2026-03-19T02:25:18.207323Z",
 63       "iopub.status.busy": "2026-03-19T02:25:18.207158Z",
 64       "iopub.status.idle": "2026-03-19T02:25:18.342522Z",
 65       "shell.execute_reply": "2026-03-19T02:25:18.341931Z"
 66      }
 67     },
 68     "outputs": [
 69      {
 70       "name": "stdout",
 71       "output_type": "stream",
 72       "text": [
 73        "Custom botocore data path: /Users/eliaws/Documents/repositories/eli-cosas/whatsapp-ai-agent-sample-for-aws-agentcore/00-agent-agentcore/agent_files/deployment_package/botocore/data\n",
 74        "Use agentcore_boto3_session() to create clients for 'bedrock-agentcore'.\n"
 75       ]
 76      }
 77     ],
 78     "source": [
 79      "import os\n",
 80      "import botocore.loaders\n",
 81      "import botocore.session\n",
 82      "\n",
 83      "# Register the custom 'bedrock-agentcore' service model bundled in the deployment package.\n",
 84      "# The system boto3/botocore does not include this service yet.\n",
 85      "CUSTOM_DATA_PATH = os.path.abspath(\n",
 86      "    os.path.join(\n",
 87      "        os.path.dirname(\"__file__\"), \"..\",\n",
 88      "        \"00-agent-agentcore\", \"agent_files\", \"deployment_package\", \"botocore\", \"data\",\n",
 89      "    )\n",
 90      ")\n",
 91      "\n",
 92      "def agentcore_boto3_session(region: str) -> \"boto3.Session\":\n",
 93      "    \"\"\"Create a boto3 Session that knows about the bedrock-agentcore service.\"\"\"\n",
 94      "    bcore = botocore.session.get_session()\n",
 95      "    loader = botocore.loaders.Loader(\n",
 96      "        extra_search_paths=[CUSTOM_DATA_PATH],\n",
 97      "    )\n",
 98      "    bcore.register_component(\"data_loader\", loader)\n",
 99      "    return boto3.Session(botocore_session=bcore, region_name=region)\n",
100      "\n",
101      "print(f\"Custom botocore data path: {CUSTOM_DATA_PATH}\")\n",
102      "print(\"Use agentcore_boto3_session() to create clients for 'bedrock-agentcore'.\")"
103     ]
104    },
105    {
106     "cell_type": "markdown",
107     "id": "v2jzjg49g1",
108     "metadata": {},
109     "source": [
110      "## 1. Setup - Read stack outputs from SSM"
111     ]
112    },
113    {
114     "cell_type": "code",
115     "execution_count": 3,
116     "id": "qqn1v5531o",
117     "metadata": {
118      "execution": {
119       "iopub.execute_input": "2026-03-19T02:25:18.344330Z",
120       "iopub.status.busy": "2026-03-19T02:25:18.344207Z",
121       "iopub.status.idle": "2026-03-19T02:25:19.159641Z",
122       "shell.execute_reply": "2026-03-19T02:25:19.158508Z"
123      }
124     },
125     "outputs": [
126      {
127       "name": "stdout",
128       "output_type": "stream",
129       "text": [
130        "Runtime ARN:  arn:aws:bedrock-agentcore:us-east-1:851725483322:runtime/WhatsAppMultimodalAgentV2-44KEQ3EM5r\n",
131        "Runtime ID:   WhatsAppMultimodalAgentV2-44KEQ3EM5r\n",
132        "Memory ID:    WhatsAppAgentMemory-qxw05PGr8L\n",
133        "S3 Bucket:    agentagentcorestack-agentbucket35e5c65f-uv3yrrnfz9oh\n"
134       ]
135      }
136     ],
137     "source": [
138      "import json\n",
139      "import boto3\n",
140      "\n",
141      "REGION = \"us-east-1\"\n",
142      "\n",
143      "ssm = boto3.client(\"ssm\", region_name=REGION)\n",
144      "\n",
145      "def get_param(name):\n",
146      "    return ssm.get_parameter(Name=name)[\"Parameter\"][\"Value\"]\n",
147      "\n",
148      "AGENT_RUNTIME_ARN = get_param(\"/agentcore/agent_runtime_arn\")\n",
149      "S3_BUCKET = get_param(\"/agentcore/s3_bucket_name\")\n",
150      "MEMORY_ID = get_param(\"/agentcore/memory_id\")\n",
151      "\n",
152      "# Extract runtime ID from ARN (last segment after /runtime/)\n",
153      "AGENT_RUNTIME_ID = AGENT_RUNTIME_ARN.split(\"/\")[-1]\n",
154      "\n",
155      "print(f\"Runtime ARN:  {AGENT_RUNTIME_ARN}\")\n",
156      "print(f\"Runtime ID:   {AGENT_RUNTIME_ID}\")\n",
157      "print(f\"Memory ID:    {MEMORY_ID}\")\n",
158      "print(f\"S3 Bucket:    {S3_BUCKET}\")"
159     ]
160    },
161    {
162     "cell_type": "markdown",
163     "id": "dvudxedlt3m",
164     "metadata": {},
165     "source": [
166      "## 2. Helper - Invoke Agent Runtime\n",
167      "\n",
168      "Wraps the `bedrock-agentcore` data plane `invoke-agent-runtime` API.\n",
169      "\n",
170      "- `actor_id` identifies the **user** (long-term memory: facts, preferences)\n",
171      "- `session_id` identifies the **conversation** (short-term memory: turns)"
172     ]
173    },
174    {
175     "cell_type": "code",
176     "execution_count": 4,
177     "id": "gjuacz71oah",
178     "metadata": {
179      "execution": {
180       "iopub.execute_input": "2026-03-19T02:25:19.162700Z",
181       "iopub.status.busy": "2026-03-19T02:25:19.162517Z",
182       "iopub.status.idle": "2026-03-19T02:25:19.410132Z",
183       "shell.execute_reply": "2026-03-19T02:25:19.409690Z"
184      }
185     },
186     "outputs": [
187      {
188       "name": "stdout",
189       "output_type": "stream",
190       "text": [
191        "actor_id:   'wa-user-5730012345670000000000000' (33 chars)\n",
192        "session_id: 'wa-chat-5730012345670000000000000' (33 chars)\n",
193        "\n",
194        "Helper ready.\n"
195       ]
196      }
197     ],
198     "source": [
199      "session = agentcore_boto3_session(REGION)\n",
200      "agentcore = session.client(\"bedrock-agentcore\")\n",
201      "\n",
202      "# IDs must be >= 33 chars, padded as the agent expects\n",
203      "TEST_PHONE = \"5730012345670000000000\"\n",
204      "ACTOR_ID  = f\"wa-user-{TEST_PHONE}\".ljust(33, \"0\")   # identifies the USER\n",
205      "SESSION_ID = f\"wa-chat-{TEST_PHONE}\".ljust(33, \"0\")   # identifies the CONVERSATION\n",
206      "\n",
207      "print(f\"actor_id:   '{ACTOR_ID}' ({len(ACTOR_ID)} chars)\")\n",
208      "print(f\"session_id: '{SESSION_ID}' ({len(SESSION_ID)} chars)\")\n",
209      "\n",
210      "\n",
211      "def invoke_agent(prompt: str, media: dict = None) -> str:\n",
212      "    \"\"\"Invoke the deployed AgentCore Runtime.\n",
213      "    \n",
214      "    Args:\n",
215      "        prompt: User text message.\n",
216      "        media: Optional media dict (type, format, data, s3_uri).\n",
217      "    \n",
218      "    Returns:\n",
219      "        Agent response text.\n",
220      "    \"\"\"\n",
221      "    payload = {\n",
222      "        \"prompt\": prompt,\n",
223      "        \"actor_id\": ACTOR_ID,\n",
224      "    }\n",
225      "    if media:\n",
226      "        payload[\"media\"] = media\n",
227      "\n",
228      "    response = agentcore.invoke_agent_runtime(\n",
229      "        agentRuntimeArn=AGENT_RUNTIME_ARN,\n",
230      "        runtimeSessionId=SESSION_ID,\n",
231      "        runtimeUserId=ACTOR_ID,\n",
232      "        payload=json.dumps(payload).encode(\"utf-8\"),\n",
233      "    )\n",
234      "\n",
235      "    content = []\n",
236      "    for chunk in response.get(\"response\", []):\n",
237      "        if isinstance(chunk, bytes):\n",
238      "            content.append(chunk.decode(\"utf-8\"))\n",
239      "        elif isinstance(chunk, dict) and \"bytes\" in chunk:\n",
240      "            content.append(chunk[\"bytes\"].decode(\"utf-8\"))\n",
241      "\n",
242      "    response_text = \"\".join(content)\n",
243      "\n",
244      "    try:\n",
245      "        response_json = json.loads(response_text)\n",
246      "        return response_json.get(\"result\", response_text)\n",
247      "    except json.JSONDecodeError:\n",
248      "        return response_text\n",
249      "\n",
250      "\n",
251      "print(\"\\nHelper ready.\")"
252     ]
253    },
254    {
255     "cell_type": "markdown",
256     "id": "qd0mjj0p3u9",
257     "metadata": {},
258     "source": [
259      "## 3. Test - Text Message"
260     ]
261    },
262    {
263     "cell_type": "code",
264     "execution_count": 5,
265     "id": "s47s29w9sr9",
266     "metadata": {
267      "execution": {
268       "iopub.execute_input": "2026-03-19T02:25:19.411359Z",
269       "iopub.status.busy": "2026-03-19T02:25:19.411274Z",
270       "iopub.status.idle": "2026-03-19T02:25:30.504796Z",
271       "shell.execute_reply": "2026-03-19T02:25:30.504037Z"
272      }
273     },
274     "outputs": [
275      {
276       "name": "stdout",
277       "output_type": "stream",
278       "text": [
279        "¡Hola Carlos! Un gusto conocerte. Soy tu asistente de WhatsApp y puedo ayudarte con muchas cosas:\n",
280        "\n",
281        "📱 **Texto y conversaciones**\n",
282        "- Responder preguntas sobre cualquier tema\n",
283        "- Ayudarte con tareas, estudios o trabajo\n",
284        "- Traducir textos entre idiomas\n",
285        "- Escribir y revisar documentos\n",
286        "\n",
287        "🖼️ **Imágenes**\n",
288        "- Describir y analizar fotos que me envíes\n",
289        "- Leer texto en imágenes\n",
290        "- Identificar objetos, personas o lugares\n",
291        "\n",
292        "📄 **Documentos**\n",
293        "- Leer y resumir PDFs, Word, etc.\n",
294        "- Ayudarte a entender contenido complejo\n",
295        "- Extraer información importante\n",
296        "\n",
297        "🎵 **Audio**\n",
298        "- Transcribir mensajes de voz\n",
299        "- Analizar contenido de audio\n",
300        "- Convertir audio a texto\n",
301        "\n",
302        "🎥 **Videos**\n",
303        "- Analizar contenido de videos\n",
304        "- Describir lo que sucede en el video\n",
305        "- Transcribir audio del video\n",
306        "\n",
307        "💡 **Otros servicios**\n",
308        "- Consejos y recomendaciones\n",
309        "- Resolución de problemas\n",
310        "- Lluvia de ideas\n",
311        "- Apoyo con decisiones\n",
312        "\n",
313        "¿En qué te gustaría que te ayude hoy, Carlos? ¡Puedes enviarme texto, fotos, documentos, audios o videos!\n",
314        "\n"
315       ]
316      }
317     ],
318     "source": [
319      "response = invoke_agent(\"Hola! Mi nombre es Carlos y soy de Colombia. Que puedes hacer por mi?\")\n",
320      "print(response)"
321     ]
322    },
323    {
324     "cell_type": "markdown",
325     "id": "aufjgi6uzh5",
326     "metadata": {},
327     "source": [
328      "## 4. Test - Memory Recall (same session)\n",
329      "\n",
330      "The agent should remember the name and country from the previous turn."
331     ]
332    },
333    {
334     "cell_type": "code",
335     "execution_count": 6,
336     "id": "fryovfsb9qv",
337     "metadata": {
338      "execution": {
339       "iopub.execute_input": "2026-03-19T02:25:30.511868Z",
340       "iopub.status.busy": "2026-03-19T02:25:30.511722Z",
341       "iopub.status.idle": "2026-03-19T02:25:34.307244Z",
342       "shell.execute_reply": "2026-03-19T02:25:34.306867Z"
343      }
344     },
345     "outputs": [
346      {
347       "name": "stdout",
348       "output_type": "stream",
349       "text": [
350        "Te llamas **Carlos** y eres de **Colombia** 🇨🇴\n",
351        "\n",
352        "Me lo dijiste en tu primer mensaje cuando te presentaste. ¡Es un gusto conocerte!\n",
353        "\n",
354        "¿Hay algo específico en lo que pueda ayudarte hoy?\n",
355        "\n"
356       ]
357      }
358     ],
359     "source": [
360      "response = invoke_agent(\"Como me llamo y de donde soy?\")\n",
361      "print(response)"
362     ]
363    },
364    {
365     "cell_type": "markdown",
366     "id": "fvjpvl23lj5",
367     "metadata": {},
368     "source": [
369      "## 5. Test - Image Processing\n",
370      "\n",
371      "Sends a base64-encoded image to the agent via the deployed runtime."
372     ]
373    },
374    {
375     "cell_type": "code",
376     "execution_count": 7,
377     "id": "i0ty1gpxsip",
378     "metadata": {
379      "execution": {
380       "iopub.execute_input": "2026-03-19T02:25:34.308700Z",
381       "iopub.status.busy": "2026-03-19T02:25:34.308617Z",
382       "iopub.status.idle": "2026-03-19T02:25:36.235896Z",
383       "shell.execute_reply": "2026-03-19T02:25:36.235460Z"
384      }
385     },
386     "outputs": [
387      {
388       "ename": "RuntimeClientError",
389       "evalue": "An error occurred (RuntimeClientError) when calling the InvokeAgentRuntime operation: Received error (500) from runtime. Please check your CloudWatch logs for more information.",
390       "output_type": "error",
391       "traceback": [
392        "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
393        "\u001b[31mRuntimeClientError\u001b[39m                        Traceback (most recent call last)",
394        "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[7]\u001b[39m\u001b[32m, line 11\u001b[39m\n\u001b[32m      8\u001b[39m     ext = Path(IMAGE_PATH).suffix.lstrip(\u001b[33m\"\u001b[39m\u001b[33m.\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m      9\u001b[39m     fmt = {\u001b[33m\"\u001b[39m\u001b[33mjpg\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mjpeg\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mjpeg\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mjpeg\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mpng\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mpng\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mgif\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mgif\u001b[39m\u001b[33m\"\u001b[39m, \u001b[33m\"\u001b[39m\u001b[33mwebp\u001b[39m\u001b[33m\"\u001b[39m: \u001b[33m\"\u001b[39m\u001b[33mwebp\u001b[39m\u001b[33m\"\u001b[39m}.get(ext, \u001b[33m\"\u001b[39m\u001b[33mjpeg\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m---> \u001b[39m\u001b[32m11\u001b[39m     response = \u001b[43minvoke_agent\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m     12\u001b[39m \u001b[43m        \u001b[49m\u001b[43mprompt\u001b[49m\u001b[43m=\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mDescribe esta imagen en detalle.\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[32m     13\u001b[39m \u001b[43m        \u001b[49m\u001b[43mmedia\u001b[49m\u001b[43m=\u001b[49m\u001b[43m{\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mtype\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mimage\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mformat\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mfmt\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mdata\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mimage_b64\u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m     14\u001b[39m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     15\u001b[39m     \u001b[38;5;28mprint\u001b[39m(response)\n\u001b[32m     16\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n",
395        "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 30\u001b[39m, in \u001b[36minvoke_agent\u001b[39m\u001b[34m(prompt, media)\u001b[39m\n\u001b[32m     27\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m media:\n\u001b[32m     28\u001b[39m     payload[\u001b[33m\"\u001b[39m\u001b[33mmedia\u001b[39m\u001b[33m\"\u001b[39m] = media\n\u001b[32m---> \u001b[39m\u001b[32m30\u001b[39m response = \u001b[43magentcore\u001b[49m\u001b[43m.\u001b[49m\u001b[43minvoke_agent_runtime\u001b[49m\u001b[43m(\u001b[49m\n\u001b[32m     31\u001b[39m \u001b[43m    \u001b[49m\u001b[43magentRuntimeArn\u001b[49m\u001b[43m=\u001b[49m\u001b[43mAGENT_RUNTIME_ARN\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m     32\u001b[39m \u001b[43m    \u001b[49m\u001b[43mruntimeSessionId\u001b[49m\u001b[43m=\u001b[49m\u001b[43mSESSION_ID\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m     33\u001b[39m \u001b[43m    \u001b[49m\u001b[43mruntimeUserId\u001b[49m\u001b[43m=\u001b[49m\u001b[43mACTOR_ID\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m     34\u001b[39m \u001b[43m    \u001b[49m\u001b[43mpayload\u001b[49m\u001b[43m=\u001b[49m\u001b[43mjson\u001b[49m\u001b[43m.\u001b[49m\u001b[43mdumps\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpayload\u001b[49m\u001b[43m)\u001b[49m\u001b[43m.\u001b[49m\u001b[43mencode\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mutf-8\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[32m     35\u001b[39m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m     37\u001b[39m content = []\n\u001b[32m     38\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m chunk \u001b[38;5;129;01min\u001b[39;00m response.get(\u001b[33m\"\u001b[39m\u001b[33mresponse\u001b[39m\u001b[33m\"\u001b[39m, []):\n",
396        "\u001b[36mFile \u001b[39m\u001b[32m~/.pyenv/versions/3.11.7/lib/python3.11/site-packages/botocore/client.py:569\u001b[39m, in \u001b[36mClientCreator._create_api_method.<locals>._api_call\u001b[39m\u001b[34m(self, *args, **kwargs)\u001b[39m\n\u001b[32m    565\u001b[39m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m(\n\u001b[32m    566\u001b[39m         \u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mpy_operation_name\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m() only accepts keyword arguments.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m    567\u001b[39m     )\n\u001b[32m    568\u001b[39m \u001b[38;5;66;03m# The \"self\" in this scope is referring to the BaseClient.\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m569\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m_make_api_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43moperation_name\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
397        "\u001b[36mFile \u001b[39m\u001b[32m~/.pyenv/versions/3.11.7/lib/python3.11/site-packages/botocore/client.py:1023\u001b[39m, in \u001b[36mBaseClient._make_api_call\u001b[39m\u001b[34m(self, operation_name, api_params)\u001b[39m\n\u001b[32m   1019\u001b[39m     error_code = error_info.get(\u001b[33m\"\u001b[39m\u001b[33mQueryErrorCode\u001b[39m\u001b[33m\"\u001b[39m) \u001b[38;5;129;01mor\u001b[39;00m error_info.get(\n\u001b[32m   1020\u001b[39m         \u001b[33m\"\u001b[39m\u001b[33mCode\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m   1021\u001b[39m     )\n\u001b[32m   1022\u001b[39m     error_class = \u001b[38;5;28mself\u001b[39m.exceptions.from_code(error_code)\n\u001b[32m-> \u001b[39m\u001b[32m1023\u001b[39m     \u001b[38;5;28;01mraise\u001b[39;00m error_class(parsed_response, operation_name)\n\u001b[32m   1024\u001b[39m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[32m   1025\u001b[39m     \u001b[38;5;28;01mreturn\u001b[39;00m parsed_response\n",
398        "\u001b[31mRuntimeClientError\u001b[39m: An error occurred (RuntimeClientError) when calling the InvokeAgentRuntime operation: Received error (500) from runtime. Please check your CloudWatch logs for more information."
399       ]
400      }
401     ],
402     "source": [
403      "import base64\n",
404      "from pathlib import Path\n",
405      "\n",
406      "IMAGE_PATH = \"imagen2.png\"\n",
407      "\n",
408      "if Path(IMAGE_PATH).exists():\n",
409      "    image_b64 = base64.b64encode(Path(IMAGE_PATH).read_bytes()).decode(\"utf-8\")\n",
410      "    ext = Path(IMAGE_PATH).suffix.lstrip(\".\")\n",
411      "    fmt = {\"jpg\": \"jpeg\", \"jpeg\": \"jpeg\", \"png\": \"png\", \"gif\": \"gif\", \"webp\": \"webp\"}.get(ext, \"jpeg\")\n",
412      "\n",
413      "    response = invoke_agent(\n",
414      "        prompt=\"Describe esta imagen en detalle.\",\n",
415      "        media={\"type\": \"image\", \"format\": fmt, \"data\": image_b64},\n",
416      "    )\n",
417      "    print(response)\n",
418      "else:\n",
419      "    print(f\"Image not found: {IMAGE_PATH}\")\n",
420      "    print(\"Place a test image in this directory and update IMAGE_PATH to test.\")"
421     ]
422    },
423    {
424     "cell_type": "markdown",
425     "id": "2qay65ftlal",
426     "metadata": {},
427     "source": [
428      "## 6. Test - Audio Transcript"
429     ]
430    },
431    {
432     "cell_type": "code",
433     "execution_count": 8,
434     "id": "dt5qn8xpp3",
435     "metadata": {
436      "execution": {
437       "iopub.execute_input": "2026-03-19T02:25:36.237485Z",
438       "iopub.status.busy": "2026-03-19T02:25:36.237405Z",
439       "iopub.status.idle": "2026-03-19T02:25:46.838828Z",
440       "shell.execute_reply": "2026-03-19T02:25:46.837748Z"
441      }
442     },
443     "outputs": [
444      {
445       "name": "stdout",
446       "output_type": "stream",
447       "text": [
448        "## 📸 **Descripción de la imagen:**\n",
449        "\n",
450        "La imagen muestra un **meme tecnológico** con una mujer joven sonriente de cabello castaño largo. La composición está dividida en dos mitades:\n",
451        "\n",
452        "**Lado izquierdo (rojo):** \n",
453        "- Fondo con efectos glitch y código\n",
454        "- Textos como \"ERROR\", \"BLOCKED\" \n",
455        "- Símbolos de advertencia (⚠️) y X rojas\n",
456        "- Representa problemas técnicos/bloqueos\n",
457        "\n",
458        "**Lado derecho (verde):**\n",
459        "- Fondo verde con símbolo de actualización/refresh\n",
460        "- Representa soluciones exitosas\n",
461        "\n",
462        "**Texto principal:** \"STEER, DON'T BLOCK\" en letras verdes grandes\n",
463        "\n",
464        "El meme sugiere un **consejo tecnológico**: en lugar de bloquear algo (lado rojo/error), es mejor redirigir o guiar (lado verde/éxito).\n",
465        "\n",
466        "---\n",
467        "\n",
468        "## 🎵 **Transcripción del audio:**\n",
469        "\n",
470        "*\"Necesito agendar una reunión para el martes a las 3 de la tarde con el equipo de marketing para hablar de la estrategia del Q4.\"*\n",
471        "\n",
472        "---\n",
473        "\n",
474        "¿Te ayudo a organizar esa reunión del martes, Carlos? Puedo ayudarte con la agenda o sugerencias para la estrategia de Q4.\n",
475        "\n"
476       ]
477      }
478     ],
479     "source": [
480      "response = invoke_agent(\n",
481      "    prompt=\"Procesa este audio\",\n",
482      "    media={\n",
483      "        \"type\": \"audio_transcript\",\n",
484      "        \"data\": \"Necesito agendar una reunion para el martes a las 3 de la tarde con el equipo de marketing para hablar de la estrategia del Q4.\",\n",
485      "    },\n",
486      ")\n",
487      "print(response)"
488     ]
489    },
490    {
491     "cell_type": "markdown",
492     "id": "scw6n059u3s",
493     "metadata": {},
494     "source": [
495      "## 7. Test - Video Analysis (TwelveLabs Pegasus)\n",
496      "\n",
497      "> Upload a test video to S3 first and update `VIDEO_S3_URI`.\n",
498      "> The TwelveLabs Pegasus model (`twelvelabs.pegasus-1-2-v1:0`) must be enabled in Bedrock."
499     ]
500    },
501    {
502     "cell_type": "code",
503     "execution_count": 9,
504     "id": "i162djhxyp",
505     "metadata": {
506      "execution": {
507       "iopub.execute_input": "2026-03-19T02:25:46.841767Z",
508       "iopub.status.busy": "2026-03-19T02:25:46.841560Z",
509       "iopub.status.idle": "2026-03-19T02:27:07.481108Z",
510       "shell.execute_reply": "2026-03-19T02:27:07.479457Z"
511      }
512     },
513     "outputs": [
514      {
515       "name": "stdout",
516       "output_type": "stream",
517       "text": [
518        "Uploaded Runtime.mp4 to s3://agentagentcorestack-agentbucket35e5c65f-uv3yrrnfz9oh/videos/Runtime.mp4\n"
519       ]
520      },
521      {
522       "name": "stdout",
523       "output_type": "stream",
524       "text": [
525        "## 🎥 **Análisis detallado del video:**\n",
526        "\n",
527        "### **📊 Resumen del contenido:**\n",
528        "Este video presenta **Amazon Bedrock Agent Runtime**, una solución para desplegar agentes de IA en producción de manera simplificada.\n",
529        "\n",
530        "### **👩‍💻 Presentadora:**\n",
531        "- Mujer joven de cabello largo y oscuro\n",
532        "- Habla directamente a la cámara con fondo morado\n",
533        "- Presenta el contenido de forma clara y técnica\n",
534        "\n",
535        "### **🎯 Mensaje principal:**\n",
536        "**Problema identificado:**\n",
537        "- Construir agentes de IA es fácil\n",
538        "- El **desafío real** es el despliegue en producción\n",
539        "- Requiere manejar: Docker files, pipelines CI/CD, políticas, balanceo de carga, infraestructura compleja\n",
540        "\n",
541        "### **💡 Solución presentada:**\n",
542        "\n",
543        "**🔧 Comandos clave mostrados:**\n",
544        "1. **Configuración del agente** - comando para setup inicial\n",
545        "2. **Lanzamiento del core** - deploy automático \n",
546        "3. **Destrucción del core** - cleanup con un comando\n",
547        "\n",
548        "**⚡ Beneficios automáticos:**\n",
549        "- Orquestadores de contenedores\n",
550        "- Seguridad basada en agentes  \n",
551        "- Aislamiento de sesiones\n",
552        "- Escalado automático\n",
553        "- Observabilidad integrada\n",
554        "\n",
555        "### **📺 Elementos visuales:**\n",
556        "- 🐱 Aparece un **gato** (elemento llamativo)\n",
557        "- ⚠️ **Icono de advertencia** rojo\n",
558        "- 💻 **Código de programación** en pantalla negra\n",
559        "- 🟣 **Fondo morado** constante\n",
560        "- 📝 Texto destacado: **\"YOUR AGENT IS NOW RUNNING FULLY SERVERLESS\"**\n",
561        "\n",
562        "### **🚀 Conclusión:**\n",
563        "**\"INVISIBLE INFRASTRUCTURE\"** - La infraestructura debe ser invisible hasta que se necesite, pero poderosa cuando se requiera. Todo esto con solo **dos comandos**.\n",
564        "\n",
565        "El video posiciona esta solución como **el comienzo** para construir agentes de IA de producción reales.\n",
566        "\n",
567        "¿Te interesa saber más sobre algún aspecto específico de esta tecnología, Carlos?\n",
568        "\n"
569       ]
570      }
571     ],
572     "source": [
573      "# Upload the local video to the stack's S3 bucket\n",
574      "s3_client = boto3.client(\"s3\", region_name=REGION)\n",
575      "s3_client.upload_file(\"Runtime.mp4\", S3_BUCKET, \"videos/Runtime.mp4\")\n",
576      "print(f\"Uploaded Runtime.mp4 to s3://{S3_BUCKET}/videos/Runtime.mp4\")\n",
577      "\n",
578      "VIDEO_S3_URI = f\"s3://{S3_BUCKET}/videos/Runtime.mp4\"\n",
579      "\n",
580      "response = invoke_agent(\n",
581      "    prompt=\"Analiza este video en detalle.\",\n",
582      "    media={\"type\": \"video\", \"s3_uri\": VIDEO_S3_URI},\n",
583      ")\n",
584      "print(response)"
585     ]
586    },
587    {
588     "cell_type": "markdown",
589     "id": "f284dasfvn",
590     "metadata": {},
591     "source": [
592      "## 8. Test - Document Processing\n",
593      "\n",
594      "> Place a test PDF in this directory and update `DOCUMENT_PATH`."
595     ]
596    },
597    {
598     "cell_type": "code",
599     "execution_count": 10,
600     "id": "tfz6pkrexrk",
601     "metadata": {
602      "execution": {
603       "iopub.execute_input": "2026-03-19T02:27:07.487829Z",
604       "iopub.status.busy": "2026-03-19T02:27:07.487505Z",
605       "iopub.status.idle": "2026-03-19T02:27:07.495390Z",
606       "shell.execute_reply": "2026-03-19T02:27:07.494419Z"
607      }
608     },
609     "outputs": [
610      {
611       "name": "stdout",
612       "output_type": "stream",
613       "text": [
614        "Document not found: sample_document.pdf\n",
615        "Place a test PDF in this directory and update DOCUMENT_PATH to test.\n"
616       ]
617      }
618     ],
619     "source": [
620      "DOCUMENT_PATH = \"sample_document.pdf\"  # Change this\n",
621      "\n",
622      "if Path(DOCUMENT_PATH).exists():\n",
623      "    doc_b64 = base64.b64encode(Path(DOCUMENT_PATH).read_bytes()).decode(\"utf-8\")\n",
624      "    ext = Path(DOCUMENT_PATH).suffix.lstrip(\".\")\n",
625      "    name = Path(DOCUMENT_PATH).stem\n",
626      "\n",
627      "    response = invoke_agent(\n",
628      "        prompt=\"Resume este documento.\",\n",
629      "        media={\"type\": \"document\", \"format\": ext, \"data\": doc_b64, \"name\": name},\n",
630      "    )\n",
631      "    print(response)\n",
632      "else:\n",
633      "    print(f\"Document not found: {DOCUMENT_PATH}\")\n",
634      "    print(\"Place a test PDF in this directory and update DOCUMENT_PATH to test.\")"
635     ]
636    },
637    {
638     "cell_type": "markdown",
639     "id": "qtwbm4kpe7",
640     "metadata": {},
641     "source": [
642      "## 9. Test - Cross-turn Memory\n",
643      "\n",
644      "The agent should recall information from all previous interactions in this session."
645     ]
646    },
647    {
648     "cell_type": "code",
649     "execution_count": 11,
650     "id": "hkrcv3zu2ug",
651     "metadata": {
652      "execution": {
653       "iopub.execute_input": "2026-03-19T02:27:07.498449Z",
654       "iopub.status.busy": "2026-03-19T02:27:07.498133Z",
655       "iopub.status.idle": "2026-03-19T02:27:18.616090Z",
656       "shell.execute_reply": "2026-03-19T02:27:18.613943Z"
657      }
658     },
659     "outputs": [
660      {
661       "name": "stdout",
662       "output_type": "stream",
663       "text": [
664        "## 📝 **Resumen de nuestra conversación:**\n",
665        "\n",
666        "### **👋 Presentaciones iniciales:**\n",
667        "- Te presentaste como **Carlos de Colombia** 🇨🇴\n",
668        "- Te expliqué mis capacidades como asistente de WhatsApp (texto, imágenes, documentos, audio, videos)\n",
669        "\n",
670        "### **🧠 Prueba de memoria:**\n",
671        "- Me preguntaste cómo te llamas y de dónde eres\n",
672        "- Confirmé correctamente: **Carlos de Colombia**\n",
673        "\n",
674        "### **📱 Contenido multimedia analizado:**\n",
675        "\n",
676        "**1️⃣ Imagen (meme tecnológico):**\n",
677        "- Mujer sonriente con fondo dividido rojo/verde\n",
678        "- Lado rojo: errores, bloqueos, símbolos de advertencia\n",
679        "- Lado verde: símbolos de éxito y actualización\n",
680        "- Mensaje: **\"STEER, DON'T BLOCK\"** (redirigir en lugar de bloquear)\n",
681        "\n",
682        "**2️⃣ Audio transcrito:**\n",
683        "- *\"Necesito agendar una reunión para el martes a las 3 de la tarde con el equipo de marketing para hablar de la estrategia del Q4.\"*\n",
684        "- Te ofrecí ayuda para organizar la reunión\n",
685        "\n",
686        "**3️⃣ Video técnico (Amazon Bedrock Agent Runtime):**\n",
687        "- Presentadora explicando cómo desplegar agentes de IA en producción\n",
688        "- **Problema:** Despliegue complejo con Docker, CI/CD, infraestructura\n",
689        "- **Solución:** Amazon Bedrock Agent Runtime con solo 2 comandos\n",
690        "- **Beneficios:** Serverless, escalado automático, infraestructura invisible\n",
691        "- Mensaje clave: **\"INVISIBLE INFRASTRUCTURE\"**\n",
692        "\n",
693        "### **🎯 Temas principales:**\n",
694        "- Tecnología y memes tech\n",
695        "- Organización de reuniones de trabajo\n",
696        "- Despliegue de agentes de IA en producción\n",
697        "\n",
698        "¿Hay algo específico de lo que hemos hablado en lo que te gustaría profundizar más, Carlos?\n",
699        "\n"
700       ]
701      }
702     ],
703     "source": [
704      "# Should recall: name=Carlos, country=Colombia, meeting=Tuesday 3PM marketing Q4\n",
705      "response = invoke_agent(\"Dame un resumen de todo lo que hemos hablado en esta conversacion.\")\n",
706      "print(response)"
707     ]
708    },
709    {
710     "cell_type": "markdown",
711     "id": "ratj2rpiokc",
712     "metadata": {},
713     "source": [
714      "## 10. Test - Check Memory Records (data plane)\n",
715      "\n",
716      "Query the AgentCore Memory directly to inspect what was stored."
717     ]
718    },
719    {
720     "cell_type": "code",
721     "execution_count": 12,
722     "id": "mslgq8jlu1",
723     "metadata": {
724      "execution": {
725       "iopub.execute_input": "2026-03-19T02:27:18.626809Z",
726       "iopub.status.busy": "2026-03-19T02:27:18.626554Z",
727       "iopub.status.idle": "2026-03-19T02:27:18.806313Z",
728       "shell.execute_reply": "2026-03-19T02:27:18.805444Z"
729      }
730     },
731     "outputs": [
732      {
733       "name": "stdout",
734       "output_type": "stream",
735       "text": [
736        "Found 0 memory records:\n",
737        "\n"
738       ]
739      }
740     ],
741     "source": [
742      "# List memory records for our test actor\n",
743      "# namespace = actor_id prefix used by the agent\n",
744      "try:\n",
745      "    records = agentcore.list_memory_records(\n",
746      "        memoryId=MEMORY_ID,\n",
747      "        namespace=ACTOR_ID,\n",
748      "    )\n",
749      "    memory_records = records.get(\"memoryRecords\", records.get(\"records\", []))\n",
750      "    print(f\"Found {len(memory_records)} memory records:\\n\")\n",
751      "    for record in memory_records:\n",
752      "        print(f\"  - Type: {record.get('type', 'N/A')}\")\n",
753      "        content = record.get(\"content\", record.get(\"text\", \"N/A\"))\n",
754      "        print(f\"    Content: {str(content)[:200]}\")\n",
755      "        print()\n",
756      "except Exception as e:\n",
757      "    print(f\"Error querying memory: {e}\")"
758     ]
759    }
760   ],
761   "metadata": {
762    "kernelspec": {
763     "display_name": "Python 3",
764     "language": "python",
765     "name": "python3"
766    },
767    "language_info": {
768     "codemirror_mode": {
769      "name": "ipython",
770      "version": 3
771     },
772     "file_extension": ".py",
773     "mimetype": "text/x-python",
774     "name": "python",
775     "nbconvert_exporter": "python",
776     "pygments_lexer": "ipython3",
777     "version": "3.11.7"
778    }
779   },
780   "nbformat": 4,
781   "nbformat_minor": 5
782  }