test_agentcore_deployed.ipynb
1 { 2 "cells": [ 3 { 4 "cell_type": "markdown", 5 "id": "rkf3pvn7utl", 6 "source": "# Test AgentCore Deployed Runtime\n\nThis notebook tests the **deployed** AgentCore Runtime via `invoke-agent-runtime`.\n\nIt validates:\n1. Text messages through the deployed endpoint\n2. Image processing (base64 encoded)\n3. Audio transcript processing\n4. Video analysis via TwelveLabs Pegasus\n5. Memory persistence across invocations (short-term + long-term)\n\n> **Prerequisites**: The `AgentAgentCoreStack` must be deployed successfully.", 7 "metadata": {} 8 }, 9 { 10 "cell_type": "code", 11 "id": "npkagulzftq", 12 "source": "%pip install boto3 --quiet", 13 "metadata": {}, 14 "execution_count": null, 15 "outputs": [] 16 }, 17 { 18 "cell_type": "code", 19 "id": "6psoan3fp1", 20 "source": "import os\nimport botocore.loaders\nimport botocore.session\n\n# Register the custom 'bedrock-agentcore' service model bundled in the deployment package.\n# The system boto3/botocore does not include this service yet.\nCUSTOM_DATA_PATH = os.path.abspath(\n os.path.join(\n os.path.dirname(\"__file__\"), \"..\",\n \"00-agent-agentcore\", \"agent_files\", \"deployment_package\", \"botocore\", \"data\",\n )\n)\n\ndef agentcore_boto3_session(region: str) -> \"boto3.Session\":\n \"\"\"Create a boto3 Session that knows about the bedrock-agentcore service.\"\"\"\n bcore = botocore.session.get_session()\n loader = botocore.loaders.Loader(\n extra_search_paths=[CUSTOM_DATA_PATH],\n )\n bcore.register_component(\"data_loader\", loader)\n return boto3.Session(botocore_session=bcore, region_name=region)\n\nprint(f\"Custom botocore data path: {CUSTOM_DATA_PATH}\")\nprint(\"Use agentcore_boto3_session() to create clients for 'bedrock-agentcore'.\")", 21 "metadata": {}, 22 "execution_count": null, 23 "outputs": [] 24 }, 25 { 26 "cell_type": "markdown", 27 "id": "v2jzjg49g1", 28 "source": "## 1. Setup - Read stack outputs from SSM", 29 "metadata": {} 30 }, 31 { 32 "cell_type": "code", 33 "id": "qqn1v5531o", 34 "source": "import json\nimport boto3\n\nREGION = \"us-east-1\"\n\nssm = boto3.client(\"ssm\", region_name=REGION)\n\ndef get_param(name):\n return ssm.get_parameter(Name=name)[\"Parameter\"][\"Value\"]\n\nAGENT_RUNTIME_ARN = get_param(\"/agentcore/agent_runtime_arn\")\nS3_BUCKET = get_param(\"/agentcore/s3_bucket_name\")\nMEMORY_ID = get_param(\"/agentcore/memory_id\")\n\n# Extract runtime ID from ARN (last segment after /runtime/)\nAGENT_RUNTIME_ID = AGENT_RUNTIME_ARN.split(\"/\")[-1]\n\nprint(f\"Runtime ARN: {AGENT_RUNTIME_ARN}\")\nprint(f\"Runtime ID: {AGENT_RUNTIME_ID}\")\nprint(f\"Memory ID: {MEMORY_ID}\")\nprint(f\"S3 Bucket: {S3_BUCKET}\")", 35 "metadata": {}, 36 "execution_count": null, 37 "outputs": [] 38 }, 39 { 40 "cell_type": "markdown", 41 "id": "dvudxedlt3m", 42 "source": "## 2. Helper - Invoke Agent Runtime\n\nWraps the `bedrock-agentcore` data plane `invoke-agent-runtime` API.\n\n- `actor_id` identifies the **user** (long-term memory: facts, preferences)\n- `session_id` identifies the **conversation** (short-term memory: turns)", 43 "metadata": {} 44 }, 45 { 46 "cell_type": "code", 47 "id": "gjuacz71oah", 48 "source": "session = agentcore_boto3_session(REGION)\nagentcore = session.client(\"bedrock-agentcore\")\n\n# IDs must be >= 33 chars, padded as the agent expects\nTEST_PHONE = \"5730012345670000000000\"\nACTOR_ID = f\"wa-user-{TEST_PHONE}\".ljust(33, \"0\") # identifies the USER\nSESSION_ID = f\"wa-chat-{TEST_PHONE}\".ljust(33, \"0\") # identifies the CONVERSATION\n\nprint(f\"actor_id: '{ACTOR_ID}' ({len(ACTOR_ID)} chars)\")\nprint(f\"session_id: '{SESSION_ID}' ({len(SESSION_ID)} chars)\")\n\n\ndef invoke_agent(prompt: str, media: dict = None) -> str:\n \"\"\"Invoke the deployed AgentCore Runtime.\n \n Args:\n prompt: User text message.\n media: Optional media dict (type, format, data, s3_uri).\n \n Returns:\n Agent response text.\n \"\"\"\n payload = {\n \"prompt\": prompt,\n \"actor_id\": ACTOR_ID,\n }\n if media:\n payload[\"media\"] = media\n\n response = agentcore.invoke_agent_runtime(\n agentRuntimeArn=AGENT_RUNTIME_ARN,\n runtimeSessionId=SESSION_ID,\n runtimeUserId=ACTOR_ID,\n payload=json.dumps(payload).encode(\"utf-8\"),\n )\n\n content = []\n for chunk in response.get(\"response\", []):\n if isinstance(chunk, bytes):\n content.append(chunk.decode(\"utf-8\"))\n elif isinstance(chunk, dict) and \"bytes\" in chunk:\n content.append(chunk[\"bytes\"].decode(\"utf-8\"))\n\n response_text = \"\".join(content)\n\n try:\n response_json = json.loads(response_text)\n return response_json.get(\"result\", response_text)\n except json.JSONDecodeError:\n return response_text\n\n\nprint(\"\\nHelper ready.\")", 49 "metadata": {}, 50 "execution_count": null, 51 "outputs": [] 52 }, 53 { 54 "cell_type": "markdown", 55 "id": "qd0mjj0p3u9", 56 "source": "## 3. Test - Text Message", 57 "metadata": {} 58 }, 59 { 60 "cell_type": "code", 61 "id": "s47s29w9sr9", 62 "source": "response = invoke_agent(\"Hola! Mi nombre es Carlos y soy de Colombia. Que puedes hacer por mi?\")\nprint(response)", 63 "metadata": {}, 64 "execution_count": null, 65 "outputs": [] 66 }, 67 { 68 "cell_type": "markdown", 69 "id": "aufjgi6uzh5", 70 "source": "## 4. Test - Memory Recall (same session)\n\nThe agent should remember the name and country from the previous turn.", 71 "metadata": {} 72 }, 73 { 74 "cell_type": "code", 75 "id": "fryovfsb9qv", 76 "source": "response = invoke_agent(\"Como me llamo y de donde soy?\")\nprint(response)", 77 "metadata": {}, 78 "execution_count": null, 79 "outputs": [] 80 }, 81 { 82 "cell_type": "markdown", 83 "id": "fvjpvl23lj5", 84 "source": "## 5. Test - Image Processing\n\nSends a base64-encoded image to the agent via the deployed runtime.", 85 "metadata": {} 86 }, 87 { 88 "cell_type": "code", 89 "id": "i0ty1gpxsip", 90 "source": "import base64\nfrom pathlib import Path\n\nIMAGE_PATH = \"imagen2.png\"\n\nif Path(IMAGE_PATH).exists():\n image_b64 = base64.b64encode(Path(IMAGE_PATH).read_bytes()).decode(\"utf-8\")\n ext = Path(IMAGE_PATH).suffix.lstrip(\".\")\n fmt = {\"jpg\": \"jpeg\", \"jpeg\": \"jpeg\", \"png\": \"png\", \"gif\": \"gif\", \"webp\": \"webp\"}.get(ext, \"jpeg\")\n\n response = invoke_agent(\n prompt=\"Describe esta imagen en detalle.\",\n media={\"type\": \"image\", \"format\": fmt, \"data\": image_b64},\n )\n print(response)\nelse:\n print(f\"Image not found: {IMAGE_PATH}\")\n print(\"Place a test image in this directory and update IMAGE_PATH to test.\")", 91 "metadata": {}, 92 "execution_count": null, 93 "outputs": [] 94 }, 95 { 96 "cell_type": "markdown", 97 "id": "2qay65ftlal", 98 "source": "## 6. Test - Audio Transcript", 99 "metadata": {} 100 }, 101 { 102 "cell_type": "code", 103 "id": "dt5qn8xpp3", 104 "source": "response = invoke_agent(\n prompt=\"Procesa este audio\",\n media={\n \"type\": \"audio_transcript\",\n \"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 },\n)\nprint(response)", 105 "metadata": {}, 106 "execution_count": null, 107 "outputs": [] 108 }, 109 { 110 "cell_type": "markdown", 111 "id": "scw6n059u3s", 112 "source": "## 7. Test - Video Analysis (TwelveLabs Pegasus)\n\n> Upload a test video to S3 first and update `VIDEO_S3_URI`.\n> The TwelveLabs Pegasus model (`twelvelabs.pegasus-1-2-v1:0`) must be enabled in Bedrock.", 113 "metadata": {} 114 }, 115 { 116 "cell_type": "code", 117 "id": "i162djhxyp", 118 "source": "# Upload the local video to the stack's S3 bucket\ns3_client = boto3.client(\"s3\", region_name=REGION)\ns3_client.upload_file(\"Runtime.mp4\", S3_BUCKET, \"videos/Runtime.mp4\")\nprint(f\"Uploaded Runtime.mp4 to s3://{S3_BUCKET}/videos/Runtime.mp4\")\n\nVIDEO_S3_URI = f\"s3://{S3_BUCKET}/videos/Runtime.mp4\"\n\nresponse = invoke_agent(\n prompt=\"Analiza este video en detalle.\",\n media={\"type\": \"video\", \"s3_uri\": VIDEO_S3_URI},\n)\nprint(response)", 119 "metadata": {}, 120 "execution_count": null, 121 "outputs": [] 122 }, 123 { 124 "cell_type": "markdown", 125 "id": "f284dasfvn", 126 "source": "## 8. Test - Document Processing\n\n> Place a test PDF in this directory and update `DOCUMENT_PATH`.", 127 "metadata": {} 128 }, 129 { 130 "cell_type": "code", 131 "id": "tfz6pkrexrk", 132 "source": "DOCUMENT_PATH = \"sample_document.pdf\" # Change this\n\nif Path(DOCUMENT_PATH).exists():\n doc_b64 = base64.b64encode(Path(DOCUMENT_PATH).read_bytes()).decode(\"utf-8\")\n ext = Path(DOCUMENT_PATH).suffix.lstrip(\".\")\n name = Path(DOCUMENT_PATH).stem\n\n response = invoke_agent(\n prompt=\"Resume este documento.\",\n media={\"type\": \"document\", \"format\": ext, \"data\": doc_b64, \"name\": name},\n )\n print(response)\nelse:\n print(f\"Document not found: {DOCUMENT_PATH}\")\n print(\"Place a test PDF in this directory and update DOCUMENT_PATH to test.\")", 133 "metadata": {}, 134 "execution_count": null, 135 "outputs": [] 136 }, 137 { 138 "cell_type": "markdown", 139 "id": "qtwbm4kpe7", 140 "source": "## 9. Test - Cross-turn Memory\n\nThe agent should recall information from all previous interactions in this session.", 141 "metadata": {} 142 }, 143 { 144 "cell_type": "code", 145 "id": "hkrcv3zu2ug", 146 "source": "# Should recall: name=Carlos, country=Colombia, meeting=Tuesday 3PM marketing Q4\nresponse = invoke_agent(\"Dame un resumen de todo lo que hemos hablado en esta conversacion.\")\nprint(response)", 147 "metadata": {}, 148 "execution_count": null, 149 "outputs": [] 150 }, 151 { 152 "cell_type": "markdown", 153 "id": "ratj2rpiokc", 154 "source": "## 10. Test - Check Memory Records (data plane)\n\nQuery the AgentCore Memory directly to inspect what was stored.", 155 "metadata": {} 156 }, 157 { 158 "cell_type": "code", 159 "id": "mslgq8jlu1", 160 "source": "# List memory records for our test actor\n# namespace = actor_id prefix used by the agent\ntry:\n records = agentcore.list_memory_records(\n memoryId=MEMORY_ID,\n namespace=ACTOR_ID,\n )\n memory_records = records.get(\"memoryRecords\", records.get(\"records\", []))\n print(f\"Found {len(memory_records)} memory records:\\n\")\n for record in memory_records:\n print(f\" - Type: {record.get('type', 'N/A')}\")\n content = record.get(\"content\", record.get(\"text\", \"N/A\"))\n print(f\" Content: {str(content)[:200]}\")\n print()\nexcept Exception as e:\n print(f\"Error querying memory: {e}\")", 161 "metadata": {}, 162 "execution_count": null, 163 "outputs": [] 164 } 165 ], 166 "metadata": { 167 "kernelspec": { 168 "display_name": "Python 3", 169 "language": "python", 170 "name": "python3" 171 }, 172 "language_info": { 173 "name": "python", 174 "version": "3.11.0" 175 } 176 }, 177 "nbformat": 4, 178 "nbformat_minor": 5 179 }